Skip to content

逻辑回归

尽管名称中带有“回归”,但逻辑回归(Logistic Regression)是一种用于监督学习的基本分类算法。它主要用于预测输入属于特定类别或类别的概率。虽然它可以扩展到多类问题,但其最常见的应用是二元分类,其中目标变量只有两个可能的输出(例如,是/否,真/假,0/1)。

可以想象预测客户是否会点击广告(是/否),或者肿瘤是恶性还是良性(M/B)。逻辑回归对“正”类(通常表示为 1)发生的概率进行建模。

与预测连续值的线性回归不同,逻辑回归使用一个特定的转换函数——逻辑函数(或 Sigmoid 函数)——将任何实数值输入(通常是特征的线性组合)映射到 0 到 1 之间的概率值。

在数学上,它将概率 P(Y=1 | X) 建模为输入特征 X 的函数。

逻辑回归的核心是 Sigmoid 函数:

σ(z) = 1 / (1 + e^(-z))

其中 z 是输入特征和权重的线性组合(类似于线性回归):z = θ₀ + θ₁x₁ + θ₂x₂ + ... + θ<0xE2><0x82><0x99>x<0xE2><0x82><0x99>(或向量表示法中的 z = Xθ)。

Sigmoid 函数将输出 z(范围从 -∞ 到 +∞)压缩到 (0, 1) 范围内。此输出可以解释为正类的估计概率。

为了进行类别预测,我们通常设定一个阈值(通常是 0.5)。如果预测概率 σ(z) 大于或等于阈值,我们将该实例分类为正类(1);否则,将其分类为负类(0)。

为了训练模型(即,找到最优权重 θ),逻辑回归使用一个称为对数损失(Log Loss)(或二元交叉熵,Binary Cross-Entropy)的损失函数。该函数衡量预测概率与训练数据中实际类别标签(0 或 1)的匹配程度。

训练期间的目标是最小化此对数损失函数。这通常使用优化算法实现,如梯度下降(Gradient Descent)或更高级的方法(例如,L-BFGS,在库实现中常用),这些方法会迭代地调整权重 θ 以减少损失。

根据目标类别的数量:

最常见的类型,其中目标变量只有两个可能的输出(例如,0 或 1,垃圾邮件/非垃圾邮件,恶性/良性)。

当目标变量有三个或更多无序(名义)的可能输出时使用,这意味着类别之间没有固有的排序(例如,将新闻文章分类为“体育”、“政治”、“科技”)。它对每个类别的概率进行建模。

当目标变量有三个或更多有序(序数)的可能输出时使用,这意味着类别之间存在有意义的排序(例如,客户满意度评分,如“差”、“好”、“优秀”)。它考虑了排序关系。

Scikit-learn 的 LogisticRegression 类可以直接处理二元和多项情况。

虽然逻辑回归相对稳健,但它依赖于某些假设以获得最佳性能:

  • 二元结果: 对于二元逻辑回归,因变量必须是二元的。
  • 观测独立性: 观测之间应该是相互独立的。
  • 无严重多重共线性: 自变量之间不应高度相关。高度的多重共线性会增加方差,并使系数解释不可靠。
  • 自变量与对数几率的线性关系: 假设自变量与结果的对数几率之间存在线性关系。违反此假设有时可以通过转换变量或添加交互项来解决。
  • 大样本量: 逻辑回归通常需要足够大的样本量才能获得稳定可靠的系数估计。

特征缩放: 虽然不是严格的假设,但如果对特征进行缩放(例如,使用 StandardScaler 或 MinMaxScaler),性能(特别是训练期间的收敛速度)通常会显著提高。

让我们使用 Scikit-learn 实现二元和多项逻辑回归。

1. 二元逻辑回归示例(Iris 数据集)

Section titled “1. 二元逻辑回归示例(Iris 数据集)”

