深度学习中的逻辑回归:从原理到Python实现

逻辑回归概述

逻辑回归是用于解决二分类问题 的经典算法,尽管名称含"回归",实为分类模型。其核心思想是通过线性组合加非线性变换,将输入特征映射到[0,1]区间,表示样本属于正类的概率:

z = w T x + b z = \mathbf{w}^T \mathbf{x} + b z=wTx+b
y ^ = σ ( z ) = 1 1 + e − z \hat{y} = \sigma(z) = \frac{1}{1 + e^{-z}} y^=σ(z)=1+e−z1

其中 σ ( z ) \sigma(z) σ(z)为sigmoid函数,其特性如下:
输入特征 x 线性变换 z = w·x + b Sigmoid激活函数 概率输出 ŷ = σ(z)

sigmoid函数
计算示例

逻辑回归损失函数

损失函数 用域名衡量预测结构与真实值之间的误差。最简单的损失函数定义方式为平方差损失:
L ( y ^ , y ) = 1 2 ( y ^ − y ) 2 L(\hat{y},y)=\frac {1}{2}(\hat{y}-y)^2 L(y^,y)=21(y^−y)2

逻辑回归 一般使用 : L ( y ^ , y ) = − ( y l o g y ^ ) − ( 1 − y ) l o g ( 1 − y ^ ) L(\hat{y},y)=-(ylog\hat{y})-(1-y)log(1-\hat{y}) L(y^,y)=−(ylogy^)−(1−y)log(1−y^)

该式子的理解:

  • 如何 y = 1 y=1 y=1,损失为 − l o g y ^ -log\hat{y} −logy^,那么要想损失越小, h a t y hat{y} haty的值必须越大,即越趋近于或者等于1
  • 如果 y = 0 y=0 y=0,损失为 − l o g ( 1 − y ^ ) -log(1-\hat{y}) −log(1−y^),那么要想损失越小,那么 y ^ \hat{y} y^的值越小,即趋近于或者等于0

损失函数是在单个训练样本中定义的,它衡量了在单个训练样本上的表现。代价函数衡量的是在全体训练样本上的表现,即衡量参数 w w w和 b b b的效果,所以训练样本的损失平均值 为:
J ( w , b ) = 1 m Σ i = 1 m L ( y ^ ( i ) , y ( i ) ) J(w,b)=\frac {1}{m}\Sigma_{i=1}^{m}L(\hat{y}^{(i)},y^{(i)}) J(w,b)=m1Σi=1mL(y^(i),y(i))

梯度下降算法


梯度下降图示

可以看到,成本函数 J J J是一个凸函数 ,包含多个局部最低。

通过最小化损失函数来优化参数 w \mathbf{w} w和 b b b:
w : = w − α ∂ J ∂ w \mathbf{w} := \mathbf{w} - \alpha \frac{\partial J}{\partial \mathbf{w}} w:=w−α∂w∂J
b : = b − α ∂ J ∂ b b := b - \alpha \frac{\partial J}{\partial b} b:=b−α∂b∂J

其中 α \alpha α表示学习速率,即每次更新的 w w w的步伐长度。当 w w w大于最优解 w ′ w^{'} w′时,导数大于0,那么 w w w就会向更小的方向更新。反之当 w w w小于最优解 w ′ w^{'} w′时,导数小于0,那么 w w w就会向更大的方向更新。迭代直到收敛。

向量化梯度计算

向量化梯度计算原理

在逻辑回归中,向量化梯度计算的核心思想是使用矩阵运算替代循环操作,大幅提升计算效率。其数学基础是:

给定:

  • 特征矩阵 X ∈ R m × n X \in \mathbb{R}^{m \times n} X∈Rm×n(m个样本,n个特征)
  • 参数向量 w ∈ R n w \in \mathbb{R}^{n} w∈Rn
  • 偏置 b ∈ R b \in \mathbb{R} b∈R
  • 预测值 y ^ = σ ( X w + b ) \hat{y} = \sigma(Xw + b) y^=σ(Xw+b)
  • 真实标签 y ∈ R m y \in \mathbb{R}^{m} y∈Rm

