机器学习入门:逻辑回归原理、损失函数与梯度下降推导

发布时间:2026/6/23 22:49:09
机器学习入门:逻辑回归原理、损失函数与梯度下降推导 目录二元分类核心概念常用算法逻辑回归成本函数梯度下降向量化二元分类二元分类Binary Classification是机器学习中最常见的任务之一目标是将数据分为两个互斥的类别。核心概念二元分类的输出通常是两个类别标签如0/1、正/负、是/否。常见的应用场景包括垃圾邮件检测、疾病诊断、客户流失预测等。关键在于构建一个模型能够通过学习历史数据中的模式对新样本进行准确分类。常用算法逻辑回归Logistic Regression通过Sigmoid函数将线性回归的输出映射到[0,1]区间表示概率。支持向量机SVM寻找一个超平面最大化两类数据间的间隔。核函数如RBF可用于处理非线性可分数据。决策树与随机森林决策树通过递归分割数据实现分类随机森林通过集成多棵决策树提升泛化能力。梯度提升树如XGBoost、LightGBM通过迭代训练弱分类器通常是决策树并优化损失函数逐步提升模型性能。逻辑回归逻辑回归是一种用于解决二分类问题的统计方法通过拟合一个逻辑函数如Sigmoid函数预测事件发生的概率。尽管名称中包含“回归”但它实际是一种分类算法适用于输出为离散值如0或1的场景。 逻辑回归使用 Sigmoid 函数处理二分类多分类场景下通常使用 SoftMax 函数 详见SoftMax函数-CSDN博客逻辑回归通过线性组合输入特征并应用Sigmoid函数将结果映射到[0,1]区间表示概率。Sigmoid函数公式为其中w 为权重向量b 为偏置项。成本函数为了训练回归的参数w和b需要定义一个成本函数。在定义成本函数之前我们需要先定义损失函数(Loss function)损失函数衡量的是单个样本的预测值和实际标签值之间的误差。一般通过最大似然估计或梯度下降法优化损失函数我们希望误差函数越小越好因为这表明我们的预测很准确。当y1时因为第二项为0 所以损失函数变为所以我们希望尽可能小所以就要尽可能大即a要尽可能大但是a是由σ函数所得即a最大不超过1也就是说当实际标签y1时我们希望预测值a也尽可能接近1这符合我们的要求。如果y0第一项变为0所以损失函数为我们希望尽可能小即尽可能大所以这使得a尽可能小a最小不低于0所以实际标签为0时我们希望预测值a尽可能接近0。损失函数衡量的是单个样本的表现而成本函数衡量的是全体训练样本的表现下面是成本函数的定义梯度下降为了根据训练集学习得到参数w和b我们需要使用优化算法梯度下降法就是优化算法中的一种。梯度下降是一种用于优化目标函数的迭代算法通过计算目标函数的梯度并沿负梯度方向更新参数逐步逼近最小值。广泛应用于机器学习模型的参数训练我们要做的就是随机任意初始化w和b然后不断用下面的式子更新w和b的值。其中α表示学习率它控制更新的速率。导数的直观理解就是曲线的斜率。假设初始参数w位于最低点右侧由于此时导数为正根据更新公式会使w逐渐减小即损失函数J(w)向左侧最低点移动。反之若w初始位于左侧导数为负会使w不断增大推动J(w)向右移动直至达到最低点。为了求解使J(w,b)最小化的参数w和b需要计算J(w,b)对w和b的偏导数。为便于理解我们先从单个训练样本的损失函数开始推导导数计算。首先采用反向计算的方式从后向前逐步求导先计算损失函数L对输出a的偏导数。在逻辑回归中我们通常处理的是多个训练样本而非单个样本因此需要探讨如何对m个训练样本进行梯度下降更新。由于成本函数J(w,b)是损失函数的平均值因此J(w,b)对w和b的偏导数也应该是单个样本梯度计算结果的均值。从上述三个导数计算公式可以看出理论上需要采用两层循环结构外层循环遍历每个训练样本内层循环对所有w参数进行累加。然而在实际的深度学习算法实现中显式使用循环结构效率极低特别是在处理大规模数据时。为了提高计算效率我们需要采用向量化技术来避免不必要的显式循环。向量化import time a np.random.rand(1000000) b np.random.rand(1000000) past time.time() c np.dot(a,b) now time.time() print(向量化版本的计算时长 str(1000*(now-past)) ms) c 0 past time.time() for i in range(1000000): c a[i] * b[i] now time.time() print(非向量化版本的计算时长 str(1000*(now-past)) ms)向量化版本的计算时长1.0833740234375ms 非向量化版本的计算时长727.9131412506104ms图中展示了一个计算向量内积的示例可以看出向量化操作显著提升了运算速度。当处理大规模数据时这种性能优势会更加突出。所有其实求成本函数使用向量化进行计算时内部结构应该是这样类似于矩阵乘法。接下来我将给出之前所用到的一些函数代码sigmoid函数def sigmoid(z): σ函数 a 1 / (1 np.exp(-z)) return aw和b参数的初始化def initialize_parameters(dim): w np.random.randn(dim,1) b 0 return w,bdim代表w的维度等于输入特征的数量需要注意的是逻辑回归中通常也可以把w初始化为全 0这里用随机初始化也能运行但对普通逻辑回归来说不是必须的。正反向传播def propagate(w,b,X,Y): m X.shape[1] A sigmoid(np.dot(w.T,X)b) cost -1/m*np.sum(Y*np.log(A)(1-Y)*np.log(1-A)) dw 1/m*np.dot(X,(A-Y).T) db 1/m*np.sum(A-Y) cost np.squeeze(cost) grads {dw:dw, db:db} return grads,costX表示输入特征矩阵形状为(n_x, m) ,n_X表示特征数量。m表示训练样本的个数。Y 训练集的标签形状为(1,m)每个标签通常是 0 或 1。因为X的每一列是一个样本所以X.shape[1]是样本数量。梯度下降算法def optimize(w,b,X,Y,num_iterations,learning_rate,print_cost False): costs [] for i in range(num_iterations): grads,cost propagate(w,b,X,Y) dw grads[dw] db grads[db] w w - learning_rate*dw b b - learning_rate*db if i%100 0: costs.append(cost) if print_cost and i % 100 0: print(Cost after iteration %i: %f %(i, cost)) params {w:w, b:b} grads {dw:dw, db:db} return params,grads,costs每次迭代都调用propagate()计算当前参数下的损失和梯度。learning_rate就是学习率α学习率控制每次更新的步子大小学习率影响太大可能震荡甚至损失变大太小收敛很慢合适损失逐渐下降每 100 次迭代记录一次成本值方便后面画图观察模型是否在学习。最后返回优化后的参数、最后一次梯度和训练过程中的损失记录。def predict(w,b,X): m X.shape[1] A sigmoid(np.dot(w.T,X)b) Y_prediction np.zeros((1,m)) for i in range(m): Y_prediction[0,i]A[0,i]0.5 return Y_prediction这个函数用训练好的参数进行预测。先得到每个样本属于类别1的概率。如果概率大于0.5预测为True存入数组后会变成1.0。如果概率小于等于0.5预测为False存入数组后会变成0.0。 逻辑回归是理解神经网络的基础想进一步学习神经网络的前向传播和反向传播 可以阅读我的下一篇神经网络入门教程前向传播与反向传播详解附NumPy/PyTorch代码-CSDN博客