当前位置: 首页 > news >正文

深度学习中的逻辑回归:从原理到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+ez1

其中 σ ( z ) \sigma(z) σ(z)为sigmoid函数,其特性如下:

输入特征 x
线性变换 z = w·x + b
Sigmoid激活函数
概率输出 ŷ = σ(z)
sigmoid函数
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^)(1y)log(1y^)
该式子的理解:

  • 如何 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(1y^),那么要想损失越小,那么 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αwJ
b : = b − α ∂ J ∂ b b := b - \alpha \frac{\partial J}{\partial b} b:=bαbJ

其中 α \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} XRm×n(m个样本,n个特征)
  • 参数向量 w ∈ R n w \in \mathbb{R}^{n} wRn
  • 偏置 b ∈ R b \in \mathbb{R} bR
  • 预测值 y ^ = σ ( X w + b ) \hat{y} = \sigma(Xw + b) y^=σ(Xw+b)
  • 真实标签 y ∈ R m y \in \mathbb{R}^{m} yRm

梯度计算可向量化为:
∇ 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=1m(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]]   # 样本3y = [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实现对比

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

性能对比测试

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() - startprint(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^Jzy^wz
    其中:

    • ∂ 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^(1y^)y^y
    • ∂ y ^ ∂ z = y ^ ( 1 − y ^ ) \frac{\partial \hat{y}}{\partial z} = \hat{y}(1-\hat{y}) zy^=y^(1y^)
    • ∂ z ∂ w = X T \frac{\partial z}{\partial w} = X^T wz=XT

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

  3. 广播机制

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

Python实现逻辑回归

完整代码

import numpy as np
import matplotlib.pyplot as pltclass LogisticRegression:def __init__(self, learning_rate=0.01, n_iters=1000):self.lr = learning_rateself.n_iters = n_itersself.weights = Noneself.bias = Nonedef _sigmoid(self, z):return 1 / (1 + np.exp(-z))def fit(self, X, y):n_samples, n_features = X.shapeself.weights = np.zeros(n_features)self.bias = 0# 梯度下降优化for _ in range(self.n_iters):# 前向传播linear_model = np.dot(X, self.weights) + self.biasy_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 * dwself.bias -= self.lr * dbdef predict_prob(self, X):linear_model = np.dot(X, self.weights) + self.biasreturn 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_classificationX, 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. 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
  • numpy:用于高效的数值计算和矩阵运算
  • matplotlib.pyplot:用于数据可视化,绘制决策边界
2. LogisticRegression类定义
2.1 初始化方法 __init__
def __init__(self, learning_rate=0.01, n_iters=1000):self.lr = learning_rateself.n_iters = n_itersself.weights = Noneself.bias = None
  • learning_rate:学习率,控制梯度下降的步长
  • n_iters:梯度下降的迭代次数
  • weights:特征权重向量(待训练)
  • bias:偏置项(待训练)
2.2 Sigmoid激活函数 _sigmoid
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+ez1
  • 函数曲线特性:
    • 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
def fit(self, X, y):n_samples, n_features = X.shapeself.weights = np.zeros(n_features)self.bias = 0
  • 输入
    • X:训练数据特征矩阵(形状:n_samples × n_features)
    • y:训练数据标签向量(形状:n_samples)
  • 初始化:权重初始化为零向量,偏置初始化为0
    # 梯度下降优化for _ in range(self.n_iters):# 前向传播linear_model = np.dot(X, self.weights) + self.biasy_pred = self._sigmoid(linear_model)
  • 前向传播
    • 计算线性部分: z = X ⋅ w + b z = X \cdot w + b z=Xw+b
    • 应用sigmoid激活: y ^ = σ ( z ) \hat{y} = \sigma(z) y^=σ(z)
        # 反向传播(向量化计算梯度)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) wJ=m1XT(y^y)
    • 偏置梯度: ∂ J ∂ b = 1 m ∑ ( y ^ − y ) \frac{\partial J}{\partial b} = \frac{1}{m} \sum (\hat{y} - y) bJ=m1(y^y)
        # 参数更新self.weights -= self.lr * dwself.bias -= self.lr * db
  • 参数更新:使用梯度下降算法
    • w : = w − α ∂ J ∂ w w := w - \alpha \frac{\partial J}{\partial w} w:=wαwJ
    • b : = b − α ∂ J ∂ b b := b - \alpha \frac{\partial J}{\partial b} b:=bαbJ
2.4 预测方法
def predict_prob(self, X):linear_model = np.dot(X, self.weights) + self.biasreturn self._sigmoid(linear_model)
  • 返回样本属于正类的概率(0-1之间)
def predict(self, X, threshold=0.5):return (self.predict_prob(X) >= threshold).astype(int)
  • 根据阈值(默认0.5)将概率转换为类别预测
  • 概率 ≥ threshold 预测为正类(1),否则为负类(0)
3. 测试与可视化
3.1 生成示例数据
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 模型训练与评估
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 决策边界可视化
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. 逻辑回归工作流程
输入特征
线性变换 z = w·x + b
Sigmoid激活 ŷ = σ(z)
概率输出 0-1
二元分类决策

2. 梯度下降优化过程

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

总结

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

  • 通过sigmoid函数实现概率输出
  • 使用交叉熵损失函数优化分类性能
  • 依赖梯度下降进行参数更新
  • 向量化实现显著提升计算效率
http://www.dtcms.com/a/265802.html

相关文章:

  • leetcode:1049. 最后一块石头的重量 II[01背包][动态规划]
  • 实际开发如何快速定位和解决死锁?
  • PM2.5和PM10分别是什么
  • 基于MATLAB的风力发电机无人机巡检路径优化研究
  • 最新PDF转markdown软件MonkeyOCR整合包,文档图片解析工具
  • 深度解析:Java内部类与外部类的交互机制
  • odoo-057 pgadmin 登录忘记密码
  • 【实时Linux实战系列】实时以太网与 TSN 基础
  • ARM单片机启动流程(二)(详细解析)
  • UDP服务器主要是指什么意思?
  • 提升自动驾驶导航能力:基于深度学习的场景理解技术
  • Centrifugo 深度解析:构建高性能实时应用的开源引擎
  • RocketMQ-Dashboard页面报Failed to fetch ops home page data错误
  • 车载交换机动态MAC学习和静态MAC绑定如何获取MAC地址表
  • BitsAndBytesConfig量化及注意事项
  • 明远智睿H618:开启多场景智慧生活新时代
  • 代码随想录打卡第五天
  • TinyWebserver学习(8)-定时器
  • 深度解析:venv和conda如何解决依赖冲突难题
  • 使用netstat与grep命令结合批量查找特定内容
  • Class3图像分类数据集代码
  • 数学建模_时间序列
  • CTF Web PHP弱类型与进制绕过(过滤)
  • 【云计算】企业项目 策略授权
  • 网络层:ip协议 与数据链路层
  • C++反射之获取可调用对象的详细信息
  • 《Spring 中上下文传递的那些事儿》Part 2:Web 请求上下文 —— RequestContextHolder 与异步处理
  • 低代码实战训练营教学大纲 (10天)
  • Linux之Socket 编程 UDP
  • 自然光实时渲染~三维场景中的全局光照