梯度计算可向量化为:
∇ w J = 1 m X T ( y ^ − y ) \nabla_w J = \frac{1}{m} X^T (\hat{y} - y) ∇wJ=m1XT(y^−y)
∇ b J = 1 m ∑ i = 1 m ( y ^ ( i ) − y ( i ) ) \nabla_b J = \frac{1}{m} \sum_{i=1}^{m} (\hat{y}^{(i)} - y^{(i)}) ∇bJ=m1i=1∑m(y^(i)−y(i))

优势对比

方法 时间复杂度 代码简洁性 计算效率
循环迭代 O ( m × n ) O(m \times n) O(m×n)
向量化 O ( 1 ) O(1) O(1) 矩阵运算 高(加速10-100倍)

伪代码实现

复制代码
# 输入:特征矩阵X,标签y,参数w,偏置b,样本数m
# 输出:权重梯度dw,偏置梯度db

前向传播:
  Z = X · w + b        # 矩阵乘法 (m×n)·(n×1) = (m×1)
  Y_hat = sigmoid(Z)   # 元素级sigmoid函数

计算梯度:
  error = Y_hat - y    # 预测误差 (m×1)
  dw = (1/m) * (Xᵀ · error)  # (n×m)·(m×1) = (n×1)
  db = (1/m) * sum(error)    # 标量

简单示例说明

假设我们有3个样本和2个特征:

输入数据

复制代码
X = [[2, 3],   # 样本1
     [1, 4],   # 样本2
     [3, 1]]   # 样本3
     
y = [1, 0, 1]   # 真实标签

w = [0.5, -0.2] # 初始权重
b = 0.1         # 初始偏置

计算步骤

  1. 前向传播(向量化):

    复制代码
    Z = X·w + b = [[2*0.5 + 3*(-0.2) + 0.1],
                  [1*0.5 + 4*(-0.2) + 0.1],
                  [3*0.5 + 1*(-0.2) + 0.1]]
         = [0.5, -0.2, 1.4]
         
    Y_hat = sigmoid(Z) ≈ [0.622, 0.450, 0.802]
  2. 计算误差:

    复制代码
    error = Y_hat - y = [0.622-1, 0.450-0, 0.802-1]
                    = [-0.378, 0.450, -0.198]
  3. 向量化梯度计算:

    复制代码
    dw = (1/3) * Xᵀ · error
       = (1/3) * [[2, 1, 3],   # X转置
                  [3, 4, 1]] ·  [[-0.378],
                                 [ 0.450],
                                 [-0.198]]
       = (1/3) * [[2*(-0.378) + 1*0.450 + 3*(-0.198)],
                  [3*(-0.378) + 4*0.450 + 1*(-0.198)]]
       = (1/3) * [[-0.756 + 0.450 - 0.594],
                  [-1.134 + 1.800 - 0.198]]
       = (1/3) * [[-0.900], [0.468]]
       ≈ [[-0.300], [0.156]]
    
    db = (1/3) * sum(error)
       = (1/3) * (-0.378 + 0.450 - 0.198)
       = (1/3) * (-0.126)
       = -0.042

Python实现对比

循环实现(低效)
python 复制代码
def compute_gradients_loop(X, y, w, b):
    m, n = X.shape
    dw = np.zeros(n)
    db = 0
    
    for i in range(m):
        z_i = np.dot(X[i], w) + b
        a_i = 1 / (1 + np.exp(-z_i))
        dz_i = a_i - y[i]
        
        for j in range(n):
            dw[j] += X[i, j] * dz_i
            
        db += dz_i
    
    dw /= m
    db /= m
    return dw, db
向量化实现(高效)
python 复制代码
def compute_gradients_vectorized(X, y, w, b):
    m = X.shape[0]
    Z = np.dot(X, w) + b
    A = 1 / (1 + np.exp(-Z))
    dZ = A - y
    
    dw = (1/m) * np.dot(X.T, dZ)
    db = (1/m) * np.sum(dZ)
    
    return dw, db

性能对比测试

