跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

逻辑回归算法详解:原理、代码与可视化

逻辑回归算法的原理、训练机制及代码实现。通过高尔夫数据集示例,演示了从数据预处理、模型训练到预测评估的全过程。内容涵盖 Sigmoid 函数、梯度下降优化、关键参数(惩罚项、C 值)的影响,并对比了手动实现与 sklearn 库的使用。文章还分析了该算法的优缺点,适合初学者掌握二元分类任务中的概率预测方法。

PgDevote发布于 2026/3/22更新于 2026/8/2312K 浏览

分类算法

找到适合数据的最佳权重

尽管一些基于概率的机器学习模型(如朴素贝叶斯)对特征独立性做出大胆假设,但逻辑回归采用了更为谨慎的方法。可以把它看作是绘制一条(或一平面)将两种结果分开的线,这样我们就可以以更大的灵活性预测概率。

定义

逻辑回归是一种用于预测二元结果的统计方法。尽管名字中有'回归',但它实际上用于分类而非回归。它估计实例属于某个特定类别的概率。如果估计的概率大于 50%,模型预测该实例属于该类别(反之亦然)。

使用的数据集

在本文中,我们将使用一个人工高尔夫数据集作为示例。该数据集根据天气条件预测一个人是否会打高尔夫。

与 KNN 类似,逻辑回归也要求先对数据进行缩放。将类别列转换为 0 和 1,同时缩放数值特征,以避免某一特征主导距离度量。

列:'Outlook'(天气状况)、'Temperature'(温度)、'Humidity'(湿度)、'Wind'(风速)和'Play'(目标特征)。类别列(Outlook 和 Windy)使用独热编码(one-hot encoding)进行编码,而数值列则使用标准缩放(z-标准化)进行缩放。

# Import required libraries
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import StandardScaler
import pandas as pd
import numpy as np

# Create dataset from dictionary
dataset_dict = {
    'Outlook': ['sunny', 'sunny', 'overcast', 'rainy', 'rainy', 'rainy', 'overcast', 'sunny', 'sunny', 'rainy', 'sunny', 'overcast', 'overcast', 'rainy', 'sunny', 'overcast', 'rainy', 'sunny', 'sunny', 'rainy', 'overcast', 'rainy', 'sunny', 'overcast', 'sunny', 'overcast', 'rainy', 'overcast'],
    'Temperature': [85.0, 80.0, 83.0, 70.0, 68.0, 65.0, 64.0, 72.0, 69.0, 75.0, 75.0, 72.0, 81.0, 71.0, 81.0, 74.0, 76.0, 78.0, 82.0, 67.0, 85.0, 73.0, 88.0, 77.0, 79.0, 80.0, 66.0, 84.0],
    'Humidity': [85.0, 90.0, 78.0, 96.0, 80.0, 70.0, 65.0, 95.0, 70.0, 80.0, 70.0, 90.0, 75.0, 80.0, 88.0, 92.0, 85.0, 75.0, 92.0, 90.0, 85.0, 88.0, 65.0, 70.0, 60.0, 95.0, 70.0, 78.0],
    'Wind': [False, True, False, False, False, True, True, False, False, False, True, True, False, True, True, False, False, True, False, True, True, False, True, False, False, True, False, False],
    'Play': ['No', 'No', 'Yes', 'Yes', 'Yes', 'No', 'Yes', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'Yes', 'No', 'No', 'Yes', 'Yes', 'No', 'No', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'Yes', 'Yes', 'No', 'Yes']
}
df = pd.DataFrame(dataset_dict)

# Prepare data: encode categorical variables
df = pd.get_dummies(df, columns=['Outlook'], prefix='', prefix_sep='', dtype=int)
df['Wind'] = df['Wind'].astype(int)
df['Play'] = (df['Play'] == 'Yes').astype(int)

# Rearrange columns
column_order = ['sunny', 'overcast', 'rainy', 'Temperature', 'Humidity', 'Wind', 'Play']
df = df[column_order]

# Split data into features and target
X, y = df.drop(columns='Play'), df['Play']

# Split data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.5, shuffle=False)

