使用Pytorch搭建简易神经网络

本文目录 

一、网络模型构建

二、手动实现梯度下降

三、自动梯度

四、使用torch.nn包进行模型搭建

五、使用torch.optim实现梯度下降过程中的参数优化

 

一、网络模型构建

    本文将使用pytorch构建一个简易的神经网络,并使用梯度下降算法对模型进行监督学习训练。

    本简易神经网络有一个数据输入层、一个隐藏层和一个数据输出层构成。其中,每个输入数据包含十个特征,可以认为输入数据是一个十维向量;经隐藏层处理后保留十五个特征,最后经数据输出层输出十个特征值。

简易神经网络

    无需考虑该神经网络的实际意义,本文仅对搭建神经网络作一示例。

二、手动实现梯度下降

    可以说是最朴素的方法了,手动实现梯度下降。batch_n是在一个批次中输入数据的数量,hidden_layer定义经过隐藏层后保留的数据特征的个数,input_data是每个数据包含的特征个数,output_data是输出数据所包含的特征个数。

    #7~8(#是行号)使用torch中的randn函数随机生成训练集<x, y>,虽然这并不是一个十分恰当的方法,但用来做测试是足够的。

    #10~11使用randn函数初始化权值w1、w2。

    epoch_n指定训练次数,learning_rate定义学习率。接下来我们用一个循环对神经网络做20次训练。我们使用torch中自带的矩阵乘法方式实现神经网络中的前向传播,然后通过链式求导法则分别求偏导数手动实现后向传播。

    注意,#18对Tensor作clamp操作相当于一个ReLU激活函数。

import torch
batch_n = 100
hidden_layer = 15
input_data = 10
output_data = 5

x = torch.randn(batch_n, input_data)
y = torch.randn(batch_n, output_data)

w1 = torch.randn(input_data, hidden_layer)
w2 = torch.randn(hidden_layer, output_data)

epoch_n = 20
learning_rate = 1e-6

for epoch in range(epoch_n):
    h1 = x.mm(w1)
    h1 = h1.clamp(min = 0)
    y_pred = h1.mm(w2)

    loss = (y_pred-y).pow(2).sum()
    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())
    grad_h.clamp(min = 0)
    grad_w1 = x.t().mm(grad_h)

    w1 -= learning_rate*grad_w1
    w2 -= learning_rate*grad_w2

    以下是运行效果。

Epoch:0, Loss:1.0563
Epoch:1, Loss:1.0350
Epoch:2, Loss:1.0142
Epoch:3, Loss:0.9938
Epoch:4, Loss:0.9740
Epoch:5, Loss:0.9547
Epoch:6, Loss:0.9358
Epoch:7, Loss:0.9174
Epoch:8, Loss:0.8995
Epoch:9, Loss:0.8820
Epoch:10, Loss:0.8649
Epoch:11, Loss:0.8482
Epoch:12, Loss:0.8318
Epoch:13, Loss:0.8158
Epoch:14, Loss:0.8003
Epoch:15, Loss:0.7850
Epoch:16, Loss:0.7700
Epoch:17, Loss:0.7553
Epoch:18, Loss:0.7409
Epoch:19, Loss:0.7269

Process finished with exit code 0

三、自动梯度

    手动计算偏导数有时是非常费解的(尤其是神经网络非常复杂的情况下)。torch.autograd包所提供的函数可以实现神经网络后向传播中的链式求导,我们可以调用这些函数使问题大大简化。

    在手动计算梯度代码的基础上,我们只需要把我们之前定义的Tensor封装到Variable类当中。封装之后,计算图中的每一个节点就是一个Variable对象。如果用X表示我们选中的对象,X.data代表Tensor数据类型的变量,X.grad代表对象的梯度,通过X.grad.data可以访问梯度的值。

    改进后的代码如下。

    #8-12中requires_grad参数的值决定了这个Variable对象是否需要计算梯度信息。#18进行前向传播,pytorch自动构建计算图,#19计算损失,#22调用loss.backward()函数进行后向传播,pytorch即可按照构建好的计算图自动计算梯度,#24-25更新权值(即让神经网络进行“学习”,#27-28将梯度置0。