python 复制代码
import time
import numpy as np

# 生成大数据集 (10,000样本, 100特征)
X_large = np.random.randn(10000, 100)
y_large = np.random.randint(0, 2, 10000)
w_large = np.random.randn(100)
b_large = 0

# 测试循环实现
start = time.time()
dw_loop, db_loop = compute_gradients_loop(X_large, y_large, w_large, b_large)
loop_time = time.time() - start

# 测试向量化实现
start = time.time()
dw_vec, db_vec = compute_gradients_vectorized(X_large, y_large, w_large, b_large)
vec_time = time.time() - start

print(f"循环实现时间: {loop_time:.4f}秒")
print(f"向量化实现时间: {vec_time:.4f}秒")
print(f"加速比: {loop_time/vec_time:.1f}x")
print(f"梯度差异: {np.linalg.norm(dw_loop - dw_vec):.6f}")

典型输出

输出示例

向量化背后的数学原理

  1. 矩阵微分规则
    ∂ ∂ w ( X w ) = X T \frac{\partial}{\partial w}(Xw) = X^T ∂w∂(Xw)=XT

  2. 链式法则的向量形式
    ∇ w J = ∂ J ∂ y ^ ⋅ ∂ y ^ ∂ z ⋅ ∂ z ∂ w \nabla_w J = \frac{\partial J}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial z} \cdot \frac{\partial z}{\partial w} ∇wJ=∂y^∂J⋅∂z∂y^⋅∂w∂z

    其中:

    • ∂ J ∂ y ^ = y ^ − y y ^ ( 1 − y ^ ) \frac{\partial J}{\partial \hat{y}} = \frac{\hat{y} - y}{\hat{y}(1-\hat{y})} ∂y^∂J=y^(1−y^)y^−y
    • ∂ y ^ ∂ z = y ^ ( 1 − y ^ ) \frac{\partial \hat{y}}{\partial z} = \hat{y}(1-\hat{y}) ∂z∂y^=y^(1−y^)
    • ∂ z ∂ w = X T \frac{\partial z}{\partial w} = X^T ∂w∂z=XT

    简化后:
    ∇ w J = X T ( y ^ − y ) \nabla_w J = X^T (\hat{y} - y) ∇wJ=XT(y^−y)

  3. 广播机制

    python 复制代码
    # 标量b自动广播到向量运算中
    Z = X.dot(w) + b  # b被加到每个样本上

Python实现逻辑回归

完整代码

python 复制代码
import numpy as np
import matplotlib.pyplot as plt

class LogisticRegression:
    def __init__(self, learning_rate=0.01, n_iters=1000):
        self.lr = learning_rate
        self.n_iters = n_iters
        self.weights = None
        self.bias = None
    
    def _sigmoid(self, z):
        return 1 / (1 + np.exp(-z))
    
    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_iters):
            # 前向传播
            linear_model = np.dot(X, self.weights) + self.bias
            y_pred = self._sigmoid(linear_model)
            
            # 反向传播(向量化计算梯度)
            dw = (1 / n_samples) * np.dot(X.T, (y_pred - y))
            db = (1 / n_samples) * np.sum(y_pred - y)
            
            # 参数更新
            self.weights -= self.lr * dw
            self.bias -= self.lr * db
    
    def predict_prob(self, X):
        linear_model = np.dot(X, self.weights) + self.bias
        return self._sigmoid(linear_model)
    
    def predict(self, X, threshold=0.5):
        return (self.predict_prob(X) >= threshold).astype(int)

# 测试示例
if __name__ == "__main__":
    # 生成示例数据
    from sklearn.datasets import make_classification
    X, y = make_classification(n_samples=100, n_features=2, n_redundant=0, 
                               n_informative=2, random_state=42)
    
    # 训练模型
    model = LogisticRegression(learning_rate=0.1, n_iters=1000)
    model.fit(X, y)
    predictions = model.predict(X)
    
    # 计算准确率
    accuracy = np.mean(predictions == y)
    print(f"Model accuracy: {accuracy:.4f}")
    
    # 可视化决策边界
    plt.figure(figsize=(10, 6))
    plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired, edgecolors='k')
    
    ax = plt.gca()
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    
    # 创建网格以绘制决策边界
    xx, yy = np.meshgrid(np.linspace(xlim[0], xlim[1], 50),
                         np.linspace(ylim[0], ylim[1], 50))
    Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    
    plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.Paired)
    plt.title("Logistic Regression Decision Boundary")
    plt.xlabel("Feature 1")
    plt.ylabel("Feature 2")
    plt.show()
  • 输出示例


