大白话5分钟带你走进人工智能-第十八节逻辑回归之交叉熵损失函数梯度求解过程(3)

本文深入探讨逻辑回归中交叉熵损失函数的梯度求解过程,解释如何通过梯度下降法找到使损失函数最小化的参数θ。文章详细介绍了求解步骤,包括随机初始化权重、求解梯度、泰勒展开近似及收敛判断,重点在于推导交叉熵损失函数的导数,最终得出逻辑回归的导函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                               第十八节逻辑回归之交叉熵损失函数梯度求解过程(2)

上一节中,我们讲解了交叉熵损失函数的概念,目标是要找到使得损失函数最小的那组θ,也就是l(θ)最大,即预测出来的结果在训练集上全部正确的概率最大。那我们怎么样找到我们的最优解呢?上节中提出用梯度下降法求解,本节的话我们对其具体细节展开。

先来看下我们用梯度下降求解最优解,想要通过梯度下降优化L(θ)到最小值需要几步?

第一步,随机产生w,随机到0附近会比较好一点,w随机到0附近就意味着不管用L1还是L2正则的时候,可以使w的整体比较小。L1和L2正则同样可以用到逻辑回归里面去,来使得逻辑回归的损失函数obj相对比较小,然后使得我们模型具有推广能力和泛化能力。其实任何算法,都可以去使用L1和L2来提高模型的泛化能力,本质上就是减少模型的复杂度。所以以后未来碰到任何的算法,w在随机的过程当中,我们最好用期望为0的正态分布,来随机产生n+1个w。

第二步是求梯度,对于逻辑回归来说,如果用SGD求梯度,我们得用交叉熵的损失函数来得到它的导函数,然后才可以知道某一个值的时候它的梯度是多少。

第三步是w k+1=w k+\lambda *-\frac{\partial L(W k)}{\partial(w k)},它本质是一阶泰勒展开近似。

           第四步是判断收敛,其实就是第二第三步循环往复来执行。

四步里面第二步求解交叉熵损失函数的导函数求得其梯度是最关键的。我们对其展开来说。我们再来看下我们的目标函数:

                         $J_{\log }(w)=\sum_{i=1}^{m}-y_{i} \log \left(p\left(x_{i} ; w\right)\right)-\left(1-y_{i}\right) \log \left(1-p\left(x_{i} ; w\right)\right)$

把负号提出来再加上1/m就是:

                        $J_{\log }(w)=-\sum_{i=1}^{m}y_{i} \log \left(p\left(x_{i} ; w\right)\right)+\left(1-y_{i}\right) \log \left(1-p\left(x_{i} ; w\right)\right)$

至于求导梯度时为什么要加-1/m,可以参考第六节梯度下降之从单元函数理解梯度下降过程(1)

我们要对损失函数里每个w求偏导,也就是对每一部分求偏导。w在pi里面,pi=1/(1+e-w^Tx),也可写成h(θ)x。上面可拆成左右两部分求导,先对左半部分yi*log pi求导,我们是对wj即(θj)求偏导,跟yi没关系,因为(lnx)'=1/x ,并且log pi是复合函数,需要对里外分别求导,即: 

                                                       y_{i} \left(\log p_{i}\right)^{\prime}=y_{i} \frac{1}{p_{i}} p_{i}^{\prime}=y_{i} \frac{1}{h_{\theta}\left(x_{i}\right)} \frac{\delta}{\delta_{\theta_{j}}} h_{\theta}\left(x_{i}\right)

后半部分同理复合函数求导,

即 :            

                        (\left(1-y_{i}\right) \log \left(1-p\left(x_{i} ; w\right)\right))^{\prime}=\left(1-y_{i}\right) (\log \left(1-p\left(x_{i} ; w\right)\right))^{\prime}=$$\left(1-y_{i}\right)\frac{1}{\left(1-p\left(x_{i} ; w\right)\right))} \left(1-p\left(x_{i} ; w\right)\right)^{\prime}

