【PyTorch官方教程中文版学习笔记02】PyTorch 神经网络


  学前准备:  1. python 中关于【类】的语法

         2. 学会查阅官方文档Linear — PyTorch 1.10 documentation

  基础知识: 1. nn.Module是PyTorch提供的神经网络类,并在类中实现了网络各层的定义及前向计算与反向传播机制。在实际使用时,如果想要实现某个神经网络,只需继承nn.Module,在初始化中定义模型结构与参数,在函数forward()中编写网络前向过程即可。更生动的比喻是,现有一个玩具车模型(nn.Module),我们自己改装了轮胎马达等(填装我们自己需要的函数),然后玩具车上跑道(forward函数)跑起来了。

        2. 常见函数

          a)卷积 convolution 

            torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0)

                                    

               有时,论文中给的神经网络框架图中可能没有给具体stride或padding的参数值,可以根据此公式推导。

          b)池化 Pooling 

            torch.nn.MaxPool2d(kernel_size, stride=None, padding=0)

            在池中过滤出最大值,参数解释参考卷积。

               作用:减少数据量,训练更快。可将图片马赛克化,或降低清晰度。

          c) Linear

            torch.nn.Linear(in_features, out_features)

             Applies a linear transformation to the incoming data: y = xA^T + b

            应用举例:

              

                  两个全连接层组成的感知机

               d)激活函数

            激活函数通常为非线性的平滑函数

            神经网络中经常使用的一个激活函数就是sigmoid函数 

            最近则主要使用ReLU(Rectified Linear Unit)函数

          

          e) 其他

            torch.randn(*size*out=Nonedtype=Nonelayout=torch.strideddevice=Nonerequires_grad=False)

             

            example: 

  实例1:

        

#下面具体以一个由两个全连接层组成的感知机为例,介绍如何使用nn.Module构造模块化的神经网络
import torch
from torch import nn

class Linear(nn.Module):
    def __init__(self, in_dim, out_dim):
        super(Linear, self).__init__() #super()帮助python将父类和子类联系起来,调用父类nn.Module的结构函数
        self.w = nn.Parameter(torch.randn(in_dim, out_dim))
        self.b = nn.Parameter(torch.randn(out_dim))
                 # torch.randn(*size, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) → Tensor
                #size(int…) --定义输出张量形状的整数序列;out(Tensor, optional) --输出张量
                #nn.Parameter函数:nn.Parameter()函数定义了全连接中的ω和b,
                # 这是一种特殊的Tensor的构造方法,默认需要求导,即requires_grad为True。
                #Parameter:参数
    def forward(self, x):
        x = x.matmul(self.w)#使用Tensor.matmul实现矩阵相乘,x*w
        y = x + self.b.expand_as(x)#将张量扩展为参数x的大小,保证矩阵形状一致。y=x*w+b
        return y

#建立感知机类,继承nn.Module,并调用了Linear的子module
class Perception(nn.Module):#perception 感知
    def __init__(self, in_dim, hid_dim, out_dim):
        super(Perception, self).__init__()#super()同上
        self.layer1 = Linear(in_dim, hid_dim)
        self.layer2 = Linear(hid_dim, out_dim)
                    #    Applies a linear transformation to the incoming data: y = xA^T + by=xA^T+b
    def forward(self, x):
        x = self.layer1(x)
        y = torch.sigmoid(x)#sigmoid作为激活函数
                            #sigmoid激活函数:h(x)=1/(1+e^(-x)),图像近似于阶跃函数,但是是连续的,平滑的非线性函数。
        y = self.layer2(y)
        y = torch.sigmoid(y)
        return y
#调用该神经网络
import torch
from perception import Perception
perception = Perception(2,3,2)
print(perception)


# named_parameters()可以返回学习参数的迭代器,分别为参数名与参数值
for name, parameter in perception.named_parameters():
    print(name, parameter)
# 随机生成数据,注意这里的4代表了样本数为4,每个样本有两维
data = torch.randn(4,2)
#输出的结果

Perception(

(layer1): Linear()
(layer2): Linear()
)

#layer1的w,b参数信息
layer1.w Parameter containing:
tensor([[ 0.3498, -0.2598, -1.0321],
[ 0.6166, -1.6089, -0.0318]], requires_grad=True)
layer1.b Parameter containing:
tensor([-1.1886, -0.2010, 0.2120], requires_grad=True)

#layer2的w,b参数信息
layer2.w Parameter containing:
tensor([[-0.3462, -1.3090],
[ 2.2993, 0.5015],
[-0.1526, -1.4099]], requires_grad=True)
layer2.b Parameter containing:
tensor([ 0.3471, -0.3661], requires_grad=True)

知识补充:

  实例2:

        

        这是一个简单的前馈神经网络,它接收输入,让输入一个接着一个的通过一些层,最后给出输出。

  

import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # 1 input image channel, 6 output channels, 5x5 square convolution
        # kernel
        self.conv1 = nn.Conv2d(1, 6, 5) #卷积1
        self.conv2 = nn.Conv2d(6, 16, 5)#卷积2
        # an affine operation: y = Wx + b
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
    def forward(self, x):
        # Max pooling over a (2, 2) window
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))#对x卷积1后,用relu激活,再进行最大池化,最大池化核为2*2
        # If the size is a square you can only specify a single number
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)#对上面的x继续卷积2后,用relu激活,再进行最大池化
        x = x.view(-1, self.num_flat_features(x))
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
    def num_flat_features(self, x):
        size = x.size()[1:] # all dimensions except the batch dimension
        num_features = 1
        for s in size:
            num_features *= s
        return num_features
net = Net()
print(net)
#输出框架参数
Net(
  (conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
  (conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear(in_features=400, out_features=120, bias=True)
  (fc2): Linear(in_features=120, out_features=84, bias=True)
  (fc3): Linear(in_features=84, out_features=10, bias=True)
)
#尝试输入一个32*32的“图片”
input = torch.randn(1, 1, 32, 32)
print(input)
out = net(input)
print(out)
#输出为一个1*10的tensor
tensor([[ 0.0537,  0.0238,  0.0759,  0.0187,  0.0491,  0.0826,  0.0281, -0.0361,
         -0.1232,  0.0870]], grad_fn=)

在此,我们完成了:
1.定义一个神经网络
2.处理输入以及调用反向传播

 参考文献:

《Pytorch官方教程中文版 》

《 深度学习之Pytorch物体检测实战》

《深度学习入门:基于python的理论与实现》