完整代码输出示例

代码结构详解

1. 导入必要的库
python 复制代码
import numpy as np
import matplotlib.pyplot as plt
  • numpy:用于高效的数值计算和矩阵运算
  • matplotlib.pyplot:用于数据可视化,绘制决策边界
2. LogisticRegression类定义
2.1 初始化方法 __init__
python 复制代码
def __init__(self, learning_rate=0.01, n_iters=1000):
    self.lr = learning_rate
    self.n_iters = n_iters
    self.weights = None
    self.bias = None
  • learning_rate:学习率,控制梯度下降的步长
  • n_iters:梯度下降的迭代次数
  • weights:特征权重向量(待训练)
  • bias:偏置项(待训练)
2.2 Sigmoid激活函数 _sigmoid
python 复制代码
def _sigmoid(self, z):
    return 1 / (1 + np.exp(-z))
  • 将线性输出转换为概率值(0-1之间)
  • 公式: σ ( z ) = 1 1 + e − z \sigma(z) = \frac{1}{1 + e^{-z}} σ(z)=1+e−z1
  • 函数曲线特性:
    • 当 z → ∞ z \to \infty z→∞ 时, σ ( z ) → 1 \sigma(z) \to 1 σ(z)→1
    • 当 z → − ∞ z \to -\infty z→−∞ 时, σ ( z ) → 0 \sigma(z) \to 0 σ(z)→0
    • 当 z = 0 z = 0 z=0 时, σ ( z ) = 0.5 \sigma(z) = 0.5 σ(z)=0.5
2.3 训练方法 fit
python 复制代码
def fit(self, X, y):
    n_samples, n_features = X.shape
    self.weights = np.zeros(n_features)
    self.bias = 0
  • 输入
    • X:训练数据特征矩阵(形状:n_samples × n_features)
    • y:训练数据标签向量(形状:n_samples)
  • 初始化:权重初始化为零向量,偏置初始化为0
python 复制代码
    # 梯度下降优化
    for _ in range(self.n_iters):
        # 前向传播
        linear_model = np.dot(X, self.weights) + self.bias
        y_pred = self._sigmoid(linear_model)
  • 前向传播
    • 计算线性部分: z = X ⋅ w + b z = X \cdot w + b z=X⋅w+b
    • 应用sigmoid激活: y ^ = σ ( z ) \hat{y} = \sigma(z) y^=σ(z)
python 复制代码
        # 反向传播(向量化计算梯度)
        dw = (1 / n_samples) * np.dot(X.T, (y_pred - y))
        db = (1 / n_samples) * np.sum(y_pred - y)
  • 梯度计算 (向量化实现):
    • 权重梯度: ∂ J ∂ w = 1 m X T ( y ^ − y ) \frac{\partial J}{\partial w} = \frac{1}{m} X^T (\hat{y} - y) ∂w∂J=m1XT(y^−y)
    • 偏置梯度: ∂ J ∂ b = 1 m ∑ ( y ^ − y ) \frac{\partial J}{\partial b} = \frac{1}{m} \sum (\hat{y} - y) ∂b∂J=m1∑(y^−y)
python 复制代码
        # 参数更新
        self.weights -= self.lr * dw
        self.bias -= self.lr * db
  • 参数更新 :使用梯度下降算法
    • w : = w − α ∂ J ∂ w w := w - \alpha \frac{\partial J}{\partial w} w:=w−α∂w∂J
    • b : = b − α ∂ J ∂ b b := b - \alpha \frac{\partial J}{\partial b} b:=b−α∂b∂J