又因为\left(1-p\left(x_{i} ; w\right)\right)^{\prime}求导结果为\left(1-p\left(x_{i} ; w\right)\right)^{\prime}=-p\left(x_{i} ; w\right)\right)^{\prime}。而p(xi;w) 实际上就是关于θ的函数,可以写成h(θ)x。所以

                                     $$\left(1-y_{i}\right)\frac{1}{\left(1-p\left(x_{i} ; w\right)\right))} \left(1-p\left(x_{i} ; w\right)\right)^{\prime}=-\left(1-y_{i}\right) \frac{1}{1-h_{\theta}\left(x_{i}\right)} \frac{\delta}{\delta_{\theta_{j}}} h_{\theta}\left(x_{i}\right)

左右两部分求导结合起来后损失函数表示成:

                                     \frac{\delta}{\delta_{\theta_{j}}} J(\theta)=-\frac{1}{m} \sum_{i=1}^{m}\left(y_{i} \frac{1}{h_{\theta}\left(x_{i}\right)} \frac{\delta}{\delta_{\theta_{j}}} h_{\theta}\left(x_{i}\right)-\left(1-y_{i}\right) \frac{1}{1-h_{\theta}\left(x_{i}\right)} \frac{\delta}{\delta_{\theta_{j}}} h_{\theta}\left(x_{i}\right)\right)

hθ(x)=1/(1+e-θ^Tx),是关于θ^Tx的Sigmoid函数.所以可以用g(θTx)表示,所以损失函数推导部分又可以写成:

                                     \frac{\delta}{\delta_{\theta_{j}}} J(\theta)=-\frac{1}{m} \sum_{i=1}^{m}\left(y_{i} \frac{1}{g\left(\theta^{T} x_{i}\right)}-\left(1-y_{i}\right) \frac{1}{1-g\left(\theta^{T} x_{i}\right)}\right) \frac{\delta}{\delta_{\theta_{j}}} g\left(\theta^{T} x_{i}\right)

又因为(1/x)'=-1/x2,(ex)'= ex,(-z)'=-1,所以\frac{\delta}{\delta_{\theta_{j}}} g\left(\theta^{T} x_{i}\right)实际上展开就是:

                                                                   \begin{aligned} \\ & \left(\frac{1}{1+e^{-z}}\right)^{\prime}\\ &=-\frac{1}{(1+e^{-z})^{2}}*(1+e^{-z})^{\prime} \\ &=-\frac{1}{(1+e^{-z})^{2}}*(e^{-z})^{\prime}\\ &=-\frac{1}{(1+e^{-z})^{2}}*(e^{-z})*(-z)^{\prime}\\ &=\frac{1}{(1+e^{-z})^{2}}*(e^{-z})*(z)^{\prime}\end{aligned}

好吧看到这是不是很晕眩,实际上耐心下来,跟着我的思路去走,就会很好理解上面的公式。我们继续吧,很快就结束了,也快大功告成了。我们对\frac{\delta}{\delta_{\theta_{j}}} g\left(\theta^{T} x_{i}\right)上面展开后的公式继续展开,整理即:

                                                                  \begin{aligned} \\ & \frac{1}{(1+e^{-z})^{2}}*(e^{-z})*(z)^{\prime}\\ &=\frac{1}{1+e^{-z}}*\frac{e^{-z}}{1+e^{-z}}*(z)^{\prime} \\ &=\frac{1}{1+e^{-z}}*(\frac{1+e^{-z}}{1+ e^{-z}}-\frac{1}{1+e^{-z}})*(z)^{\prime}\end{aligned}

因为z就是θTx,hθ(x)=1/(1+e-θ^Tx)是关于θ^Tx的Sigmoid函数.同样可以用g(θTx)表示。所以上面\frac{\delta}{\delta_{\theta_{j}}} g\left(\theta^{T} x_{i}\right)展开后的公式最后可以表示成:

 

                                                                   \begin{aligned} \\ &\frac{1}{1+e^{-z}}*(\frac{1+e^{-z}}{1+ e^{-z}}-\frac{1}{1+e^{-z}})*(z)^{\prime} \\ &\\ &=g\left(\theta^{T} x_{i}\right)\left(1-g\left(\theta^{T} x_{i}\right)\right) \frac{\delta}{\delta_{\theta_{j}}} \theta^{T} x_{i}\end{aligned}