# Scale numerical features
scaler = StandardScaler()
X_train[['Temperature', 'Humidity']] = scaler.fit_transform(X_train[['Temperature', 'Humidity']])
X_test[['Temperature', 'Humidity']] = scaler.transform(X_test[['Temperature', 'Humidity']])

# Print results
print("Training set:")
print(pd.concat([X_train, y_train], axis=1), '\n')
print("Test set:")
print(pd.concat([X_test, y_test], axis=1))

主要机制

逻辑回归通过对输入特征的线性组合应用逻辑函数来工作。其操作过程如下:

  1. 计算输入特征的加权和(类似于线性回归)。
  2. 对这个和应用逻辑函数(也称为 Sigmoid 函数),它将任何实数映射到 0 和 1 之间的值。
  3. 将此值解释为属于正类的概率。
  4. 使用阈值(通常是 0.5)做出最终的分类决策。

对于我们的高尔夫数据集,逻辑回归可能会将天气因素合并为一个单一的分数,然后将此分数转换为打高尔夫的概率。

训练步骤

逻辑回归的训练过程涉及为输入特征找到最佳的权重。以下是一般的步骤概述:

  1. 初始化权重(通常为小的随机值)。
# Initialize weights (including bias) to 0.1
initial_weights = np.full(X_train_np.shape[1], 0.1)
# Create and display DataFrame for initial weights
print(f"Initial Weights: {initial_weights}")
  1. 对于每个训练示例: a. 使用当前的权重计算预测概率。
def sigmoid(z):
    return 1 / (1 + np.exp(-z))

def calculate_probabilities(X, weights):
    z = np.dot(X, weights)
    return sigmoid(z)

def calculate_log_loss(probabilities, y):
    return -y * np.log(probabilities) - (1 - y) * np.log(1 - probabilities)

def create_output_dataframe(X, y, weights):
    probabilities = calculate_probabilities(X, weights)
    log_losses = calculate_log_loss(probabilities, y)
    df = pd.DataFrame({'Probability': probabilities, 'Label': y, 'Log Loss': log_losses})
    return df

def calculate_average_log_loss(X, y, weights):
    probabilities = calculate_probabilities(X, weights)
    log_losses = calculate_log_loss(probabilities, y)
    return np.mean(log_losses)

# Convert X_train and y_train to numpy arrays for easier computation
X_train_np = X_train.to_numpy()
y_train_np = y_train.to_numpy()

# Add a column of 1s to X_train_np for the bias term
X_train_np = np.column_stack((np.ones(X_train_np.shape[0]), X_train_np))

# Create and display DataFrame for initial weights
initial_df = create_output_dataframe(X_train_np, y_train_np, initial_weights)
print(initial_df.to_string(index=False, float_format=lambda x: f"{x:.6f}"))
print(f"\nAverage Log Loss: {calculate_average_log_loss(X_train_np, y_train_np, initial_weights):.6f}")

b. 通过计算其对数损失,将该概率与实际类别标签进行比较。

  1. 更新权重以最小化损失(通常使用一些优化算法,如梯度下降。这包括反复进行步骤 2,直到对数损失无法进一步减小)。
def gradient_descent_step(X, y, weights, learning_rate):
    m = len(y)
    probabilities = calculate_probabilities(X, weights)
    gradient = np.dot(X.T, (probabilities - y)) / m
    new_weights = weights - learning_rate * gradient
    # Create new array for updated weights
    return new_weights

# Perform one step of gradient descent (one of the simplest optimization algorithm)
learning_rate = 0.1
updated_weights = gradient_descent_step(X_train_np, y_train_np, initial_weights, learning_rate)

# Print initial and updated weights
print("\nInitial weights:")
for feature, weight in zip(['Bias'] + list(X_train.columns), initial_weights):
    print(f"{feature:11}: {weight:.2f}")

print("\nUpdated weights after one iteration:")
for feature, weight in zip(['Bias'] + list(X_train.columns), updated_weights):
    print(f"{feature:11}: {weight:.2f}")
