使用基本的函数搭建一个两层神经网络(输入层不算做一层)
import torch batch_n = 100 hidden_layer = 100 input_data = 1000 output_data = 10 x = torch.randn(batch_n, input_data) # 输入的样本特征 y = torch.randn(batch_n, output_data) # 输入的样本值 w1 = torch.randn(input_data, hidden_layer) # 参数1 w2 = torch.randn(hidden_layer, output_data) # 参数2 epoch_n = 20 learning_rate = 0.1**6 for epoch in range(epoch_n): h1 = x.mm(w1) # 100*100 # 进行前向传播第一层,x*w1 求出 h1(batch_n ,input_date) h1 = h1.clamp(min=0) # 裁剪结果h1 相当于使用ReLu 激活函数 y_pred = h1.mm(w2) # 100*10 #前向传播第二层,h1*w2 求出 y_pred(batch_n,output_data) loss = (y_pred - y).pow(2).sum() # 计算损失 求(y_pred - y)的平方的和,y_pred ,y是大小为(batch_n,output_data)的矩阵 print("Epoch:{},Loss:{:.4f}".format(epoch,loss)) # 输出批次和损失 grad_y_pred = 2*(y_pred - y) grad_w2 = h1.t().mm(grad_y_pred) # 第二层网络求导 第一层结果的转置乘预测结果,得到梯度 grad_h = grad_y_pred.clone() # 克隆 grad_h = grad_h.mm(w2.t()) # 链式求导1 预测结果乘第二层网络的系数,得到导数 grad_h.clamp_(min=0) # ReLu grad_w1 = x.t().mm(grad_h) # 链式求导2 x的转置乘求导1的结果 得到梯度 w1 -= learning_rate*grad_w1 # 修改参数,学习率乘梯度 w2 -= learning_rate*grad_w2
torch.autograd包
主要用于完成神经网络后向传播中的链式求导
Variable类
torch.autograd包中的Variable类,将Tensor数据类型变量进行封装。计算图中的每个节点变为一个Variable对象,来应用自动梯度。
Variable对象X中, X.data为Tensor数据类型变量,X.grad代表X的梯度,梯度的值为X.grad.data。
loss.backward()
让模型根据计算图自动计算每个节点的梯度值。
import torch from torch.autograd import Variable batch_n = 100 hidden_layer = 100 input_data = 1000 output_data = 10 class Model(torch.nn.Module): # 继承torch.nn.Module 重写网络的前向传播和后向传播 def __init__(self): super(Model,self).__init__() def forward(self, input, w1, w2): # 前项传播 x = torch.mm(input, w1) x = torch.clamp(x, min=0) x = torch.mm(x, w2) return x def backward(self): # 跳过,主函数中用loss.backward()进行反向求导 pass model = Model() x = Variable(torch.randn(batch_n, input_data), requires_grad=False) # x封装为节点,设置为不自动求导 y = Variable(torch.randn(batch_n, output_data), requires_grad=False) w1 = Variable(torch.randn(input_data, hidden_layer), requires_grad=True) # w1封装为节点,设置为自动求导 w2 = Variable(torch.randn(hidden_layer, output_data), requires_grad=True) epoch_n = 20 learning_rate = 0.1**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.data[0])) loss.backward() # 反向传播 w1.data -= learning_rate*w1.grad.data # 进行学习,更新参数 w2.data -= learning_rate*w2.grad.data w1.grad.data.zero_() # 梯度重置 w2.grad.data.zero_()