所以损失函数可以推导成:

                                       \begin{aligned} &\frac{\delta}{\delta_{\theta_{j}}} J(\theta)=-\frac{1}{m} \sum_{i=1}^{m}\left(y_{i} \frac{1}{h_{\theta}\left(x_{i}\right)} \frac{\delta}{\delta_{\theta_{j}}} h_{\theta}\left(x_{i}\right)-\left(1-y_{i}\right) \frac{1}{1-h_{\theta}\left(x_{i}\right)} \frac{\delta}{\delta_{\theta_{j}}} h_{\theta}\left(x_{i}\right)\right)\\ &\\ & \qquad \quad=-\frac{1}{m} \sum_{i=1}^{m}\left(y_{i} \frac{1}{g\left(\theta^{T} x_{i}\right)}-\left(1-y_{i}\right) \frac{1}{1-g\left(\theta^{T} x_{i}\right)}\right) \frac{\delta}{\delta_{\theta_{j}}} g\left(\theta^{T} x_{i}\right)\\ &\\ & \qquad \quad=-\frac{1}{m} \sum_{i=1}^{m}\left(y_{i} \frac{1}{g\left(\theta^{T} x_{i}\right)}-\left(1-y_{i}\right) \frac{1}{1-g\left(\theta^{T} x_{i}\right)}\right) g\left(\theta^{T} x_{i}\right)\left(1-g\left(\theta^{T} x_{i}\right)\right) \frac{\delta}{\delta_{\theta_{j}}} \theta^{T} x_{i}\end{aligned}

而θTx就是θ1x1+θ2x2+……+θjxj+……+θnxn,如果对θj求偏导,只剩xj。即 \frac{\delta}{\delta_{\theta_{j}}} \theta^{T} x_{i}=x_{i}^{j}

xij这种表达方式大家应该已经习惯了,因为i代表第i行,j代表第j列,因为损失函数前面有一个加和符号,所以它实际上还是每一行的事。接下来就是把损失函数式子拆开,正负相消即:

                             \begin{aligned} &\frac{\delta}{\delta_{\theta_{j}}} J(\theta)=-\frac{1}{m} \sum_{i=1}^{m}\left(y_{i} \frac{1}{g\left(\theta^{T} x_{i}\right)}-\left(1-y_{i}\right) \frac{1}{1-g\left(\theta^{T} x_{i}\right)}\right) g\left(\theta^{T} x_{i}\right)\left(1-g\left(\theta^{T} x_{i}\right)\right) \frac{\delta}{\delta_{\theta_{j}}} \theta^{T} x_{i}\\ &\\ & \qquad \quad=-\frac{1}{m} \sum_{i=1}^{m}\left(y_{i}\left(1-g\left(\theta^{T} x_{i}\right)\right)-\left(1-y_{i}\right) g\left(\theta^{T} x_{i}\right)\right) x_{i}^{j}\\ &\\ & \qquad \quad=-\frac{1}{m} \sum_{i=1}^{m}\left(y_{i}-g\left(\theta^{T} x_{i}\right)\right) x_{i}^{j}\\ &\\ & \qquad \quad=\frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x_{i}\right)-y_{i}\right) ) x_{i}^{j}\end{aligned}

最后一步是把前面的负号放进去得到的。到此我们推导成功,擦擦汗,真不容易!!!。它就是逻辑回归的导函数,你会发现它推导之后和mse的导函数是一样的,都是(hθ(x)-y)*xj这种形式。只不过在多元线性回归的时候,hθ(x)是wTx,在逻辑回归里面,hθ(x)是1/(1+e-θTx)。hθ(x)不一样,但是整体形式一样。所以这也是它叫逻辑回归的一个很大原因。

有了逻辑回归损失函数推出来的导函数,我们用梯度下降求解的时候,我们就可以把第三步中的-\frac{\partial L(W k)}{\partial(w k)}这一部分算出来了。只要给我一组w,或者θ,w0一直到wn。有了θ,x,y,xj,我就可以把导数求出来。有了导数,继而求得梯度。然后就可以用梯度下降公式去求解了。

下一节中我们讲解逻辑回归的优化。