# With sklearn, you can get the final weights (coefficients) and final bias (intercepts) easily.
# The result is almost the same as doing it manually above.
from sklearn.linear_model import LogisticRegression
lr_clf = LogisticRegression(penalty=None, solver='saga')
lr_clf.fit(X_train, y_train)
coefficients = lr_clf.coef_
intercept = lr_clf.intercept_
y_train_prob = lr_clf.predict_proba(X_train)[:, 1]
loss = -np.mean(y_train * np.log(y_train_prob) + (1 - y_train) * np.log(1 - y_train_prob))
print(f"Weights & Bias Final: {coefficients[0].round(2)}, {round(intercept[0], 2)}")
print("Loss Final:", loss.round(3))

分类步骤

一旦模型训练完成:

  1. 对于新实例,使用最终权重(也称为系数)计算概率,就像训练步骤中一样。
  2. 通过查看概率来解释输出:如果 p ≥ 0.5,预测为类别 1;否则,预测为类别 0。
# Calculate prediction probability
predicted_probs = lr_clf.predict_proba(X_test)[:, 1]
z_values = np.log(predicted_probs / (1 - predicted_probs))
result_df = pd.DataFrame({
    'ID': X_test.index,
    'Z-Values': z_values.round(3),
    'Probabilities': predicted_probs.round(3)
}).set_index('ID')
print(result_df)

# Make predictions
y_pred = lr_clf.predict(X_test)
print(y_pred)

评估步骤

result_df = pd.DataFrame({
    'ID': X_test.index,
    'Label': y_test,
    'Probabilities': predicted_probs.round(2),
    'Prediction': y_pred,
}).set_index('ID')
print(result_df)

关键参数

逻辑回归有几个重要的参数来控制其行为:

1. 惩罚项:使用的正则化类型('l1','l2','elasticnet' 或 'none')。逻辑回归中的正则化通过在模型的损失函数中加入惩罚项,防止过拟合,并鼓励简化模型。

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
regs = [None, 'l1', 'l2']
coeff_dict = {}
for reg in regs:
    lr_clf = LogisticRegression(penalty=reg, solver='saga')
    lr_clf.fit(X_train, y_train)
    coefficients = lr_clf.coef_
    intercept = lr_clf.intercept_
    predicted_probs = lr_clf.predict_proba(X_train)[:, 1]
    loss = -np.mean(y_train * np.log(predicted_probs) + (1 - y_train) * np.log(1 - predicted_probs))
    predictions = lr_clf.predict(X_test)
    accuracy = accuracy_score(y_test, predictions)
    coeff_dict[reg] = {'Coefficients': coefficients, 'Intercept': intercept, 'Loss': loss, 'Accuracy': accuracy}

for reg, vals in coeff_dict.items():
    print(f"{reg}: Coeff: {vals['Coefficients'][0].round(2)}, Intercept: {vals['Intercept'].round(2)}, Loss: {vals['Loss'].round(3)}, Accuracy: {vals['Accuracy'].round(3)}")

2. 正则化强度(C):控制拟合训练数据与保持模型简洁之间的权衡。较小的 C 意味着更强的正则化。

# List of regularization strengths to try for L1
strengths = [0.001, 0.01, 0.1, 1, 10, 100]
coeff_dict = {}
for strength in strengths:
    lr_clf = LogisticRegression(penalty='l1', C=strength, solver='saga')
    lr_clf.fit(X_train, y_train)
    coefficients = lr_clf.coef_
    intercept = lr_clf.intercept_
    predicted_probs = lr_clf.predict_proba(X_train)[:, 1]
    loss = -np.mean(y_train * np.log(predicted_probs) + (1 - y_train) * np.log(1 - predicted_probs))
    predictions = lr_clf.predict(X_test)
    accuracy = accuracy_score(y_test, predictions)
    coeff_dict[f'L1_{strength}'] = {
        'Coefficients': coefficients[0].round(2),
        'Intercept': round(intercept[0], 2),
        'Loss': round(loss, 3),
        'Accuracy': round(accuracy * 100, 2)
    }
