pytorch 两层神经网络的实现(含relu激励方程的反向传播推导过程)

神经网络的典型处理如下所示:

  1. 定义可学习参数的网络结构(堆叠各层和层的设计);
  2. 数据集的制作和输入;
  3. 对输入进行处理(由定义的网络层进行处理),主要体现在网络的前向传播;
  4. 计算loss ,由Loss层计算;
  5. 反向传播求梯度;
  6. 根据梯度改变参数值,最简单的实现方式(SGD)为:
    weight = weight - learning_rate * gradient

使用pytorch和auto_grad(torch自动求导功能):

import torch
#import numpy
#from torch.autograd import Variable
EPOCH = 500
LEARNING_RATE = 1e-6
N , D_in , H , D_out = 64 , 1000, 100 , 10
# N代表的是样本个数,D_in是样本的维度,H是隐藏层的维度,D_out是输出层的维度
X = torch.randn(N,D_in)
Y = torch.randn(N,D_out)

# 先用随机值初始化两层神经网络的权重
w1 = torch.randn(D_in,H,requires_grad=True)
w2 = torch.randn(H,D_out,requires_grad=True)

"""h = w1 * x
h_relu = relu(h)
y = w2 * x"""


for step in range(EPOCH):
    #前向传播
    h = torch.mm(X, w1)  # 隐层  h = w1 * x
    h_relu = h.clamp(min=0)  # relu 将小于0的部分修正为0 大于0的部分则不变
    y_pred = torch.mm(h_relu, w2)  # 输出层  y = w2 * h_relu
    
    
    # 损失函数计算误差
    loss = (y_pred - Y).pow(2).sum()
    if step % 100 == 0:
        print('epoch: {} loss: {:.5f}'.format(step, loss.item()))#loss为(1,)的tensor

    
    # 反向传播 计算导数
    loss.backward() # 会自动计算所有参数的导数(包括W1、W2、X)
    
    
    #更新参数
    with torch.no_grad():
        #随机梯度下降
        w1 -= LEARNING_RATE * w1.grad
        w2 -= LEARNING_RATE * w2.grad
        #更新完梯度之后要手动置0。不置0会一直叠加
        w1.grad.zero_()
        w2.grad.zero_()

使用pytorch(反向传播要自己求导):

import torch

EPOCH = 500
LEARNING_RATE = 1e-6
#超参数初始化
N , D_in , H , D_out = 64 , 1000, 100 , 10 # N代表的是样本个数,D_in是样本的维度,H是隐藏层的维度,D_out是输出层的维度

#训练数据和参数初始化
X = torch.randn(N,D_in)
Y = torch.randn(N,D_out)

# 先用随机值初始化两层神经网络的权重
w1 = torch.randn(D_in,H)
w2 = torch.randn(H,D_out)
#print("X:",X,"Y:",Y,w1,w2)

for step in range(500): 
    #前向传播
    h = X.mm(w1) #(N,H)
    h_relu = h.clamp(min=0)#(N,H)
    y_pred = h_relu.mm(w2) #(N,D_out)
    
    
    #定义损失函数
    loss = (y_pred - Y).pow(2).sum().item()
    if step % 100 == 0:
        print('epoch: {} loss: {:.5f}'.format(step, loss))#loss为(1,)的tensor

    #反向传播
    grad_y_pred = 2.0 * (y_pred - Y)#(N,D_out)
    grad_w2 = h_relu.t().mm(grad_y_pred)#(H,D_out)
    grad_h_relu = grad_y_pred.mm(w2.t())#(N,H)
    grad_h[h > 0] = grad_h_relu[h > 0].clone()#大于0时导数不变
    grad_h[h < 0] = 0#小于0时导数变0
    grad_w1 = X.t().mm(grad_h)#要grad_w1的矩阵维度和w1维度相同,才能相减

    #参数更新
    w1 -= LEARNING_RATE * grad_w1
    w2 -= LEARNING_RATE * grad_w2

这种写法,反向传播的求导是最大的难点。需要理解正向传播和反向传播来推导公式,再把公式用代码实现。最好需要看一下吴恩达的机器学习视频的前三章(代价函数和梯度求导)和神经网络部分,理解反向传播的计算方法。但是它的视频的激励函数不同,我们需要针对本代码中的relu函数来实现反向传播。

这里我贴出了手写的推导过程:

pytorch 两层神经网络的实现(含relu激励方程的反向传播推导过程)_第1张图片
下面是对神经网络里面的一些tensor进行输出,从维度来理解

import torch
lr = 1e-6
EPOCH = 500
LEARNING_RATE = 1e-6
#超参数初始化
N , D_in , H , D_out = 3 , 4, 2 ,1 # N代表的是样本个数,D_in是样本的维度,H是隐藏层的维度,D_out是输出层的维度
#训练数据和参数初始化
X = torch.randn(N,D_in)
Y = torch.randn(N,D_out)
# 先用随机值初始化两层神经网络的权重
w1 = torch.randn(D_in,H)
w2 = torch.randn(H,D_out)

print("X:",X)#3样本 4特征
print("Y:",Y)#3结果
print("w1:",w1)
print("w2",w2)

h = X.mm(w1) 
print("h:",h)
h_relu = h.clamp(min=0)#(N,h_dim)
print("h_relu",h_relu)

附上运行结果和个人理解:

X: tensor([[ 1.3393, -0.3668, -0.3531,  1.4490],
        [-0.2834,  0.3056,  1.0691,  1.7448],
        [ 0.1956,  0.9079,  0.4525, -1.1220]])
Y: tensor([[-1.8117],
        [-0.4406],
        [ 1.1850]])
w1: tensor([[ 1.4459, -0.1429],
        [-0.8366, -0.5614],
        [-1.4148, -0.4373],
        [ 0.4911, -1.1529]])
w2 tensor([[-0.6083],
        [-0.2623]])
        
h: tensor([[ 3.4545, -1.5016],
        [-1.3210, -2.6101],
        [-1.6679,  0.5581]])
h_relu tensor([[3.4545, 0.0000],
        [0.0000, 0.0000],
        [0.0000, 0.5581]])
  • 神经网络的示意图是以一个特征(维度)为一个单元,而不是变量。
  • X有三个变量,每个变量有四个特征(维度)。W1分别对四个特征的每个特征有两种权值
  • 隐藏层有三个变量,两个单元(维度)
  • 将变量的4种特征×权值1相加之后,就得到了隐藏层单元里这个对应变量的特征值1
  • 将变量的4种特征×权值2相加之后,就得到了隐藏层单元里这个对应变量的特征值2

参考:

  1. 吴恩达机器学习视频:https://www.bilibili.com/video/av50747658?from=search&seid=8008773056378130405
  2. https://blog.csdn.net/qq_30057549/article/details/103018003
  3. 个人的针对吴恩达机器学习视频的笔记(下一篇推出,参考修改自黄海广博士)

最后

其实这已经是年初1月做的了, 距离现在已经很久啦。 如今想来, 这依然是入门深度学习最好的实践之一 。 入门深度学习的第一份代码,应该是这个。

然后吴恩达的机器学习视频也在上半年看完了,我是在黄海广博士的博客上稍作修改我的吴恩达机器学习笔记的。

但是后来发现,本地的markdown博客并不能在csdn上直接展示,里面的图很难传。就不更新啦,有需要可以联系我要。

目前我即将入读博士,如果对机器学习或自然语言处理感兴趣,欢迎关注我的知乎一起学习交流:
https://www.zhihu.com/people/da-shu-22-92-78

你可能感兴趣的:(python,pytorch,神经网络,机器学习,随机梯度下降,深度学习)