Pytorch 深度学习实践第4讲

三、反向传播

课程链接:Pytorch 深度学习实践——反向传播

1、两层的神经网络

Pytorch 深度学习实践第4讲_第1张图片

问题:每一层输出的都是上一层输入的线性函数,不管加多少隐藏层的神经网络,最后的output也只是input的线性组合。

Pytorch 深度学习实践第4讲_第2张图片

解决方法:每一层神经网络都需要一个非线性函数单元Nonlinear Function

2、链式法则(Chain Rule)

把复合函数上每一步的偏导数进行累积,以求得最终的导数。

①构建计算图(Forward)

②计算局部导数

③导数通过节点传递,采用链式法则计算导数(Backward)

Pytorch 深度学习实践第4讲_第3张图片

以线性模型为例:

Pytorch 深度学习实践第4讲_第4张图片

3、Tensor(张量)

在Pytorch中,Tensor是构建动态计算图的重要成分。它包括存储在节点的权重和上述提到的局部导数。

Ⅰ、课程作业:构建线性模型y=w*x的计算图
代码实现:
#Construct Computation Graph
import torch

x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

w = torch.Tensor([1.0])
w.requires_grad = True

def forward(x):
    return w * x    #w是一个Tensor,因此在乘法运算时,x也转换为Tensor变量,所得的结果也是Tensor变量

def loss(t, y):
    return (t - y) ** 2

for epoch in range(100):
    for x, y in zip(x_data, y_data):
        t = forward(x)
        l = loss(t, y)  #l是一个tensor
        l.backward()    #backward会反向计算梯度
        print('grad:' + '\t' + str(x) + '\t' + str(y) + '\t' + str(format(w.grad.item(), '.2f')))    #把grad里的值变为标量
        w.data -= 0.01 * w.grad.data    #这里注意要取grad里的data,因为grad是个Tensor变量
        w.grad.data.zero_() #由于backward计算完梯度后会一直累加,所以在更新完w后需要把w的梯度重置为0
    if(epoch % 10 == 0):
        print('Epoch =' + '\t' + str(epoch) + '\t' + str(format(l.item(), '.4f')))

print("predict after training ", 4, forward(4).item())

结果展示:

Epoch = 0 7.3159
Epoch = 10 0.0174
Epoch = 20 0.0000
Epoch = 30 0.0000
Epoch = 40 0.0000
Epoch = 50 0.0000
Epoch = 60 0.0000
Epoch = 70 0.0000
Epoch = 80 0.0000
Epoch = 90 0.0000
predict after training 4 7.999998569488525

Ⅱ、课后作业:构建二次模型 y = w 1 x 2 + w 2 x + b y=w_1x^2+w_2x+b y=w1x2+w2x+b的计算图
代码实现:
#Construct Computation Graph
import torch

x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

w1 = torch.Tensor([1.0])#初始权值
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(t, y):
    return (t - y) ** 2

for epoch in range(100):
    for x, y in zip(x_data, y_data):
        t = forward(x)
        l = loss(t, y)  #l是一个tensor
        l.backward()    #backward会反向计算梯度
        #print('grad:' + '\t' + str(x) + '\t' + str(y) + '\t' + str(format(w.grad.item(), '.2f')))    #把grad里的值变为标量
        w1.data -= 0.01 * w1.grad.data    #这里注意要取grad里的data,因为grad是个Tensor变量
        w2.data -= 0.01 * w2.grad.data
        b.data -= 0.01 * b.grad.data
        w1.grad.data.zero_()
        w2.grad.data.zero_()
        b.grad.data.zero_()
    if(epoch % 10 == 0):
        print('Epoch =' + '\t' + str(epoch) + '\t' + str(format(l.item(), '.4f')))

print("predict after training ", 4, forward(4).item())

结果展示:

Epoch = 0 18.3218
Epoch = 10 0.0285
Epoch = 20 0.0191
Epoch = 30 0.0142
Epoch = 40 0.0112
Epoch = 50 0.0094
Epoch = 60 0.0082
Epoch = 70 0.0074
Epoch = 80 0.0069
Epoch = 90 0.0066
predict after training 4 8.544171333312988

结果分析:在构建完二次模型的计算图后,可以看到预测x=4时的 y ^ \hat{y} y^还存在误差(y=8),这是由于数据集是线性模型的数据集导致的,现在把数据集改为如下:
x_data = [1.0, 2.0, 3.0]
y_data = [3.0, 7.0, 13.0]

w1 = torch.Tensor([0.5])#初始权值
w1.requires_grad = True#计算梯度,默认是不计算的
w2 = torch.Tensor([0.5])
w2.requires_grad = True
b = torch.Tensor([0.5])
b.requires_grad = True

显然这个数据集对应的二次模型为 y = x 2 + x + 1 y=x^2+x+1 y=x2+x+1,权值初始都改为0.5
再来看一下结果:
Epoch = 0 10.7623
Epoch = 10 0.0334
Epoch = 20 0.0152
Epoch = 30 0.0068
Epoch = 40 0.0030
Epoch = 50 0.0013
Epoch = 60 0.0006
Epoch = 70 0.0002
Epoch = 80 0.0001
Epoch = 90 0.0000
predict after training 4 20.987239837646484

结果分析:可以看到这时x=4的 y ^ \hat{y} y^预测准确。

你可能感兴趣的:(神经网络,深度学习,python)