Pytorch深度学习实践笔记 --- 反向传播Back Propagation 前情提要梯度下降算法 Gradient DescentGradient梯度就是对cost(w)求倒数 g ∂cost(w)/∂w 代表当前函数cost(w)的趋势Update w w - a * ga --- 学习率 w - a * ∂cost(w)/∂w 梯度开始下降迭代过程就是根据梯度实现若g0此时cost(w)单调减则w若g0cost(w)单调增则w都是往下降方向走由于本质是贪心所以不一定得到全局最优而是局部最优两者。x_data [1.0, 2.0, 3.0] y_data [2.0, 4.0, 6.0] w 1 def forward(x): return w * x def cost(xs, ys): # 传进来的是x_data和y_data的列表 cost 0 for x, y in zip(xs, ys): # 遍历两个列表 y_pred forward(x) cost (y_pred - y) ** 2 return cost / len(xs) def gradient(xs, ys): grad 0 for x, y in zip(xs, ys): grad 2 * x * (x * w - y) # 对cost求导数 化简后 得 return grad / len(xs) a 0.01 # 学习率 for epoch in range(1, 10, 1): cost_val cost(x_data, y_data) grad_val gradient(x_data, y_data) w w - a * grad_val print(fEpoch {epoch}, w {w}, loss {cost_val}) print(-------------------------------------------)随机梯度下降Stochastic Gradient Descent --- SGD该算法源于梯度下降算法中的求和导致难以并行运算只求损失loss可以提高效率。∂loss/∂w d(y_pred - y)^2 / dw 2 * x * (x * w - y)w w - a * ∂loss/∂wx_data [1.0, 2.0, 3.0] y_data [2.0, 4.0, 6.0] w 1.0 def forward(x): return x * w def loss(x, y): y_pred forward(x) return (y_pred - y) ** 2 # y_pred与实际y比较 来算loss def gradient(x, y): return 2.0 * x * (x * w - y) # 对loss求导数化简后 得 for epoch in range(1, 10, 1): for x, y in zip(x_data, y_data): grad_val gradient(x, y) w w - 0.01 * grad_val # update print(fEpoch {epoch}, w {w}, loss {loss(x, y)})反向传播 Back Propagation前提多层神经网络的局部梯度传递目的是为了求loss关于w的导数来算梯度即 ∂loss/∂w数学原理链式求导对于两层神经网络y_pred W2(W1*X b1) b2第一层 第二层 W2*W1*X (W2*b1 b2) W*X b注根据以上推导无论几层都能线性表示所以就没有意义了于是引入nonlinear function。计算步骤1、create computational graph(forward)x,w - f - f(x,w) - z - ... - loss2、local gradient 局部梯度 --- 正向目标算出损失loss - z ( ∂L/∂z ) - f( ∂z/∂x , ∂z/∂w ) - x( ∂L/∂x ∂L/∂z * ∂z/∂x ) ,w( ∂L/∂w ... )3、backward --- 反向目标求梯度通过反向传播进行链式求导更新梯度以上步骤的进行目的是求 ∂loss/∂wx_data [1.0, 2.0, 3.0] y_data [2.0, 4.0, 6.0] w1 torch.Tensor([1.0]) # 创建一个张量wTensor中包含data和graddata和grad也是Tensor w1.requires_grad True # 需要计算梯度 w2 torch.Tensor([1.0]) w2.requires_grad True b torch.Tensor([1.0]) b.requires_grad True def forward(x): return w1 * x ** 2 w2 * x b def loss(x, y): # 构建计算图, tensor 做计算就会构建计算图 y_pred forward(x) return (y_pred - y) ** 2 def gradient(x, y): # ∂loss/∂w return 2.0 * x * (x * w - y) print(Predict (before training),4,forward(4)) a 0.01 # 设置学习率 for epoch in range(1, 100, 1): for x, y in zip(x_data, y_data): l loss(x, y) l.backward() # 不断计算梯度 print(\tgrad:, x, y, w1.grad.item(), w2.grad.item(), b.grad.item())#梯度值的标量数值.item() 方法的作用是将只包含一个元素的 PyTorch tensor 转换为普通的 Python 数值类型如 float。这样做是为了打印时更清晰显示的是具体的数字而不是 tensor 对象。 # 注意这里的grad是一个tensor所以要取他的data w1.data w1.data - a * w1.grad.data w2.data w2.data - a * w2.grad.data b.data b.data - a * b.grad.data # 释放之前计算的梯度 w1.grad.data.zero_() w2.grad.data.zero_() b.grad.data.zero_() print(Epoch:, epoch, l.item()) print(predict (after training), 4, forward(4).item())