逻辑回归:从原理到代码实现的完整指南
一、逻辑回归的起源与发展
逻辑回归作为一种经典的分类算法,其发展历程可追溯至 20 世纪。1934 年,统计学家 Joseph Berkson 首次提出了逻辑回归的雏形,当时主要用于解决医学领域的二分类问题。在随后的几十年里,经过众多统计学家的不断完善和拓展,逻辑回归逐渐成为统计学和机器学习领域中不可或缺的重要工具。
20 世纪 70 年代,随着计算机技术的兴起,逻辑回归的应用范围得到了极大的扩展。它不再局限于医学领域,开始在社会学、经济学、生物学等多个学科中发挥重要作用。例如,在经济学中,可用于预测企业的破产风险;在社会学中,可用于分析影响人们投票行为的因素等。
进入 21 世纪,随着大数据时代的来临,逻辑回归凭借其简单高效、易于解释等优点,在机器学习领域中依然占据着重要的地位。尽管出现了许多复杂的深度学习算法,但在很多实际场景中,逻辑回归仍然是首选的分类算法之一。
二、逻辑回归的基本概念
(一)逻辑回归的定义
逻辑回归(Logistic Regression)是一种用于解决二分类问题的统计学习方法。它通过建立一个回归模型来预测某个事件发生的概率,其输出值是一个介于 0 和 1 之间的概率值,根据这个概率值可以将样本分为两类。
与线性回归不同,逻辑回归的因变量是离散的,而线性回归的因变量是连续的。逻辑回归的核心思想是将线性回归的输出通过一个非线性函数(即 Sigmoid 函数)映射到 [0,1] 区间,从而得到样本属于某一类别的概率。
(二)逻辑回归与线性回归的区别
- 因变量类型不同:线性回归的因变量是连续变量,而逻辑回归的因变量是离散变量(通常是二分类变量)。
- 模型输出不同:线性回归的输出是一个连续的值,而逻辑回归的输出是样本属于某一类别的概率,取值范围在 [0,1] 之间。
- 假设条件不同:线性回归假设因变量与自变量之间存在线性关系,且误差项服从正态分布;而逻辑回归没有这样的假设,它通过 Sigmoid 函数将线性关系转化为非线性关系。
- 应用场景不同:线性回归主要用于预测连续变量的值,如房价预测、销售额预测等;而逻辑回归主要用于解决二分类问题,如垃圾邮件识别、疾病诊断等。
三、逻辑回归的数学原理
(一)Sigmoid 函数
Sigmoid 函数是逻辑回归中非常重要的一个函数,它的数学表达式为:
\(g(z) = \frac{1}{1 + e^{-z}}\)
其中,\(z\)是线性回归的输出,即\(z = w^Tx + b\),\(w\)是权重向量,\(x\)是输入特征向量,\(b\)是偏置项。
Sigmoid 函数的图像是一个 S 形曲线,当\(z\)趋近于正无穷时,\(g(z)\)趋近于 1;当\(z\)趋近于负无穷时,\(g(z)\)趋近于 0;当\(z = 0\)时,\(g(z) = 0.5\)。这一特性使得 Sigmoid 函数能够将线性回归的输出映射到 [0,1] 区间,从而得到样本属于某一类别的概率。
(二)逻辑回归模型
逻辑回归模型的数学表达式为:
\(P(y=1|x) = g(w^Tx + b) = \frac{1}{1 + e^{-(w^Tx + b)}}\)
\(P(y=0|x) = 1 - P(y=1|x) = \frac{e^{-(w^Tx + b)}}{1 + e^{-(w^Tx + b)}}\)
其中,\(P(y=1|x)\)表示在给定输入特征\(x\)的情况下,样本属于类别 1 的概率;\(P(y=0|x)\)表示样本属于类别 0 的概率。
为了方便计算,我们可以将上述两个式子合并为:
\(P(y|x;w,b) = [P(y=1|x;w,b)]^y [P(y=0|x;w,b)]^{1-y}\)
(三)损失函数
在逻辑回归中,我们需要通过训练数据来估计模型的参数\(w\)和\(b\)。常用的参数估计方法是最大似然估计法,即找到一组参数\(w\)和\(b\),使得在这组参数下,训练数据出现的概率最大。
似然函数的表达式为:
\(L(w,b) = \prod_{i=1}^{m} P(y_i|x_i;w,b) = \prod_{i=1}^{m} [g(w^Tx_i + b)]^{y_i} [1 - g(w^Tx_i + b)]^{1 - y_i}\)
为了便于计算,我们通常对似然函数取对数,得到对数似然函数:
\(l(w,b) = \ln L(w,b) = \sum_{i=1}^{m} [y_i \ln g(w^Tx_i + b) + (1 - y_i) \ln (1 - g(w^Tx_i + b))]\)
我们的目标是最大化对数似然函数,即找到\(w\)和\(b\)使得\(l(w,b)\)最大。为了将最大化问题转化为最小化问题,我们可以定义损失函数为对数似然函数的相反数:
\(J(w,b) = - \frac{1}{m} l(w,b) = - \frac{1}{m} \sum_{i=1}^{m} [y_i \ln g(w^Tx_i + b) + (1 - y_i) \ln (1 - g(w^Tx_i + b))]\)
(四)参数求解
在逻辑回归中,通常使用梯度下降法来求解损失函数的最小值,从而得到模型的参数\(w\)和\(b\)。梯度下降法的基本思想是沿着损失函数的负梯度方向不断更新参数,直到损失函数收敛到最小值。
损失函数\(J(w,b)\)对\(w\)和\(b\)的偏导数分别为:
\(\frac{\partial J(w,b)}{\partial w_j} = \frac{1}{m} \sum_{i=1}^{m} (g(w^Tx_i + b) - y_i) x_{ij}\)
\(\frac{\partial J(w,b)}{\partial b} = \frac{1}{m} \sum_{i=1}^{m} (g(w^Tx_i + b) - y_i)\)
其中,\(x_{ij}\)表示第\(i\)个样本的第\(j\)个特征。
根据梯度下降法的更新规则,参数\(w\)和\(b\)的更新公式为:
\(w_j = w_j - \alpha \frac{\partial J(w,b)}{\partial w_j}\)
\(b = b - \alpha \frac{\partial J(w,b)}{\partial b}\)
其中,\(\alpha\)是学习率,它决定了每次参数更新的步长。学习率的选择非常重要,如果学习率过大,可能会导致参数在最小值附近震荡;如果学习率过小,可能会导致收敛速度过慢。
四、逻辑回归的算法优化
(一)正则化
在逻辑回归中,当模型的参数过多或训练数据过少时,容易出现过拟合现象。过拟合会导致模型在训练数据上表现良好,但在测试数据上表现不佳。为了避免过拟合,我们可以采用正则化的方法。
正则化的基本思想是在损失函数中加入一个正则项,用于惩罚过大的参数值,从而限制模型的复杂度。常用的正则化方法有 L1 正则化和 L2 正则化。
- L1 正则化
L1 正则化的损失函数表达式为:
\(J(w,b) = - \frac{1}{m} \sum_{i=1}^{m} [y_i \ln g(w^Tx_i + b) + (1 - y_i) \ln (1 - g(w^Tx_i + b))] + \lambda \sum_{j=1}^{n} |w_j|\)
其中,\(\lambda\)是正则化参数,它控制了正则项的权重。\(\lambda\)越大,对参数的惩罚越重,模型的复杂度越低。
L1 正则化会使得部分参数的值变为 0,从而实现特征选择的功能。这对于处理高维数据非常有用,可以减少特征的数量,提高模型的泛化能力。
- L2 正则化
L2 正则化的损失函数表达式为:
\(J(w,b) = - \frac{1}{m} \sum_{i=1}^{m} [y_i \ln g(w^Tx_i + b) + (1 - y_i) \ln (1 - g(w^Tx_i + b))] + \lambda \sum_{j=1}^{n} w_j^2\)
L2 正则化不会使得参数的值变为 0,而是会使得参数的值都比较小。它可以有效地防止模型过拟合,提高模型的泛化能力。
在实际应用中,我们可以根据具体问题选择合适的正则化方法。如果需要进行特征选择,通常选择 L1 正则化;如果只是为了防止过拟合,通常选择 L2 正则化。
(二)梯度下降法的改进
除了基本的梯度下降法外,还有一些改进的梯度下降法可以提高逻辑回归的训练效率和收敛速度,如随机梯度下降法(SGD)、批量梯度下降法(BGD)和小批量梯度下降法(MBGD)。
- 随机梯度下降法(SGD)
随机梯度下降法每次只使用一个样本进行参数更新,其更新公式为:
\(w_j = w_j - \alpha (g(w^Tx_i + b) - y_i) x_{ij}\)
\(b = b - \alpha (g(w^Tx_i + b) - y_i)\)
随机梯度下降法的优点是训练速度快,适用于大规模数据集;缺点是参数更新的波动较大,可能会在最小值附近震荡,收敛速度较慢。
- 批量梯度下降法(BGD)
批量梯度下降法每次使用所有样本进行参数更新,其更新公式与基本的梯度下降法相同。批量梯度下降法的优点是参数更新稳定,收敛速度快;缺点是训练速度慢,适用于小规模数据集。
- 小批量梯度下降法(MBGD)
小批量梯度下降法每次使用一小部分样本进行参数更新,其更新公式为:
\(w_j = w_j - \alpha \frac{1}{k} \sum_{i=1}^{k} (g(w^Tx_i + b) - y_i) x_{ij}\)
\(b = b - \alpha \frac{1}{k} \sum_{i=1}^{k} (g(w^Tx_i + b) - y_i)\)
其中,\(k\)是小批量样本的数量。小批量梯度下降法结合了随机梯度下降法和批量梯度下降法的优点,既具有较快的训练速度,又具有较稳定的参数更新,是实际应用中常用的梯度下降法。
五、逻辑回归的评估指标
在逻辑回归中,我们需要使用一些评估指标来衡量模型的性能。常用的评估指标包括准确率(Accuracy)、精确率(Precision)、召回率(Recall)、F1 值(F1-Score)和 ROC 曲线(Receiver Operating Characteristic Curve)与 AUC 值(Area Under the Curve)。
(一)准确率(Accuracy)
准确率是指分类正确的样本数占总样本数的比例,其计算公式为:
\(Accuracy = \frac{TP + TN}{TP + TN + FP + FN}\)
其中,\(TP\)表示真正例(实际为正类,预测为正类),\(TN\)表示真负例(实际为负类,预测为负类),\(FP\)表示假正例(实际为负类,预测为正类),\(FN\)表示假负例(实际为正类,预测为负类)。
准确率是一个简单直观的评估指标,但它在不平衡数据集上的表现可能不佳。例如,在一个包含 99% 负类样本和 1% 正类样本的数据集上,一个简单地将所有样本都预测为负类的模型,其准确率可以达到 99%,但这并不是一个好的模型。
(二)精确率(Precision)
精确率是指在预测为正类的样本中,真正为正类的样本数所占的比例,其计算公式为:
\(Precision = \frac{TP}{TP + FP}\)
精确率主要用于衡量模型预测正类的准确性,适用于对假正例敏感的场景,如垃圾邮件识别中,我们希望尽可能少地将正常邮件误判为垃圾邮件。
(三)召回率(Recall)
召回率是指在实际为正类的样本中,被预测为正类的样本数所占的比例,其计算公式为:
\(Recall = \frac{TP}{TP + FN}\)
召回率主要用于衡量模型对正类样本的识别能力,适用于对假负例敏感的场景,如疾病诊断中,我们希望尽可能多地识别出患有疾病的患者。
(四)F1 值(F1-Score)
F1 值是精确率和召回率的调和平均数,其计算公式为:
\(F1 - Score = 2 \times \frac{Precision \times Recall}{Precision + Recall}\)
F1 值综合考虑了精确率和召回率,能够较好地反映模型的整体性能。F1 值的取值范围在 [0,1] 之间,F1 值越接近 1,说明模型的性能越好。
(五)ROC 曲线与 AUC 值
ROC 曲线是以假正例率(FPR)为横轴,真正例率(TPR)为纵轴绘制的曲线。其中,假正例率的计算公式为:
\(FPR = \frac{FP}{FP + TN}\)
真正例率的计算公式为:
\(TPR = \frac{TP}{TP + FN}\)
ROC 曲线能够直观地反映模型在不同阈值下的性能。理想情况下,ROC 曲线应该尽可能地靠近左上角,即具有较高的 TPR 和较低的 FPR。
AUC 值是 ROC 曲线下的面积,其取值范围在 [0,1] 之间。AUC 值越接近 1,说明模型的性能越好;AUC 值为 0.5 时,说明模型的性能与随机猜测相当。
六、逻辑回归的代码案例
(一)数据集介绍
本次代码案例使用的是鸢尾花数据集(Iris Dataset)的一个子集,我们只选取其中的两个类别(山鸢尾和变色鸢尾),将其作为二分类问题来解决。鸢尾花数据集包含了 150 个样本,每个样本有 4 个特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度)和一个类别标签。
(二)代码实现
- 导入所需的库
python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
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, precision_score, recall_score, f1_score, roc_curve, auc
- 加载数据集并进行预处理
# 加载鸢尾花数据集
python
iris = load_iris()
X = iris.data
y = iris.target
# 只选取两个类别(0和1)
X = X[y != 2]
y = y[y != 2]
# 划分训练集和测试集
python
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 数据标准化
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
- 构建逻辑回归模型并进行训练
# 构建逻辑回归模型
model = LogisticRegression()
# 训练模型
model.fit(X_train, y_train)
- 模型预测与评估
python
# 模型预测
y_pred = model.predict(X_test)
y_pred_proba = model.predict_proba(X_test)[:, 1]
# 计算评估指标
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
print("准确率:", accuracy)
print("精确率:", precision)
print("召回率:", recall)
print("F1值:", f1)
# 绘制ROC曲线并计算AUC值
fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba)
roc_auc = auc(fpr, tpr)
plt.figure()
plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic')
plt.legend(loc="lower right")
plt.show()
- 结果分析
从上述代码的运行结果可以看出,我们构建的逻辑回归模型在测试集上的准确率、精确率、召回率和 F