逻辑斯蒂回归(Logistic Regression)算法

一、概念

逻辑斯蒂回归(简称Logistic回归)是一种监督学习算法 ,虽然名字含"回归",但实际用于分类任务 (尤其适用于二分类)。其核心思想是:通过一个Sigmoid函数将线性回归的输出(连续值)映射到0-1之间,得到样本属于某一类别的概率,再根据概率进行分类决策。

逻辑斯蒂回归是参数模型(需要估计模型参数),属于线性分类器(决策边界是线性的),广泛应用于垃圾邮件识别、疾病预测、用户流失分析等场景。

二、核心理论

逻辑斯蒂回归的工作流程可概括为3步:

  1. 线性组合 :对输入特征 xxx 进行线性加权,得到 z=w⋅x+bz = w \cdot x + bz=w⋅x+b(www 为权重向量,bbb 为偏置项)。
  2. 概率映射 :通过Sigmoid函数将 zzz 映射到 (0,1)(0,1)(0,1) 区间,得到样本属于正类(如类别1)的概率 P(Y=1∣x)P(Y=1|x)P(Y=1∣x)。
  3. 分类决策 :若 P(Y=1∣x)≥0.5P(Y=1|x) \geq 0.5P(Y=1∣x)≥0.5,预测为正类;否则预测为负类(阈值0.5可根据业务调整)。

关键理论基础

  • Sigmoid函数:解决线性回归输出范围无界的问题,其值域严格在(0,1)之间,适合表示概率。
  • 对数几率 :Sigmoid的反函数是"对数几率"(log⁡P1−P\log\frac{P}{1-P}log1−PP),逻辑斯蒂回归本质是通过线性模型拟合"对数几率",因此也称为"对数几率回归"。
  • 损失函数 :采用交叉熵损失(而非平方损失),因为交叉熵对参数是凸函数,可通过梯度下降高效优化;而平方损失在分类场景下是非凸的,易陷入局部最优。
三、数学公式
1. Sigmoid函数

将线性输出 zzz 映射为概率的函数:
σ(z)=11+e−z \sigma(z) = \frac{1}{1 + e^{-z}} σ(z)=1+e−z1

其中 z=w⋅x+b=w1x1+w2x2+...+wdxd+bz = w \cdot x + b = w_1x_1 + w_2x_2 + ... + w_dx_d + bz=w⋅x+b=w1x1+w2x2+...+wdxd+b(ddd 为特征维度)。

Sigmoid函数的性质:

  • 值域:(0,1)(0,1)(0,1),适合表示概率;
  • 导数:σ′(z)=σ(z)⋅(1−σ(z))\sigma'(z) = \sigma(z) \cdot (1 - \sigma(z))σ′(z)=σ(z)⋅(1−σ(z))(推导中会用到,简化计算);
  • 单调性:随 zzz 增大单调递增,当 z=0z=0z=0 时,σ(z)=0.5\sigma(z)=0.5σ(z)=0.5。
2. 概率表示

设样本 xxx 属于正类(Y=1Y=1Y=1)的概率为 PPP,负类(Y=0Y=0Y=0)的概率为 1−P1-P1−P,则:
P(Y=1∣x)=σ(w⋅x+b)=11+e−(w⋅x+b) P(Y=1|x) = \sigma(w \cdot x + b) = \frac{1}{1 + e^{-(w \cdot x + b)}} P(Y=1∣x)=σ(w⋅x+b)=1+e−(w⋅x+b)1
P(Y=0∣x)=1−σ(w⋅x+b)=e−(w⋅x+b)1+e−(w⋅x+b) P(Y=0|x) = 1 - \sigma(w \cdot x + b) = \frac{e^{-(w \cdot x + b)}}{1 + e^{-(w \cdot x + b)}} P(Y=0∣x)=1−σ(w⋅x+b)=1+e−(w⋅x+b)e−(w⋅x+b)

3. 对数几率(Log Odds)

对概率取"对数几率"(正类概率与负类概率的比值的对数):
log⁡(P(Y=1∣x)P(Y=0∣x))=w⋅x+b \log\left( \frac{P(Y=1|x)}{P(Y=0|x)} \right) = w \cdot x + b log(P(Y=0∣x)P(Y=1∣x))=w⋅x+b

可见,逻辑斯蒂回归本质是用线性模型拟合"对数几率",这也是其"回归"名称的由来。

4. 损失函数(交叉熵损失)