2.4 预测方法
python 复制代码
def predict_prob(self, X):
    linear_model = np.dot(X, self.weights) + self.bias
    return self._sigmoid(linear_model)
  • 返回样本属于正类的概率(0-1之间)
python 复制代码
def predict(self, X, threshold=0.5):
    return (self.predict_prob(X) >= threshold).astype(int)
  • 根据阈值(默认0.5)将概率转换为类别预测
  • 概率 ≥ threshold 预测为正类(1),否则为负类(0)
3. 测试与可视化
3.1 生成示例数据
python 复制代码
from sklearn.datasets import make_classification
X, y = make_classification(n_samples=100, n_features=2, n_redundant=0, 
                           n_informative=2, random_state=42)
  • 使用scikit-learn生成二分类数据集
  • 100个样本,2个特征,无冗余特征
  • random_state=42确保结果可复现
3.2 模型训练与评估
python 复制代码
model = LogisticRegression(learning_rate=0.1, n_iters=1000)
model.fit(X, y)
predictions = model.predict(X)
accuracy = np.mean(predictions == y)
print(f"Model accuracy: {accuracy:.4f}")
  • 创建模型实例(学习率0.1,迭代1000次)
  • 训练模型
  • 在训练集上预测并计算准确率
3.3 决策边界可视化
python 复制代码
plt.figure(figsize=(10, 6))
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired, edgecolors='k')
  • 创建散点图,不同颜色表示不同类别
python 复制代码
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()

# 创建网格点
xx, yy = np.meshgrid(np.linspace(xlim[0], xlim[1], 50),
                     np.linspace(ylim[0], ylim[1], 50))
  • 获取当前坐标轴范围
  • 创建覆盖整个绘图区域的网格点
python 复制代码
# 预测网格点的类别
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# 绘制决策边界
plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.Paired)
  • 将网格点转换为特征矩阵进行预测
  • 使用等高线填充绘制决策区域
python 复制代码
plt.title("Logistic Regression Decision Boundary")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.show()
  • 添加标题和轴标签
  • 显示可视化结果

关键概念图解

1. 逻辑回归工作流程

输入特征 线性变换 z = w·x + b Sigmoid激活 ŷ = σ(z) 概率输出 0-1 二元分类决策

2. 梯度下降优化过程

否 是 初始化参数 前向传播计算预测值 计算损失函数 反向传播计算梯度 更新参数 达到最大迭代次数? 输出最终模型

总结

逻辑回归作为深度学习的基础组件,具有以下特点:

  • 通过sigmoid函数实现概率输出
  • 使用交叉熵损失函数优化分类性能
  • 依赖梯度下降进行参数更新
  • 向量化实现显著提升计算效率
相关推荐
小雷FansUnion2 小时前
深入理解MCP架构:智能服务编排、上下文管理与动态路由实战
人工智能·架构·大模型·mcp
资讯分享周2 小时前
扣子空间PPT生产力升级:AI智能生成与多模态创作新时代
人工智能·powerpoint
水木兰亭3 小时前
数据结构之——树及树的存储
数据结构·c++·学习·算法
思则变3 小时前
[Pytest] [Part 2]增加 log功能
开发语言·python·pytest
叶子爱分享3 小时前
计算机视觉与图像处理的关系
图像处理·人工智能·计算机视觉
鱼摆摆拜拜3 小时前
第 3 章:神经网络如何学习
人工智能·神经网络·学习
一只鹿鹿鹿3 小时前
信息化项目验收,软件工程评审和检查表单
大数据·人工智能·后端·智慧城市·软件工程
张较瘦_3 小时前
[论文阅读] 人工智能 | 深度学习系统崩溃恢复新方案:DaiFu框架的原位修复技术
论文阅读·人工智能·深度学习
cver1233 小时前
野生动物检测数据集介绍-5,138张图片 野生动物保护监测 智能狩猎相机系统 生态研究与调查
人工智能·pytorch·深度学习·目标检测·计算机视觉·目标跟踪
漫谈网络3 小时前
WebSocket 在前后端的完整使用流程
javascript·python·websocket