1.3 nn.Module 神经网络(一)

torch.nn是专门为神经网络设计的模块化接口。nn构建于Autograd之上,用来定义和运行神经网络nn.Module是nn中最重要的,可以把它看作一个网络的封装,包含网络各层定义以及forward方法、调用forward(input)方法,可返回前向传播结果。下面以LeNet网络为例:

 

1.3 nn.Module 神经网络(一)_第1张图片

                                                                                                LeNet网络结构

1.定义网络

1.1 定义网络时候,需要继承nn.Module,并实现它的forward方法,把网络中具有可学参数的层放在构造函数__init__中。其他的建议放外面,在forward中使用nn.functional代替。

eg:

import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        #nn.Module子类的函数必须在构造函数中执行父类的构造函数
        #下式等价于nn.Module.__init__(self)
        super(Net,self).__init__()
        #卷积层‘1’表示输入图片为单通道,‘6’表示输出通道数,‘5’表示卷积核为5*5
        self.conv1=nn.Conv2d(1,6,5)
        #卷积层
        self.conv2 = nn.Conv2d (6, 16, 5)
        #仿射层、全连接层,y=wx+b
        #一般定义一个linear层的时候,写法为nn.Linear(in_features,out_features)
        self.fc1=nn.Linear(16*5*5,120)
        self.fc2 = nn.Linear (120, 84)
        self.fc3 = nn.Linear (84, 10)
    def forward(self,x):
        #卷积-->激活-->池化
        x=F.max_pool2d(F.relu(self.conv1(x)),(2,2))
        x = F.max_pool2d (F.relu (self.conv2 (x)), 2)
        #reshape,‘-1’表示自适应
        #这句话一般出现在model类的forward函数中,具体位置一般都是在调用分类器之前。分类器是一个简单的nn.Linear()结构,
        # 输入输出都是维度为一的值,x = x.view(x.size(0), -1)  这句话的出现就是为了将前面多维度的tensor展平成一维
        #view()函数的功能根reshape类似,用来转换size大小。x = x.view(batchsize, -1)中batchsize指转换后有几行,
        # 而-1指在不告诉函数有多少列的情况下,根据原tensor数据和batchsize自动分配列数。
        x=x.view(x.size()[0],-1)
        x=F.relu(self.fc1(x))
        x=F.relu(self.fc2(x))
        x=self.fc3(x)
        return x
net=Net()
print(net)

out:
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)
)

1.2 网络的可学习参数通过net.parameters()返回,net.named_parameters可同时返回可学习的参数及名称。

params=list(net.parameters())
#print(params)
print(len(params))
for name,parameters in net.named_parameters():
    print(name,':',parameters.size())

out:10
conv1.weight : torch.Size([6, 1, 5, 5])
conv1.bias : torch.Size([6])
conv2.weight : torch.Size([16, 6, 5, 5])
conv2.bias : torch.Size([16])
fc1.weight : torch.Size([120, 400])
fc1.bias : torch.Size([120])
fc2.weight : torch.Size([84, 120])
fc2.bias : torch.Size([84])
fc3.weight : torch.Size([10, 84])
fc3.bias : torch.Size([10])

1.3 forward函数的输入输出都是Variable,只有Variable,才有自动求导功能,Tensor是没有的,所以输入时,需要把Tensor封装成Variable。

from torch.autograd import Variable
import torch as t
input=Variable(t.randn(1,1,32,32))
out=net(input)
print(out.size())

out:
torch.Size([1, 10])
net.zero_grad()#所有参数的梯度清零
out.backward(Variable(t.ones(1,10)))#反向传播

注意:torch.nn支持mini-batches,不支持一次只输一个样本,即一次必须是一个batch。如果只想输入一个样本,则用input.squeeze(0),将batch_size设为1。例如,nn.Conv2d输入必须是4维的,(nSamples,nChannels,Height,Width)

你可能感兴趣的:(Pytorch入门)