对于 nnn 个样本 {(x1,y1),(x2,y2),...,(xn,yn)}\{(x_1,y_1), (x_2,y_2), ..., (x_n,y_n)\}{(x1,y1),(x2,y2),...,(xn,yn)}(yi∈{0,1}y_i \in \{0,1\}yi∈{0,1}),损失函数定义为:
L(w,b)=−1n∑i=1n[yilog⁡(Pi)+(1−yi)log⁡(1−Pi)] L(w,b) = -\frac{1}{n} \sum_{i=1}^n \left[ y_i \log(P_i) + (1 - y_i) \log(1 - P_i) \right] L(w,b)=−n1i=1∑n[yilog(Pi)+(1−yi)log(1−Pi)]

其中 Pi=P(Y=1∣xi)=σ(w⋅xi+b)P_i = P(Y=1|x_i) = \sigma(w \cdot x_i + b)Pi=P(Y=1∣xi)=σ(w⋅xi+b)。

损失函数的意义:当 yi=1y_i=1yi=1 时,若 PiP_iPi 接近1,损失接近0;若 PiP_iPi 接近0,损失趋近于无穷大(惩罚错误预测)。

四、推导过程(参数求解)

目标:通过梯度下降法 最小化损失函数 L(w,b)L(w,b)L(w,b),求解最优参数 www 和 bbb。

1. 简化参数表示

为方便计算,将偏置项 bbb 纳入权重向量 www(令 w0=bw_0 = bw0=b,x0=1x_0 = 1x0=1),则 z=w⋅xz = w \cdot xz=w⋅x(www 为 (d+1)(d+1)(d+1) 维,xxx 为 (d+1)(d+1)(d+1) 维,含 x0=1x_0=1x0=1)。此时 Pi=σ(w⋅xi)P_i = \sigma(w \cdot x_i)Pi=σ(w⋅xi)。

2. 计算损失函数对参数的偏导数

对单个样本 iii,损失项为 li=−[yilog⁡(Pi)+(1−yi)log⁡(1−Pi)]l_i = -[y_i \log(P_i) + (1 - y_i) \log(1 - P_i)]li=−[yilog(Pi)+(1−yi)log(1−Pi)],总损失 L=1n∑liL = \frac{1}{n}\sum l_iL=n1∑li。

求 lil_ili 对 wjw_jwj(第 jjj 个权重)的偏导数:
∂li∂wj=−[yi⋅1Pi⋅∂Pi∂wj+(1−yi)⋅11−Pi⋅(−∂Pi∂wj)] \frac{\partial l_i}{\partial w_j} = -\left[ y_i \cdot \frac{1}{P_i} \cdot \frac{\partial P_i}{\partial w_j} + (1 - y_i) \cdot \frac{1}{1 - P_i} \cdot \left( -\frac{\partial P_i}{\partial w_j} \right) \right] ∂wj∂li=−[yi⋅Pi1⋅∂wj∂Pi+(1−yi)⋅1−Pi1⋅(−∂wj∂Pi)]

利用Sigmoid导数性质 ∂Pi∂wj=Pi(1−Pi)⋅xij\frac{\partial P_i}{\partial w_j} = P_i (1 - P_i) \cdot x_{ij}∂wj∂Pi=Pi(1−Pi)⋅xij(xijx_{ij}xij 为样本 iii 的第 jjj 个特征),代入上式:
∂li∂wj=−[yi(1−Pi)xij−(1−yi)Pixij]=−[yi−Pi]xij \frac{\partial l_i}{\partial w_j} = -\left[ y_i (1 - P_i) x_{ij} - (1 - y_i) P_i x_{ij} \right] = -\left[ y_i - P_i \right] x_{ij} ∂wj∂li=−[yi(1−Pi)xij−(1−yi)Pixij]=−[yi−Pi]xij

因此,总损失对 wjw_jwj 的偏导数为:
∂L∂wj=1n∑i=1n∂li∂wj=1n∑i=1n(Pi−yi)xij \frac{\partial L}{\partial w_j} = \frac{1}{n} \sum_{i=1}^n \frac{\partial l_i}{\partial w_j} = \frac{1}{n} \sum_{i=1}^n (P_i - y_i) x_{ij} ∂wj∂L=n1i=1∑n∂wj∂li=n1i=1∑n(Pi−yi)xij

3. 梯度下降更新参数

参数更新公式(α\alphaα 为学习率):
wj=wj−α⋅∂L∂wj=wj−α⋅1n∑i=1n(Pi−yi)xij w_j = w_j - \alpha \cdot \frac{\partial L}{\partial w_j} = w_j - \alpha \cdot \frac{1}{n} \sum_{i=1}^n (P_i - y_i) x_{ij} wj=wj−α⋅∂wj∂L=wj−α⋅n1i=1∑n(Pi−yi)xij

重复迭代上述更新过程,直到损失函数收敛(变化小于阈值)或达到最大迭代次数。

五、Python实现(二分类逻辑斯蒂回归)
python 复制代码
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification
from sklearn.metrics import accuracy_score

class LogisticRegression:
    def __init__(self, learning_rate=0.01, n_iterations=1000):
        self.learning_rate = learning_rate  # 学习率
        self.n_iterations = n_iterations    # 迭代次数
        self.weights = None                 # 权重
        self.bias = None                    # 偏置

    def _sigmoid(self, z):
        # 防止指数溢出(z过大时e^-z接近0,过小则接近无穷)
        return 1 / (1 + np.exp(-np.clip(z, -250, 250)))

    def fit(self, X, y):
        n_samples, n_features = X.shape
        # 初始化参数
        self.weights = np.zeros(n_features)
        self.bias = 0

        # 梯度下降迭代
        for _ in range(self.n_iterations):
            # 线性输出 z = w·x + b
            z = np.dot(X, self.weights) + self.bias
            # 概率 P = sigmoid(z)
            y_pred_proba = self._sigmoid(z)

            # 计算梯度(批量梯度下降)
            dw = (1 / n_samples) * np.dot(X.T, (y_pred_proba - y))  # 权重梯度
            db = (1 / n_samples) * np.sum(y_pred_proba - y)          # 偏置梯度

            # 更新参数
            self.weights -= self.learning_rate * dw
            self.bias -= self.learning_rate * db

    def predict_proba(self, X):
        # 预测正类概率
        z = np.dot(X, self.weights) + self.bias
        return self._sigmoid(z)

    def predict(self, X, threshold=0.5):
        # 根据概率预测类别(默认阈值0.5)
        y_pred_proba = self.predict_proba(X)
        return (y_pred_proba >= threshold).astype(int)


# 测试代码
if __name__ == "__main__":
    # 生成二分类模拟数据
    X, y = make_classification(n_samples=1000, n_features=10, n_classes=2, random_state=42)
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

    # 训练模型
    model = LogisticRegression(learning_rate=0.01, n_iterations=1000)
    model.fit(X_train, y_train)

    # 预测与评估
    y_pred = model.predict(X_test)
    accuracy = accuracy_score(y_test, y_pred)
    print(f"自定义逻辑斯蒂回归准确率:{accuracy:.4f}")  # 约 0.89-0.93
六、sklearn实现

sklearn的 LogisticRegression 支持二分类和多分类(通过 multi_class 参数),并提供正则化(L1、L2等)防止过拟合。

示例(乳腺癌分类数据集)
python 复制代码
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 加载数据集(二分类:良性/恶性肿瘤)
data = load_breast_cancer()
X, y = data.data, data.target  # 30维特征

# 拆分数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 初始化模型(L2正则化,学习率自适应的solver)
model = LogisticRegression(max_iter=10000, penalty='l2', solver='lbfgs', random_state=42)

# 训练
model.fit(X_train, y_train)

# 预测
y_pred = model.predict(X_test)
y_pred_proba = model.predict_proba(X_test)  # 输出每个类别的概率

# 评估
accuracy = accuracy_score(y_test, y_pred)
print(f"sklearn逻辑斯蒂回归准确率:{accuracy:.4f}")  # 约 0.97-0.98
七、总结
  • 优点:输出为概率,可解释性强(权重反映特征重要性);训练高效(凸优化问题);适合作为基线模型。
  • 缺点:仅能捕捉线性关系(需手动构造非线性特征);对异常值敏感;高维数据下可能过拟合(需正则化)。
  • 适用场景:二分类任务(如风险评估、点击率预测)、多分类(通过One-vs-Rest或Softmax)。
相关推荐
SunnyKriSmile7 小时前
C语言译码操作
c语言·算法·if语句·译码操作·switch语句
小小小CTFER7 小时前
理论题] 2025 年 “技耀泉城” 海右技能人才大赛网络安全知识竞赛题目(二)
算法·安全·web安全
断剑zou天涯9 小时前
【算法笔记】暴力递归尝试
java·笔记·算法
油泼辣子多加10 小时前
【实战】自然语言处理--长文本分类(1)DPCNN算法
算法·自然语言处理·分类
I'm a winner10 小时前
基于YOLO算法的医疗应用专题:第一章 计算机视觉与深度学习概述
算法·yolo·计算机视觉
vir0211 小时前
P1928 外星密码(dfs)
java·数据结构·算法·深度优先·1024程序员节
喜欢吃燃面11 小时前
数据结构算法题:list
开发语言·c++·学习·算法·1024程序员节
寂静山林11 小时前
UVa 12991 Game Rooms
算法·1024程序员节