我们将使用 Iris 数据集,但将其修改为二元任务:分类花是“setosa”(类别 0)还是“非 setosa”(类别 1,合并了“versicolor”和“virginica”)。我们只使用前两个特征(花萼长度和宽度),以便于可视化(尽管原始教程的绘图已被移除)。

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# --- Load and Prepare Data ---
iris = load_iris()
# Use only first two features for this example
X = iris.data[:, :2]
# Create binary target: 0 = setosa, 1 = not setosa
y = (iris.target != 0).astype(int)
feature_names = iris.feature_names[:2]
target_names = ['setosa', 'not setosa']
# --- Split Data ---
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)
# --- Scale Features ---
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# --- Train Logistic Regression Model ---
# C is the inverse of regularization strength; smaller values specify stronger regularization.
model_binary = LogisticRegression(C=1.0, random_state=42, solver='liblinear')
model_binary.fit(X_train_scaled, y_train)
# --- Make Predictions ---
y_pred_binary = model_binary.predict(X_test_scaled)
proba_binary = model_binary.predict_proba(X_test_scaled) # Get probabilities
# --- Evaluate Model ---
print("-- Binary Logistic Regression (Iris: Setosa vs. Not Setosa) ---")
accuracy_binary = accuracy_score(y_test, y_pred_binary)
print(f"Accuracy: {accuracy_binary:.4f}")
print("\nConfusion Matrix:")
print(confusion_matrix(y_test, y_pred_binary))
print("\nClassification Report:")
print(classification_report(y_test, y_pred_binary, target_names=target_names))
# print("\nPredicted Probabilities (first 5):\n", proba_binary[:5])
# Description: Shows the probability estimates for each class (setosa, not setosa) for the first 5 test samples.

解释:此代码训练了一个二元逻辑回归模型。它加载 Iris 数据,将目标变量转换为二元形式,分割数据集,缩放特征,训练模型,预测类别和概率,并使用标准指标进行评估。输出显示了高准确率,表明模型能够根据花萼尺寸有效区分 setosa 和其他两个物种。

2. 多项逻辑回归示例(Digits 数据集)

Section titled “2. 多项逻辑回归示例(Digits 数据集)”

现在,让我们使用 Digits 数据集,它有 10 个类别(数字 0-9),这使其成为一个多项分类问题。

import numpy as np
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# --- Load Data ---
digits = load_digits()
X = digits.data
y = digits.target
# --- Split Data ---
# Using a larger test size as in the original example
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=1, stratify=y)
# --- Scale Features ---
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# --- Train Multinomial Logistic Regression Model ---
# Scikit-learn's LogisticRegression handles multinomial automatically
# when multi_class='auto' or 'multinomial' (with appropriate solvers like 'lbfgs')
# Using a solver suitable for multinomial like 'lbfgs'
model_multi = LogisticRegression(multi_class='multinomial', solver='lbfgs', max_iter=5000, random_state=42)
model_multi.fit(X_train_scaled, y_train)
# --- Make Predictions ---
y_pred_multi = model_multi.predict(X_test_scaled)
# --- Evaluate Model ---
print("\n--- Multinomial Logistic Regression (Digits Dataset) ---")
accuracy_multi = accuracy_score(y_test, y_pred_multi)
print(f"Accuracy: {accuracy_multi:.4f}")
# Confusion matrix is larger for multi-class
print("\nConfusion Matrix:")
cm_multi = confusion_matrix(y_test, y_pred_multi)
# print(cm_multi) # Can be large, maybe just print shape or specific parts
print(f"(Confusion Matrix Shape: {cm_multi.shape})")
print("\nClassification Report:")
# Get target names as strings for the report
target_names_digits = [str(i) for i in digits.target_names]
print(classification_report(y_test, y_pred_multi, target_names=target_names_digits))

解释:此代码解决了一个多类问题。它加载 Digits 数据集,分割数据,缩放特征,并训练一个配置为多项分类(multi_class='multinomial',solver='lbfgs')的 LogisticRegression 模型。评估结果显示高准确率,并在分类报告中提供了每个类别的指标(precision, recall, f1-score),展示了模型识别手写数字的有效性。

逻辑回归是一种通用且易于解释的分类算法,可作为出色的基线模型,并且通常在线性可分或接近线性可分的数据上表现良好。其输出的概率在许多应用中也很有价值。

进一步阅读:https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression