深度学习中的逻辑回归:从原理到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函数,其特性如下:


逻辑回归损失函数
损失函数用域名衡量预测结构与真实值之间的误差。最简单的损失函数定义方式为平方差损失:
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]] # 样本3y = [1, 0, 1] # 真实标签w = [0.5, -0.2] # 初始权重
b = 0.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]
-
计算误差:
error = Y_hat - y = [0.622-1, 0.450-0, 0.802-1]= [-0.378, 0.450, -0.198]
-
向量化梯度计算:
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}")
典型输出:

向量化背后的数学原理
-
矩阵微分规则:
∂ ∂ w ( X w ) = X T \frac{\partial}{\partial w}(Xw) = X^T ∂w∂(Xw)=XT -
链式法则的向量形式:
∇ 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) -
广播机制:
# 标量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+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
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=X⋅w+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) ∂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)
# 参数更新self.weights -= self.lr * dwself.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 预测方法
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. 逻辑回归工作流程
2. 梯度下降优化过程
总结
逻辑回归作为深度学习的基础组件,具有以下特点:
- 通过sigmoid函数实现概率输出
- 使用交叉熵损失函数优化分类性能
- 依赖梯度下降进行参数更新
- 向量化实现显著提升计算效率