<think>嗯,用户问的是如果没有sklearn库的话,如何手动实现一个拟合函数,比如线性回归。首先,我需要理解用户的需求。可能用户是在学习机器学习或者统计,想了解底层原理,或者环境限制不能使用现成的库,需要自己实现。 用户可能对线性回归的基本概念有所了解,但不知道具体的数学推导和代码实现步骤。所以,我需要先简单回顾线性回归的原理,然后分步骤解释如何手动实现。 首先,线性回归的目标是找到最佳拟合直线,使得预测值和实际值的残差平方和最小。数学上是通过最小二乘法来求解系数。这时候需要用到正规方程,也就是通过求导得到参数的闭式解。公式是θ = (X^T X)^{-1} X^T y。这里需要注意矩阵运算的条件,比如X矩阵是否可逆,是否需要加入正则化项等。 接下来,我需要考虑如何将这个数学过程转化为代码。首先需要构造设计矩阵X,通常会在原始数据前加一列1,用来对应截距项。然后计算X的转置,矩阵乘法,求逆,再乘以X的转置和y的乘积。 可能会遇到的问题包括矩阵不可逆的情况,这时候可能需要检查特征是否存在多重共线性,或者使用伪逆来代替。此外,计算逆矩阵的时候数值稳定性也很重要,尤其是当数据量较大或者特征较多时。 然后,我需要将这个过程用Python代码实现,不使用sklearn,而是用numpy库进行矩阵运算。虽然用户可能希望不用任何库,但numpy是基础的科学计算库,通常还是可以使用的。不过如果用户真的不想用任何库,可能需要手动实现矩阵运算,但这样复杂度太高,不太现实。所以假设用户允许使用numpy。 接下来,分步骤解释代码的实现过程,包括数据准备、构造X矩阵、计算参数、预测函数等。同时,可能需要给出一个简单的示例数据,并展示如何调用这个函数,最后评估模型的好坏,比如计算R平方值。 用户可能还关心如何处理异常情况,比如特征数量不一致,矩阵不可逆,或者数据标准化的问题。这时候可能需要补充说明,比如建议在拟合前对数据进行标准化处理,或者在矩阵不可逆时使用伪逆。 最后,总结手动实现的优缺点,指出虽然手动实现有助于理解原理,但在实际应用中还是推荐使用优化过的库如sklearn,因为它们在效率和数值稳定性上更好。</think>好的,我尽量用大白话解释如何手动实现线性回归拟合。咱们分四步走: 1️⃣ **原理回顾** 线性回归就是找一条直线/平面,让所有数据点到这条线的垂直距离(残差)平方和最小。数学上用这个公式求系数: $$ \theta = (X^T X)^{-1} X^T y $$ (这个叫正规方程,其实就是最小二乘法的解) 2️⃣ **手写代码实现** 假设我们用numpy做矩阵运算(毕竟手动写矩阵运算太痛苦了): ```python import numpy as np def manual_linear_regression(X, y): # 给特征矩阵加一列1(对应截距项b) X_b = np.c_[np.ones((X.shape[0], 1)), X] # 核心计算公式 theta = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y) return theta # 示例数据 X = np.array([[1], [2], [3]]) # 特征 y = np.array([2, 4, 6]) # 目标值 # 训练模型 coefficients = manual_linear_regression(X, y) print(f"截距b: {coefficients[0]}, 斜率w: {coefficients[1:]}") # 输出:截距b: 0.0, 斜率w: [2.] → 完美拟合y=2x ``` 3️⃣ **使用技巧** - 如果出现矩阵不可逆,可以改用伪逆:`np.linalg.pinv` - 数据量大时建议先标准化(减均值/除标准差) - 预测函数可以这样写: ```python def predict(X_new, theta): X_new_b = np.c_[np.ones((X_new.shape[0], 1)), X_new] return X_new_b.dot(theta) ``` 4️⃣ **效果评估** 计算R²值看拟合效果: ```python y_pred = predict(X, coefficients) ss_res = np.sum((y - y_pred)**2) ss_tot = np.sum((y - np.mean(y))**2) r2 = 1 - ss_res/ss_tot print(f"R²得分: {r2:.3f}") # 本例输出1.0(完全拟合) ``` ⚠️ **注意事项** - 这个方法时间复杂度是O(n&sup3;),数据量上万时会很慢 - 实际应用建议梯度下降法(需要写迭代优化) - 特征太多容易导致矩阵计算不稳定 - 真实数据建议还是用现成库(比如用`scipy.linalg.lstsq`更安全) 理解了这个手动版,再用sklearn的`LinearRegression`时,就知道它背后在做什么魔法啦!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

L先生AI课堂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值