使用自动梯度搭建一个二层结构的神经网络模型


前面已经 搭建了一个简易神经网络模型,接下来使用自动梯度搭建一个二层结构的神经网络模型。

1 torch.autograd 和 Variable

通过使用 torch.autograd(主要功能是完成神经网络后向传播中的链式求导) 包,可以使模型参数自动计算在优化过程中需要用到的梯度值,在很大程度上帮助降低了实现后向传播代码的复杂度。

实现自动梯度功能的过程大致为:先通过输入的 Tensor 数据类型的变量在神经网络的前向传播过程中生成一张计算图,然后根据这个计算图和输出结果准确计算出每个参数需要更新的梯度,并通过完成后向传播完成对参数的梯度更新。

在实践中完成自动梯度需要用到 torch.autograd 包中的 Variable 类对我们定义的 Tensor数据类型变量进行封装,在封装后,计算图中的各个节点就是一个 Variable 对象,这样才能应用自动梯度的功能。

'''导入包'''
import torch 
from torch.autograd import Variable 
batch_n = 100 
hidden_layer = 100 
input_data = 1000 
output_data = 10

'''用 Variable 类对 Tensor 数据类型变量进行封装'''
x = Variable(torch.randn(batch_n, input_data), requires_grad = False)  #100*1000
y = Variable(torch.randn(batch_n, output_data), requires_grad = False)  #100*10
w1 = Variable(torch.randn(input_data, hidden_layer), requires_grad = True)  #1000*100
w2 = Variable(torch.randn(hidden_layer, output_data), requires_grad = True)  #100*10

epoch_n = 20 
learning_rate = 1e-6

'''新的模型训练和参数优化的代码'''
for epoch in range(epoch_n): 
    y_pred = x.mm(w1).clamp(min = 0).mm(w2) 
    loss = (y_pred - y).pow(2).sum() 
    print("Epoch:{}, Loss:{:.4f}".format(epoch,loss))
    loss.backward() 
 
    w1.data -= learning_rate*w1.grad.data 
    w2.data -= learning_rate*w2.grad.data 
 
    w1.grad.data.zero_() 
    w2.grad.data.zero_()
Epoch:0, Loss:36054716.0000
Epoch:1, Loss:46005456.0000
Epoch:2, Loss:145356976.0000
Epoch:3, Loss:482522144.0000
Epoch:4, Loss:511481344.0000
Epoch:5, Loss:5381819.0000
Epoch:6, Loss:3527648.0000
Epoch:7, Loss:2548170.7500
Epoch:8, Loss:1980495.5000
Epoch:9, Loss:1623881.0000
Epoch:10, Loss:1383441.8750
Epoch:11, Loss:1210102.3750
Epoch:12, Loss:1077163.5000
Epoch:13, Loss:970541.5000
Epoch:14, Loss:881934.3750
Epoch:15, Loss:806076.7500
Epoch:16, Loss:740382.0000
Epoch:17, Loss:682604.8750
Epoch:18, Loss:631387.1875
Epoch:19, Loss:585655.7500

和之前的代码相比,当前的代码更简洁了,之前代码中的后向传播计算部分变成了新代码中的 loss.backward(),这个函数的功能在于让模型根据计算图自动计算每个节点的梯度值并根据需求进行保留。

2 自定义传播函数

还可以通过构建一个继承了 torch.nn.Module的新类,来完成对前向传播函数和后向传播函数的重写。

在这个新类中,我们使用 forward作为前向传播函数的关键字,使用 backward 作为后向传播函数的关键字。

2.1 搭建简易神经网络

'''导入包'''
import torch 
from torch.autograd import Variable 
batch_n = 64 
hidden_layer = 100 
input_data = 1000 
output_data = 10

'''何定义我们的前向传播 forward 函数和后向传播backward 函数'''
class Model(torch.nn.Module):  #类继承
    def __init__(self):  #类的初始化
        super(Model, self).__init__() 
        
    def forward(self, input, w1, w2):  #forward 函数,实现了模型的前向传播中的矩阵运算
        x = torch.mm(input, w1)
        x = torch.clamp(x, min = 0) 
        x =torch.mm(x, w2) 
        return x 
    
    def backward(self):  #backward 函数,实现了模型的后向传播中的自动梯度计算,后向传播如果没有特别的需求,则在一般情况下不用进行调整
        pass
    
model = Model()  #调用类

2.2 训练模型、参数优化

'''对模型进行训练和对参数进行优化'''
x = Variable(torch.randn(batch_n, input_data), requires_grad = False) 
y = Variable(torch.randn(batch_n, output_data), requires_grad = False) 
w1 = Variable(torch.randn(input_data, hidden_layer), requires_grad = True) 
w2 = Variable(torch.randn(hidden_layer, output_data) ,requires_grad = True) 

epoch_n = 30 
learning_rate = 1e-6 

for epoch in range(epoch_n): 
    y_pred = model(x, w1, w2)  #输出模型预测值
    loss = (y_pred - y).pow(2).sum() 
    print("Epoch:{}, Loss:{:.4f}".format(epoch,loss)) 
    loss.backward() 
    w1.data -= learning_rate * w1.grad.data
    w2.data -= learning_rate * w2.grad.data 
    
    w1.grad.data.zero_() 
    w2.grad.data.zero_()
Epoch:0, Loss:30154982.0000
Epoch:1, Loss:27915354.0000
Epoch:2, Loss:27383836.0000
Epoch:3, Loss:24799186.0000
Epoch:4, Loss:19323030.0000
Epoch:5, Loss:12777702.0000
Epoch:6, Loss:7516660.0000
Epoch:7, Loss:4245948.0000
Epoch:8, Loss:2488885.0000
Epoch:9, Loss:1586501.0000
Epoch:10, Loss:1111118.8750
Epoch:11, Loss:840452.1875
Epoch:12, Loss:670228.2500
Epoch:13, Loss:552621.6875
Epoch:14, Loss:465184.7188
Epoch:15, Loss:396748.5625
Epoch:16, Loss:341388.4688
Epoch:17, Loss:295734.4375
Epoch:18, Loss:257580.7188
Epoch:19, Loss:225402.2812
Epoch:20, Loss:198073.2188
Epoch:21, Loss:174757.3594
Epoch:22, Loss:154748.5938
Epoch:23, Loss:137464.6094
Epoch:24, Loss:122470.6094
Epoch:25, Loss:109405.7500
Epoch:26, Loss:97988.0469
Epoch:27, Loss:87962.7266
Epoch:28, Loss:79135.0156
Epoch:29, Loss:71336.7109

从结果来看,对参数的优化同样在顺利进行,每次输出的 loss 值也在逐渐减小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值