资讯动态

深度学习6:神经网络学习3:神经网络梯度计算(简单的神经网络代码实现,经典)

发布时间:2026/10/23 2:45:25 来源:尧图企业网站定制
已经用数值微分算出神经网络的梯度,那接下来怎么算最优权重参数下个blog见一、理解为啥是L对w的梯度1. 先明确谁是变量谁是数据2. 为什么调整 w 而不是 X1. 多个数据时损失函数怎么定义2. 实际训练中不是一次用全部数据二、代码(涉及闭包/匿名函数有点绕)三、整个链路的完整逻辑一、理解为啥是L对w的梯度知道x 不需要知道具体f(神经网络中间层太多黑盒所以没法正常一个个求导算最小损失函数)只需要知道根据x利用forward可以算出y就行参考blog机器学习:线性回归3正规方程法和梯度下降法里面 梯度下降前置知识和疑问导数y对x求导让y最小怎么调整x类比我们这是损失函数对权重求导损失函数 预测值 - 真实值平方 (真实值t有预测值y 通过x的forward也有) 所以影响损失函数的是 forward里面的权重在神经网络的学习中梯度的计算非常重要。神经网络中的梯度指的就是损失函数关于权重参数的梯度。我们以一个单层的简单网络为例形状为2 × 3 2 \times 32×3权重参数为W WW损失函数记为L LL。那么它的权重参数和梯度为W ( w 11 w 12 w 13 w 21 w 22 w 23 ) W \begin{pmatrix} w_{11} w_{12} w_{13} \\ w_{21} w_{22} w_{23} \end{pmatrix}W(w11​w21​​w12​w22​​w13​w23​​)∂ L ∂ W ( ∂ L ∂ w 11 ∂ L ∂ w 12 ∂ L ∂ w 13 ∂ L ∂ w 21 ∂ L ∂ w 22 ∂ L ∂ w 23 ) \frac{\partial L}{\partial W} \begin{pmatrix} \frac{\partial L}{\partial w_{11}} \frac{\partial L}{\partial w_{12}} \frac{\partial L}{\partial w_{13}} \\ \frac{\partial L}{\partial w_{21}} \frac{\partial L}{\partial w_{22}} \frac{\partial L}{\partial w_{23}} \end{pmatrix}∂W∂L​(∂w11​∂L​∂w21​∂L​​∂w12​∂L​∂w22​∂L​​∂w13​∂L​∂w23​∂L​​)这里梯度∂ L ∂ W \frac{\partial L}{\partial W}∂W∂L​也是一个2 × 3 2 \times 32×3的矩阵其中各个元素由L LL关于W WW中各元素的偏导数构成。当初我没理解透问了一个很憨的问题知道x和对应真实值tw是定义的2*3随机矩阵(显然输入是两个神经元输出是三个神经元)利用数值微分算出损失函数对w的梯度为啥调整w来改变损失函数不是改变x吗?1. 先明确谁是变量谁是数据在你描述的场景里X输入数据特征是已知的、固定的t真实标签也是已知的、固定的w2 × 3 2 \times 32×3的随机矩阵是模型参数是需要被学习/调整的损失函数L ( w ) L(w)L(w)本质上是关于w ww的函数。X 和 t 只是代入其中的常数。所以梯度是∂ L ∂ w \frac{\partial L}{\partial w}∂w∂L​而不是∂ L ∂ X \frac{\partial L}{\partial X}∂X∂L​。因为 X 不是你要优化的对象它只是“题目给定的条件”。2. 为什么调整 w 而不是 X打个比方你在射箭靶子 (X, t) 是固定不动的箭的落点由你的瞄准方式 (w) 决定。脱靶了你该调整的是你的瞄准方式而不是去挪靶子。X 是靶子数据是客观给定的你不能改。w 是瞄准方式模型参数你能改也应该改。损失函数衡量“当前 w 下预测和真实值差多少”。训练的目标就是w ∗ arg ⁡ min ⁡ w L ( w ) w^* \arg\min_w L(w)w∗argwmin​L(w)即找到一组 w让损失最小。当初我没理解透又问了一个很憨的问题这是给的一组数据找W如果是多个数据W怎么同时满足多个数据损失函数最小取平均吗1. 多个数据时损失函数怎么定义假设你有N NN组数据( X 1 , t 1 ) , ( X 2 , t 2 ) , … , ( X N , t N ) (X_1, t_1), (X_2, t_2), \dots, (X_N, t_N)(X1​,t1​),(X2​,t2​),…,(XN​,tN​)每组数据都会产生一个损失L i ( w ) loss ( f ( X i ; w ) , t i ) L_i(w) \text{loss}(f(X_i; w), t_i)Li​(w)loss(f(Xi​;w),ti​)你不可能让w ww同时让每个L i L_iLi​都最小——因为它们可能互相冲突。所以要把它们合成一个总损失最常见的就是L ( w ) 1 N ∑ i 1 N L i ( w ) L(w) \frac{1}{N} \sum_{i1}^{N} L_i(w)L(w)N1​i1∑N​Li​(w)这就是平均损失。然后用梯度下降w ← w − η ⋅ 1 N ∑ i 1 N ∂ L i ∂ w w \leftarrow w - \eta \cdot \frac{1}{N} \sum_{i1}^{N} \frac{\partial L_i}{\partial w}w←w−η⋅N1​i1∑N​∂w∂Li​​2. 实际训练中不是一次用全部数据理论上你用全部 N 组数据算平均梯度叫批量梯度下降BGD。但数据量大时太慢实际常用方法每次用多少数据梯度批量梯度下降全部 N 条精确平均随机梯度下降 SGD1 条单条梯度有噪声小批量梯度下降一小批如 32 条小批平均小批量是实践中最常用的每次取一批数据算这批的平均梯度更新一次 w。这样既有平均的效果又快。二、代码(涉及闭包/匿名函数有点绕)引入softmax在blog: 深度学习2:激活函数ReLU,softmax和恒等函数及激活函数的最终选择引入交叉熵在 blog 深度学习4:神经网络学习1:损失函数,交叉熵误差引用梯度方法在blog: 深度学习5:神经网络学习2:数值微分偏导梯度fromcommon.functionsimportsoftmax,cross_entropyfromcommon.gradientimportnumerical_gradientimportnumpyasnp# 定义一个简单神经网络类classSimpleNet:# 初始化def__init__(self):self.Wnp.random.randn(2,3)# 前向传播defforward(self,X):aX self.W ysoftmax(a)returny# 计算损失值defloss(self,x,t):yself.forward(x)losscross_entropy(y,t)returnloss# 主流程if__name____main__:# 1. 定义数据xnp.array([0.6,0.9])tnp.array([0,0,1])# 2. 定义神经网络模型netSimpleNet()# 3. 计算梯度在loss里面已经使用x和w算出预测值了# lambda 不接收参数 ≠ W 没被用到# w就是net对象的属性 间接参与计算在loss 先执行forward时候用了w然后才是交叉熵算损失flambda_:net.loss(x,t)# 3. 计算梯度(这里传net.W 进去微调和forward里读取的是同一个)# 所以 微调一下 x[i] tmp h fxh1 f(x)这里就重新用修改后的w走一遍forward和交叉熵算损失gradwnumerical_gradient(f,net.W)print(gradw)一定搞明白f(x)这个调用里x虽然传进去了但lambda根本没用它可实际上还是影响了loss因为numerical_gradient改的是net.W本身而lambda内部走forward时用的是self.W。numerical_gradient 里改 x[i]其实就是 net.W[i]↓调用 f(net.W)↓f 忽略参数执行 net.loss(x, t)↓forward 里 x self.W ← 这里的 self.W 已经被改过了↓softmax → cross_entropy → 返回新的 loss三、整个链路的完整逻辑核心就是xt真实值不能改不断修改w看损失函数最后算每个权重的梯度X 是靶子数据是客观给定的你不能改。w 是瞄准方式模型参数你能改也应该改。损失函数衡量“当前 w 下预测和真实值差多少”。主流程x, t 是数据net.W 是权重f lambda _: net.loss(x, t) # 把“数据固定住”只留下 W 可动numerical_gradient(f, net.W) # 让 W 的每个元素微调看 loss 变化进入numerical_gradient(f, net.W)x形参 net.W循环每个 W 元素微调 W[i] → f(W) → net.loss(x, t) → 用 self.W也就是被微调后的 W算 loss计算差分 → 得到该 W 元素的梯度

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