import torch
from torch.autograd import Variable
batch_n = 100
hidden_layer = 15
input_data = 10
output_data = 5

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 = 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:1.0718
Epoch:1, Loss:1.0501
Epoch:2, Loss:1.0289
Epoch:3, Loss:1.0082
Epoch:4, Loss:0.9880
Epoch:5, Loss:0.9683
Epoch:6, Loss:0.9490
Epoch:7, Loss:0.9302
Epoch:8, Loss:0.9118
Epoch:9, Loss:0.8938
Epoch:10, Loss:0.8763
Epoch:11, Loss:0.8591
Epoch:12, Loss:0.8423
Epoch:13, Loss:0.8260
Epoch:14, Loss:0.8099
Epoch:15, Loss:0.7943
Epoch:16, Loss:0.7790
Epoch:17, Loss:0.7641
Epoch:18, Loss:0.7495
Epoch:19, Loss:0.7352

Process finished with exit code 0

四、使用torch.nn包进行模型搭建

    torch.nn.Sequential类是torch.nn中的一种序列容器,通过在容器中嵌套各种实现神经网络中具体功能的类,来完成对神经网络模型的搭建。

    torch.nn.Sequential括号内的内容就是我们搭建的神经网络的具体结构,这里先通过torch.nn.Linear(input_data, hidden_layer)完成输入层到隐藏层的线性变换,然后经过激活函数及torch.nn.Linear(hidden_layer, output_data)完成隐藏层到输出层的线性变换。这于上文中手动构建的神经网络模型是相一致的。

models = torch.nn.Sequential(
    torch.nn.Linear(input_data, hidden_layer),
    torch.nn.ReLU(),
    torch.nn.Linear(hidden_layer, output_data)
)

五、使用torch.optim实现梯度下降过程中的参数优化

    使用torch.nn.MSELoss()均方误差函数来计算损失,使用torch.optim.Adam类作为我们的模型参数优化函数。

import torch
from torch.autograd import Variable

batch_n = 100
hidden_layer = 15
input_data = 10
output_data = 5

x = Variable(torch.randn(batch_n, input_data), requires_grad=False)
y = Variable(torch.randn(batch_n, output_data), requires_grad=False)

models = torch.nn.Sequential(
    torch.nn.Linear(input_data, hidden_layer),
    torch.nn.ReLU(),
    torch.nn.Linear(hidden_layer, output_data)
)

epoch_n = 20
learning_rate = 1e-6
loss_f = torch.nn.MSELoss()

optimzer = torch.optim.Adam(models.parameters(), lr = learning_rate)

for epoch in range(epoch_n):
    y_pred = models(x)
    loss = loss_f(y_pred, y)
    print("Epoch:{}, Loss:{:.4f}".format(epoch, loss))

    optimzer.zero_grad()
    loss.backward()
    
    optimzer.step()

以下是运行效果

Epoch:0, Loss:0.9989
Epoch:1, Loss:0.9781
Epoch:2, Loss:0.9578
Epoch:3, Loss:0.9380
Epoch:4, Loss:0.9187
Epoch:5, Loss:0.8999
Epoch:6, Loss:0.8816
Epoch:7, Loss:0.8637
Epoch:8, Loss:0.8462
Epoch:9, Loss:0.8291
Epoch:10, Loss:0.8126
Epoch:11, Loss:0.7965
Epoch:12, Loss:0.7808
Epoch:13, Loss:0.7655
Epoch:14, Loss:0.7505
Epoch:15, Loss:0.7359
Epoch:16, Loss:0.7217
Epoch:17, Loss:0.7077
Epoch:18, Loss:0.6942
Epoch:19, Loss:0.6808

Process finished with exit code 0

 

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值