引言
逻辑回归(Logistic Regression)是机器学习中经典的二分类算法,虽名为'回归',实则属于分类模型。它凭借简单高效、可解释性强、泛化能力稳定的特点,在工业界(如风控建模、用户转化预测)和学术研究中被广泛应用。本文将从基础概念切入,深入剖析逻辑回归的数学原理、损失函数设计、参数求解过程,再通过 Python 手动实现与 sklearn 库实操验证,补充正则化优化、多分类拓展及实战注意事项,适合机器学习入门者及需要夯实分类算法基础的开发者阅读。
逻辑回归这一经典二分类算法。内容涵盖核心概念、与线性回归的区别、Sigmoid 函数与概率建模、交叉熵损失函数设计及梯度下降参数求解过程。通过 Python 手动实现与 sklearn 库调用对比,展示了代码实践。此外还讨论了正则化(L1/L2/ElasticNet)解决过拟合、One-vs-Rest 与 One-vs-One 多分类策略、优缺点分析及典型应用场景。文章旨在帮助读者掌握逻辑回归的理论与工程落地能力。
逻辑回归(Logistic Regression)是机器学习中经典的二分类算法,虽名为'回归',实则属于分类模型。它凭借简单高效、可解释性强、泛化能力稳定的特点,在工业界(如风控建模、用户转化预测)和学术研究中被广泛应用。本文将从基础概念切入,深入剖析逻辑回归的数学原理、损失函数设计、参数求解过程,再通过 Python 手动实现与 sklearn 库实操验证,补充正则化优化、多分类拓展及实战注意事项,适合机器学习入门者及需要夯实分类算法基础的开发者阅读。
线性回归的核心是拟合自变量与连续因变量的线性关系,输出结果为连续值;而逻辑回归针对分类问题,输出结果是样本属于某一类别的概率(范围 0~1),再通过阈值判断类别。两者的核心差异如下:
| 对比维度 | 线性回归 | 逻辑回归 |
|---|---|---|
| 模型类型 | 回归模型(无监督) | 分类模型(监督学习) |
| 输出范围 | $(-\infty, +\infty)$ 连续值 | $[0, 1]$ 概率值 |
| 损失函数 | 均方误差(MSE) | 交叉熵损失(Cross-Entropy) |
| 适用场景 | 预测连续值(如房价、销量) | 二分类/多分类(如风控、垃圾邮件识别) |
逻辑回归的核心是'将线性回归的输出映射到$[0,1]$区间,转化为分类概率'。具体步骤:
通过 Sigmoid 函数将线性输出 $z$ 映射为概率 $p$,表示样本属于正类的概率;
先构建自变量的线性组合:
$$z = w_0 + w_1x_1 + w_2x_2 + ... + w_dx_d = w^Tx$$
(其中 $w_0$ 为偏置项,$w$ 为权重向量,$x$ 为特征向量);
Sigmoid 函数(也叫 Logistic 函数)是逻辑回归的核心激活函数,其作用是将线性输出 $z$(范围$(-\infty, +\infty)$)压缩到$[0,1]$区间,满足概率的取值要求。
$$\sigma(z) = \frac{1}{1 + e^{-z}}$$
import numpy as np
import matplotlib.pyplot as plt
# 定义 Sigmoid 函数
def sigmoid(z):
return 1 / (1 + np.exp(-z))
# 生成 z 值并计算对应的 sigmoid 结果
z = np.linspace(-10, 10, 1000)
sigma_z = sigmoid(z)
# 可视化
plt.figure(figsize=(8, 5))
plt.plot(z, sigma_z, 'b-', linewidth=2)
plt.axvline(x=0, color='k', linestyle='--', alpha=0.5) # z=0 辅助线
plt.axhline(y=0.5, color='k', linestyle='--', alpha=0.5) # 概率 0.5 辅助线
plt.xlabel('z = w^Tx')
plt.ylabel('$\sigma(z)$ (Probability)')
plt.title('Sigmoid Function')
plt.grid(True, alpha=0.3)
plt.show()
逻辑回归通过 Sigmoid 函数构建样本属于正类(记为 1)和负类(记为 0)的概率模型:
负类概率:
$$P(y=0|x;w) = 1 - \sigma(w^Tx) = \frac{e^{-w^Tx}}{1 + e^{-w^Tx}}$$
正类概率:
$$P(y=1|x;w) = \sigma(w^Tx) = \frac{1}{1 + e^{-w^Tx}}$$
将两式合并为统一形式(似然函数的基础):
$$P(y|x;w) = [\sigma(w^Tx)]^y \cdot [1 - \sigma(w^Tx)]^{1-y}$$
类别判定规则:设定阈值 $threshold$(默认 0.5),若 $P(y=1|x;w) \ge threshold$,则预测为正类(y=1),否则为负类(y=0)。阈值可根据业务需求调整(如风控场景需提高正类阈值以降低误判率)。
逻辑回归无法直接使用线性回归的均方误差(MSE)作为损失函数——因为 Sigmoid 函数与 MSE 结合后,损失函数是非凸的,存在多个局部最小值,无法通过梯度下降找到全局最优解。因此,逻辑回归采用交叉熵损失函数(Cross-Entropy Loss),确保损失函数为凸函数,梯度下降可收敛到全局最优。
对于单个样本 $(x_i, y_i)$,损失函数定义为:
$$L(w; x_i, y_i) = -y_i \log(\sigma(w^Tx_i)) - (1 - y_i) \log(1 - \sigma(w^Tx_i))$$
解读:
全局损失为所有样本损失的平均值(也可求和,不影响梯度方向):
$$J(w) = \frac{1}{n} \sum_{i=1}^{n} \left[ -y_i \log(\sigma(w^Tx_i)) - (1 - y_i) \log(1 - \sigma(w^Tx_i)) \right]$$
逻辑回归的目标是最小化全局损失函数 $J(w)$,求解最优权重 $w$。
逻辑回归通过梯度下降法最小化损失函数,核心是计算损失函数对权重 $w$ 的梯度,再沿梯度负方向更新权重。
对全局损失函数 $J(w)$ 求关于权重 $w_j$ 的偏导数(以单个特征权重为例):
$$\nabla_w J(w) = \frac{1}{n} X^T (\sigma(Xw) - y)$$
其中 $X$ 为 $n \times (d+1)$ 特征矩阵(含偏置项 $x_0=1$),$y$ 为 $n \times 1$ 标签向量,$\sigma(Xw)$ 为 $n \times 1$ 预测概率向量。
代入 Sigmoid 函数导数特性 $\sigma'(z) = \sigma(z)(1 - \sigma(z))$,结合链式法则推导:
权重更新公式为($\alpha$ 为学习率,控制步长):
$$w = w - \alpha \cdot \nabla_w J(w) = w - \alpha \cdot \frac{1}{n} X^T (\sigma(Xw) - y)$$
迭代更新权重,直到梯度的绝对值小于预设阈值(收敛),或达到最大迭代次数,停止迭代并输出最优权重 $w$。
以鸢尾花数据集(二分类任务,取前两类)为例,分别实现手动逻辑回归与 sklearn 库调用,验证模型效果。
pip install numpy pandas matplotlib scikit-learn
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 1. 数据加载与预处理(二分类任务)
iris = load_iris()
X = iris.data[:, :2] # 取前 2 个特征,便于可视化
y = iris.target # 筛选前两类(y=0 和 y=1),转为二分类问题
mask = (y == 0) | (y == 1)
X = X[mask]
y = y[mask]
# 标准化(逻辑回归对量纲敏感,必须预处理)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 添加偏置项 x0=1(特征矩阵首列全为 1)
X_scaled = np.hstack([np.ones((X_scaled.shape[0], 1)), X_scaled])
# 划分训练集与测试集
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.3, random_state=42
)
# 2. 定义逻辑回归类(梯度下降实现)
class LogisticRegressionManual:
def __init__(self, learning_rate=0.01, max_iter=1000, tol=1e-4):
self.lr = learning_rate # 学习率
self.max_iter = max_iter # 最大迭代次数
self.tol = tol # 收敛阈值
self.w = None # 权重参数(含偏置项)
# Sigmoid 函数
def sigmoid(self, z):
# 避免指数溢出:z 过大时 e^-z 趋近于 0,z 过小时 e^-z 趋近于 +∞
z = np.clip(z, -100, 100)
return 1 / (1 + np.exp(-z))
# 训练模型
def fit(self, X, y):
n_samples, n_features = X.shape
self.w = np.zeros(n_features) # 初始化权重为 0
for _ in range(self.max_iter):
# 计算线性输出 z 和预测概率
z = np.dot(X, self.w)
y_pred_prob = self.sigmoid(z)
# 计算梯度
gradient = np.dot(X.T, (y_pred_prob - y)) / n_samples
# 判断收敛(梯度绝对值最大值小于阈值)
if np.max(np.abs(gradient)) < self.tol:
break
# 更新权重
self.w -= self.lr * gradient
# 预测(返回类别标签)
def predict(self, X):
z = np.dot(X, self.w)
y_pred_prob = self.sigmoid(z)
return np.where(y_pred_prob >= 0.5, 1, 0)
# 3. 训练与评估
lr_manual = LogisticRegressionManual(learning_rate=0.1, max_iter=2000)
lr_manual.fit(X_train, y_train)
y_pred_manual = lr_manual.predict(X_test)
# 计算准确率
acc_manual = accuracy_score(y_test, y_pred_manual)
print(f"手动实现逻辑回归准确率:{acc_manual:.4f}")
print(f"最优权重(含偏置项):{lr_manual.w}")
# 4. 可视化决策边界
plt.figure(figsize=(8, 6))
# 绘制样本点
plt.scatter(X_test[:, 1], X_test[:, 2], c=y_test, cmap='viridis', edgecolors='black', label='True Label')
# 绘制决策边界 (z=w0 + w1x1 + w2x2 = 0 → x2 = -(w0 + w1x1)/w2)
x1 = np.linspace(X_test[:, 1].min(), X_test[:, 1].max(), 100)
x2 = -(lr_manual.w[0] + lr_manual.w[1] * x1) / lr_manual.w[2]
plt.plot(x1, x2, 'r-', label='Decision Boundary')
plt.xlabel('Feature 1 (Standardized)')
plt.ylabel('Feature 2 (Standardized)')
plt.title('Logistic Regression (Manual Implementation)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
sklearn 的 LogisticRegression 类内置正则化、多分类支持、自适应求解器,适合实际项目使用,默认采用 L2 正则化和 liblinear 求解器。
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, confusion_matrix
# 1. 数据预处理(同上,无需手动添加偏置项,sklearn 自动处理)
# X_train、X_test、y_train、y_test 已在手动实现中定义
# 2. 初始化并训练模型(指定二分类,关闭正则化便于对比手动结果)
lr_sklearn = LogisticRegression(
penalty='none', # 关闭正则化
solver='liblinear', # 适合小样本二分类
random_state=42
)
lr_sklearn.fit(X_train[:, 1:], y_train) # 去掉手动添加的偏置项(sklearn 自动处理)
# 3. 预测与评估
y_pred_sklearn = lr_sklearn.predict(X_test[:, 1:])
acc_sklearn = accuracy_score(y_test, y_pred_sklearn)
# 输出详细评估指标
print(f"sklearn 逻辑回归准确率:{acc_sklearn:.4f}")
print("分类报告:")
print(classification_report(y_test, y_pred_sklearn))
print("混淆矩阵:")
print(confusion_matrix(y_test, y_pred_sklearn))
# 输出模型参数(系数 + 偏置项)
print(f"特征系数:{lr_sklearn.coef_}")
print(f"偏置项:{lr_sklearn.intercept_}")
# 4. 可视化决策边界(与手动实现对比)
plt.figure(figsize=(8, 6))
plt.scatter(X_test[:, 1], X_test[:, 2], c=y_test, cmap='viridis', edgecolors='black', label='True Label')
# 决策边界: w0 + w1x1 + w2x2 = 0 → x2 = -(w0 + w1x1)/w2
x1 = np.linspace(X_test[:, 1].min(), X_test[:, 1].max(), 100)
x2 = -(lr_sklearn.intercept_[0] + lr_sklearn.coef_[0][0] * x1) / lr_sklearn.coef_[0][1]
plt.plot(x1, x2, 'r-', label='Decision Boundary')
plt.xlabel('Feature 1 (Standardized)')
plt.ylabel('Feature 2 (Standardized)')
plt.title('Logistic Regression (sklearn Implementation)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
结果说明:手动实现与 sklearn 实现的准确率基本一致(接近 1.0,因鸢尾花数据集前两类特征可分性强),权重参数也大致相同,验证了手动推导的正确性。
当特征维度过高或样本量较小时,逻辑回归易出现过拟合(训练集准确率高,测试集准确率低)。正则化通过对权重施加惩罚,限制权重绝对值过大,从而降低模型复杂度,缓解过拟合。
在损失函数中添加权重绝对值之和的惩罚项,可实现特征选择(使部分权重变为 0):
$$J(w) = \text{Cross-Entropy Loss} + \lambda \sum_{j=1}^{d} |w_j|$$
适用场景:特征维度高、存在冗余特征时。
在损失函数中添加权重平方和的惩罚项,使权重趋于平缓,不具备特征选择能力:
$$J(w) = \text{Cross-Entropy Loss} + \frac{\lambda}{2} \sum_{j=1}^{d} w_j^2$$
适用场景:大多数常规场景,是逻辑回归的默认正则化方式。
结合 L1 和 L2 正则化的优点,适合特征冗余且需保留部分关键特征的场景:
$$J(w) = \text{Cross-Entropy Loss} + \lambda_1 \sum_{j=1}^{d} |w_j| + \frac{\lambda_2}{2} \sum_{j=1}^{d} w_j^2$$
# L1 正则化示例
lr_l1 = LogisticRegression(
penalty='l1', # L1 正则化
solver='liblinear', # L1 正则化需搭配 liblinear 求解器
C=0.1, # 正则化强度倒数(C 越小,正则化越强)
random_state=42
)
lr_l1.fit(X_train[:, 1:], y_train)
# L2 正则化示例(默认)
lr_l2 = LogisticRegression(
penalty='l2', # L2 正则化
solver='liblinear',
C=0.1,
random_state=42
)
lr_l2.fit(X_train[:, 1:], y_train)
# 对比权重(L1 会使部分权重趋近于 0)
print("L1 正则化权重:", lr_l1.coef_)
print("L2 正则化权重:", lr_l2.coef_)
逻辑回归本质是二分类模型,通过'拆解为多个二分类任务'实现多分类,sklearn 支持两种多分类策略:
核心思想:将每个类别视为正类,其余所有类别视为负类,训练 K 个二分类逻辑回归模型(K 为类别数);预测时,选择概率最大的模型对应的类别作为结果。
优点:简单高效,适合类别数较多的场景;缺点:对不平衡数据敏感。
核心思想:每两个类别构建一个二分类模型,共训练 $$C(K,2) = \frac{K(K-1)}{2}$$ 个模型;预测时,通过投票确定最终类别(被预测为正类次数最多的类别获胜)。
优点:对不平衡数据鲁棒性强;缺点:模型数量多,计算成本高,适合类别数较少的场景。
# 使用完整鸢尾花数据集(3 分类)
X_full = iris.data
y_full = iris.target
X_full_scaled = scaler.fit_transform(X_full)
X_train_full, X_test_full, y_train_full, y_test_full = train_test_split(
X_full_scaled, y_full, test_size=0.3, random_state=42
)
# OvR 策略(默认)
lr_ovr = LogisticRegression(
multi_class='ovr', # 多分类策略:OvR
solver='liblinear',
random_state=42
)
lr_ovr.fit(X_train_full, y_train_full)
y_pred_ovr = lr_ovr.predict(X_test_full)
# OvO 策略
lr_ovo = LogisticRegression(
multi_class='multinomial', # 多分类策略: OvO
solver='lbfgs', # 需搭配 lbfgs/sag/saga 求解器
random_state=42
)
lr_ovo.fit(X_train_full, y_train_full)
y_pred_ovo = lr_ovo.predict(X_test_full)
# 评估
print("OvR 准确率:", accuracy_score(y_test_full, y_pred_ovr))
print("OvO 准确率:", accuracy_score(y_test_full, y_pred_ovo))
逻辑回归是机器学习分类算法的'入门基石',其核心是通过 Sigmoid 函数将线性输出转化为概率,结合交叉熵损失与梯度下降求解最优参数。它虽结构简单,但可解释性和工程实用性极强,是工业界首选的基线模型。
针对逻辑回归的线性局限,可拓展学习以下算法:
希望本文能帮助大家夯实逻辑回归的理论基础与工程实践能力,在实际项目中灵活运用并优化模型。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online