print(pd.DataFrame(coeff_dict).T)
# List of regularization strengths to try for L2
strengths = [0.001, 0.01, 0.1, 1, 10, 100]
coeff_dict = {}
for strength in strengths:
    lr_clf = LogisticRegression(penalty='l2', C=strength, solver='saga')
    lr_clf.fit(X_train, y_train)
    coefficients = lr_clf.coef_
    intercept = lr_clf.intercept_
    predicted_probs = lr_clf.predict_proba(X_train)[:, 1]
    loss = -np.mean(y_train * np.log(predicted_probs) + (1 - y_train) * np.log(1 - predicted_probs))
    predictions = lr_clf.predict(X_test)
    accuracy = accuracy_score(y_test, predictions)
    coeff_dict[f'L2_{strength}'] = {
        'Coefficients': coefficients[0].round(2),
        'Intercept': round(intercept[0], 2),
        'Loss': round(loss, 3),
        'Accuracy': round(accuracy * 100, 2)
    }
print(pd.DataFrame(coeff_dict).T)

3. 求解器:用于优化的算法('liblinear','newton-cg','lbfgs','sag','saga')。某些正则化可能需要特定的算法。

4. 最大迭代次数:求解器收敛的最大迭代次数。

对于我们的高尔夫数据集,我们可能以'l2'惩罚项、'liblinear'求解器和 C=1.0 作为基准进行尝试。

优点与缺点

像机器学习中的任何算法一样,逻辑回归也有其优点和局限性。

优点:

  1. 简单性:易于实现和理解。
  2. 可解释性:权重直接显示每个特征的重要性。
  3. 效率:不需要过多的计算能力。
  4. 概率输出:提供概率而不仅仅是分类。

缺点:

  1. 线性假设:假设特征与结果的对数几率之间存在线性关系。
  2. 特征独立性:假设特征之间没有高度相关性。
  3. 有限的复杂性:在决策边界高度非线性的情况下,可能出现欠拟合。
  4. 需要更多数据:需要相对较大的样本量以获得稳定的结果。

在我们的高尔夫示例中,逻辑回归可能提供一个清晰、可解释的模型,说明每个天气因素如何影响打高尔夫的决策。然而,如果决策涉及天气条件之间的复杂交互,无法通过线性模型捕捉,那么它可能会遇到困难。

最后备注

逻辑回归作为一种强大而简洁的分类工具脱颖而出。它的优势在于能够处理复杂数据的同时保持易于解释。与一些其他基础模型不同,它提供平滑的概率估计,并且能很好地处理多个特征。在现实世界中,从预测客户行为到医学诊断,逻辑回归往往表现出惊人的效果。它不仅仅是一个过渡工具——它是一个可靠的模型,在许多情况下能与更复杂的模型匹敌。

逻辑回归代码总结

# Import required libraries
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score

# Load the dataset
dataset_dict = {
    'Outlook': ['sunny', 'sunny', 'overcast', 'rainy', 'rainy', 'rainy', 'overcast', 'sunny', 'sunny', 'rainy', 'sunny', 'overcast', 'overcast', 'rainy', 'sunny', 'overcast', 'rainy', 'sunny', 'sunny', 'rainy', 'overcast', 'rainy', 'sunny', 'overcast', 'sunny', 'overcast', 'rainy', 'overcast'],
    'Temperature': [85.0, 80.0, 83.0, 70.0, 68.0, 65.0, 64.0, 72.0, 69.0, 75.0, 75.0, 72.0, 81.0, 71.0, 81.0, 74.0, 76.0, 78.0, 82.0, 67.0, 85.0, 73.0, 88.0, 77.0, 79.0, 80.0, 66.0, 84.0],
    'Humidity': [85.0, 90.0, 78.0, 96.0, 80.0, 70.0, 65.0, 95.0, 70.0, 80.0, 70.0, 90.0, 75.0, 80.0, 88.0, 92.0, 85.0, 75.0, 92.0, 90.0, 85.0, 88.0, 65.0, 70.0, 60.0, 95.0, 70.0, 78.0],
    'Wind': [False, True, False, False, False, True, True, False, False, False, True, True, False, True, True, False, False, True, False, True, True, False, True, False, False, True, False, False],
    'Play': ['No', 'No', 'Yes', 'Yes', 'Yes', 'No', 'Yes', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'Yes', 'No', 'No', 'Yes', 'Yes', 'No', 'No', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'Yes', 'Yes', 'No', 'Yes']
}
df = pd.DataFrame(dataset_dict)

# Prepare data: encode categorical variables
df = pd.get_dummies(df, columns=['Outlook'], prefix='', prefix_sep='', dtype=int)
df['Wind'] = df['Wind'].astype(int)
df['Play'] = (df['Play'] == 'Yes').astype(int)

# Split data into training and testing sets
X, y = df.drop(columns='Play'), df['Play']
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.5, shuffle=False)

# Scale numerical features
scaler = StandardScaler()
float_cols = X_train.select_dtypes(include=['float64']).columns
X_train[float_cols] = scaler.fit_transform(X_train[float_cols])
X_test[float_cols] = scaler.transform(X_test[float_cols])

# Train the model
lr_clf = LogisticRegression(penalty='l2', C=1, solver='saga')
lr_clf.fit(X_train, y_train)

# Make predictions
y_pred = lr_clf.predict(X_test)

# Evaluate the model
print(f"Accuracy: {accuracy_score(y_test, y_pred)}")

关于 scikit-learn 中的 LogisticRegression 实现,读者可以参考官方文档,该文档提供了关于其使用和参数的全面信息。

目录

  1. 分类算法
  2. 找到适合数据的最佳权重
  3. 定义
  4. 使用的数据集
  5. Import required libraries
  6. Create dataset from dictionary
  7. Prepare data: encode categorical variables
  8. Rearrange columns
  9. Split data into features and target
  10. Split data into training and testing sets
  11. Scale numerical features
  12. Print results
  13. 主要机制
  14. 训练步骤
  15. Initialize weights (including bias) to 0.1
  16. Create and display DataFrame for initial weights
  17. Convert Xtrain and ytrain to numpy arrays for easier computation
  18. Add a column of 1s to Xtrainnp for the bias term
  19. Create and display DataFrame for initial weights
  20. Perform one step of gradient descent (one of the simplest optimization algorithm)
  21. Print initial and updated weights
  22. With sklearn, you can get the final weights (coefficients) and final bias (intercepts) easily.
  23. The result is almost the same as doing it manually above.
  24. 分类步骤
  25. Calculate prediction probability
  26. Make predictions
  27. 评估步骤
  28. 关键参数
  29. List of regularization strengths to try for L1
  30. List of regularization strengths to try for L2
  31. 优点与缺点
  32. 优点:
  33. 缺点:
  34. 最后备注
  35. 逻辑回归代码总结
  36. Import required libraries
  37. Load the dataset
  38. Prepare data: encode categorical variables
  39. Split data into training and testing sets
  40. Scale numerical features
  41. Train the model
  42. Make predictions
  43. Evaluate the model
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Jenkins 自动化部署教程
  • 从 ReAct 到 Plan-and-Execute:AI Agent 推理架构的理解与选择
  • 支持国内股票分析的 AI 开源项目精选与实战指南
  • 大模型分布式训练与 LoRA/LISA 微调技术详解
  • C++ 协程深度解析:从内部机制到实用场景
  • DeepSeek-R1 大模型基于 MS-Swift 框架的部署、推理与微调实践
  • Spatial Joy 2025 全球 AR&AI 赛事:资源、玩法及避坑攻略
  • LangChain 架构演进与功能扩展:流式事件处理、事件过滤及回调策略
  • Python Web UI 自动化测试:推送本地代码到 Git 远程仓库
  • 电商 AI 绘画:产品提示词撰写实战指南
  • Stable Diffusion XL 提示词增强工具:SDXL Prompt Styler 使用指南
  • MaxClaw:Go 语言实现的本地优先 AI 智能体平台
  • 基于 C++11 手写 Promise 实现
  • AI 原生应用开发:知识图谱七大核心算法
  • ERNIE-4.5-0.3B 轻量模型部署指南与性能测评
  • Vue3 核心语法与状态管理学习笔记
  • 基于 SpringBoot 的高校图书馆借阅管理系统设计与实现
  • 深入解析潜在扩散模型(LDMs)架构与原理
  • YOLO12 WebUI:上传图片即时目标检测
  • OpenClaw Session 机制完全指南:重置、压缩、剪枝与记忆管理

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online