【Pytorch学习】用pytorch搭建第一个神经网络

简述

虽然使用过pytorch来搭建GANs,但是对于Pytorch其实还是不是很熟,这里想系统的学习下。顺便再来做一下笔记。

学习网站

https://morvanzhou.github.io/tutorials/machine-learning/torch/3-01-regression/

大家直接看原文好了。这里我自己随便写写便于我自己记忆。

拟合过程

数据

  • torch.unsqueeze(),会扩展这个维度。然后dim选择的方向是列的方向。这里,就是将[1,2,3]变成了[[1], [2], [3]] 类似于这样的操作。
  • torch.rand() 随机数,范围为(0,1)然后,输入的内容为tuple表示规模
  • 因为有结构的问题,所以,这里就直接使用了.data先获取数据之后,再用numpy()来转成numpy中的数据类型。
  • 画图的话是基础,这里就不讲了。
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F     # 激励函数都在这

x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1)  # x data (tensor), shape=(100, 1)
y = x.pow(2) + 0.2*torch.rand(x.size())                 # noisy y data (tensor), shape=(100, 1)

# 画图
plt.scatter(x.data.numpy(), y.data.numpy())
plt.show()

建立神经网络

这里会写一个类。就是神经网络类。

  • 基类为torch.nn.Module

在pytorch的官方文档中写道

Base class for all neural network modules.
所有神经网络的基类
Your models should also subclass this class.
你的模型也需要是这个类的子类
Modules can also contain other Modules, allowing to nest them in a tree structure. You can assign the submodules as regular attributes:
Modules可以包括其他的模块,允许按照树形结构建造它。你也可以创立一个子模块,通过下面的方式。(其实文档下写的标准方法,跟下面的是一样的)

  • 通过super函数实现父类的初始化
  • 创建类变量,一个隐藏层的模型,一个输出层模型
  • 丢进去的两个参数,其实就都是。表示的是输入这个小模块的长度,再到输出这个小模块的长度。其实就说这个模型就是隐含着一个矩阵,做了一个矩阵乘法之后,就可以得到后面的东西了。
  • 重载了前向传播的函数内容。
  • 表示,前向传播的过程中,先经过隐藏层模型,再被relu的激活模型调用,之后,在通过输出层。这就是整个前向传播的流程了
class Net(torch.nn.Module):  # 继承 torch 的 Module
    def __init__(self, n_feature, n_hidden, n_output):
        super(Net, self).__init__()     # 继承 __init__ 功能
        # 定义每层用什么样的形式
        self.hidden = torch.nn.Linear(n_feature, n_hidden)   # 隐藏层线性输出
        self.predict = torch.nn.Linear(n_hidden, n_output)   # 输出层线性输出

    def forward(self, x):   # 这同时也是 Module 中的 forward 功能
        # 正向传播输入值, 神经网络分析出输出值
        x = F.relu(self.hidden(x))      # 激励函数(隐藏层的线性值)
        x = self.predict(x)             # 输出值
        return x

之后,我们就需要自己申明这样的一个对象了。

net = Net(n_feature=1, n_hidden=10, n_output=1)

意思就是输入层的节点数为1,隐藏层的节点为10,输出层的节点为1

因为输入层为x,而我们这里考虑的只是一个简单的函数拟合问题,当然,这里就只有一个节点啦。这里,我们想起来,为什么之前需要有unsqueeze()操作了

训练神经网络

操作其实非常粗糙

构建一个优化器和损失函数

  • 下面选择的优化方法是SGD(随机梯度下降),然后,学习率为0.2
  • MSELoss 其实就是 ∑ ( x i , y i ) ( x i − y i ) 2 \sum_{(xi, yi)}(x_i- y_i) ^2 (xi,yi)(xiyi)2。当然啦,有一个系数什么的。那个在确定了输入的集合的规模情况下,这个就是无关紧要的啦。
optimizer = torch.optim.SGD(net.parameters(), lr=0.2)  # 传入 net 的所有参数, 学习率
loss_func = torch.nn.MSELoss() # 预测值和真实值的误差计算公式 (均方差)

训练这个模型

for t in range(100):
    prediction = net(x)     # 喂给 net 训练数据 x, 输出预测值

    loss = loss_func(prediction, y)     # 计算两者的误差

    optimizer.zero_grad()   # 清空上一步的残余更新参数值
    loss.backward()         # 误差反向传播, 计算参数更新值
    optimizer.step()        # 将参数更新值施加到 net 的 parameters 上

到这里,其实整个模型就拟合完了。

完整代码(加上画图,生成gif)

  • 下面的包都是除了标准库自带的话,其他都是可以直接pip install
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F  # 激励函数都在这
import os
import shutil
import imageio

PNGFILE = './png/'
if not os.path.exists(PNGFILE):
    os.mkdir(PNGFILE)
else:
    shutil.rmtree(PNGFILE)
    os.mkdir(PNGFILE)
x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1)  # x data (tensor), shape=(100, 1)
y = x.pow(2) + 0.2 * torch.rand(x.size())  # noisy y data (tensor), shape=(100, 1)

# 画图
plt.scatter(x.data.numpy(), y.data.numpy())


class Net(torch.nn.Module):  # 继承 torch 的 Module
    def __init__(self, n_feature, n_hidden, n_output):
        super(Net, self).__init__()  # 继承 __init__ 功能
        # 定义每层用什么样的形式
        self.hidden = torch.nn.Linear(n_feature, n_hidden)  # 隐藏层线性输出
        self.predict = torch.nn.Linear(n_hidden, n_output)  # 输出层线性输出

    def forward(self, x):  # 这同时也是 Module 中的 forward 功能
        # 正向传播输入值, 神经网络分析出输出值
        x = F.relu(self.hidden(x))  # 激励函数(隐藏层的线性值)
        x = self.predict(x)  # 输出值
        return x


net = Net(1, 10, 1)
optimizer = torch.optim.SGD(net.parameters(), lr=.21)
loss_func = torch.nn.MSELoss()

name_list = []

for t in range(100):
    prediction = net(x)
    loss = loss_func(prediction, y)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if (t + 1) % 5:
        plt.cla()
        plt.scatter(x.data.numpy(), y.data.numpy())
        plt.plot(x.data.numpy(), prediction.data.numpy(), color='r')
        plt.text(0.5, 0, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 20, 'color': 'red'})
        plt.savefig(PNGFILE + '%d.png' % t)
        name_list.append(PNGFILE + '%d.png' % t)

generated_images = []
for png_path in name_list:
    generated_images.append(imageio.imread(png_path))
shutil.rmtree(PNGFILE)
imageio.mimsave('net.gif', generated_images, 'GIF', duration=0.2)

你可能感兴趣的:(Python,机器学习+深度学习+强化学习,机器学习+深度学习+强化学习,Pytorch学习)