人工智能编程:神经网络的快速搭建模块,以及网络模型参数的获取

人工智能专栏限时打折中

以下几个专栏限时打折中,欢迎订阅


正文


为方便用户使用,PyTorch实现了神经网络中绝大多数的layer,这些layer都继承于nn.Module,封装了可学习参数parameter,并实现了forward函数,且很多都专门针对GPU运算进行了CuDNN优化,其速度和性能都十分优异。

如nn.Linear(in_features, out_features, bias),需关注这三个参数的作用。

如nn.Linear中有weight和bias两个可学习参数输入输出的形状,如nn.linear的输入形状是(N, input_features),输出为(N,output_features),N是batch_size。

在PyTorch里面编写神经网络,所有的层结构和损失函数都来自于torch.nn,所有的模型构建都是从这个基类 nn.Module 继承的,于是有了下面这个模板。

class net_name(nn.Moudle) :

def __init__ (self,other_ments) :

super(net_name,self). __init__()

self.conv1=nn.Conv2d(in_channels, out_channels, kernel_size)

# other network l ayer 其它网络层

def forward(self, x):

x=self.conv1(x)

return x

这样就建立了一个计算图 ,并且这个结构可以复用多次,每次调用就相当于用该计算图定义的相同参数做一次前向传播,这得益于 PyTorch 的自动求导功能,所以我们不需要自己编写反向传播,而所有的网络层都是由 nn 这个包得到的,比如线性层nn.Linear,等之后使用的时候我们可以详细地介绍每一种网络对应的结构,以及如何调用。

定义完模型之后 ,我们需要通过nn这个包来定义损失函数。 常见的损失函数都已经定义在了nn巾,比如均方误差 、多分类的交叉熵,以及二分类的交叉熵,等等,调用这些已经定义好的损失函数也很简单:

criterion = nn.CrossEntropyLoss( )

loss = criterion(output, target)

这样就能求得我们的输出和真实目标之间的损失函数了

常见的神经网络层:

卷积层conv = nn.Conv2d(1, 1, (3, 3), 1, bias=False)

池化层pool = nn.AvgPool2d(2,2)

Linear:全连接层linear = nn.Linear(3, 4)

BatchNorm:批规范化层bn = nn.BatchNorm1d(4)

Dropout:dropout层dropout = nn.Dropout(0.5)#0.5的概率舍弃

激活函数relu = nn.ReLU(True)

# Embedding层,有4个词,每个词用5维的向量表示

embedding = nn.Embedding(4, 5)

搭建网络的两种方式

我们在搭建神经网络的时候,可以将多个神经网络层组合在一起,我们可以使用Sequential和ModuleList这两种方式。

我们先来看一下Sequential,它我们可以看作是一个module

# Sequential的三种写法

写法一:为每一个神经网络层添加一个名字

net1 = nn.Sequential()

net1.add_module('conv', nn.Conv2d(3, 3, 3))

net1.add_module('batchnorm', nn.BatchNorm2d(3))

net1.add_module('activation_layer', nn.ReLU())

人工智能编程:神经网络的快速搭建模块,以及网络模型参数的获取

因为有名字,所以我们可以根据名字来取出神经网络的每一层

net1.conv

net1.batchnorm

前向传播out=net1(input)

写法二:

net2 = nn.Sequential(

nn.Conv2d(3, 3, 3),

nn.BatchNorm2d(3),

nn.ReLU()

)

人工智能编程:神经网络的快速搭建模块,以及网络模型参数的获取

这个没有名字,我们可以通过索引取出Sequential中神经网路的每一层

net2[0]

前向传播out=net2(input)

写法三:使用OrderedDict将神经网络层封装为一个字典,然后传递到Sequential中

from collections import OrderedDict

net3= nn.Sequential(OrderedDict([

('conv1', nn.Conv2d(3, 3, 3)),

('bn1', nn.BatchNorm2d(3)),

('relu1', nn.ReLU())

]))


人工智能编程:神经网络的快速搭建模块,以及网络模型参数的获取

可以根据名字取出神经网络的每一层

net3.conv1

前向传播

方式一:output = net3(input)

方式二:output = net3.relu1(net1.batchnorm(net1.conv(input)))

ModuleList的使用方式,注意ModuleList在Module中使用它的时候(在实现nn.Module的__init__()方法中使用的时候),才能自动识别为子module。

class Net4(nn.Module):

def __init__(self):

super(Net4, self).__init__()

self.module_list = nn.ModuleList([nn.Conv2d(3, 3, 3), nn.ReLU()])

def forward(self):

model = MyModule()

ModuleList其实就是一个List,只不过在Module中它会自动识别为module,识别为module的好处就是它会作为整个module的一个整体,在反向传播中跟新其参数。


除ModuleList之外还有ParameterList,其是一个可以包含多个parameter的类list对象。我们如果要是在init中用到list,我们应该用ModuleList或ParameterList,而不是使用list。

class MyLinear(nn.Module):

def __init__(self, inp, outp):

super(MyLinear, self).__init__()

# requires_grad = True

self.w = nn.Parameter(torch.randn(outp, inp))

self.b = nn.Parameter(torch.randn(outp))

def forward(self, x):

x = x @ self.w.t() + self.b

return x

人工智能编程:神经网络的快速搭建模块,以及网络模型参数的获取

这个表示建立一个全连接层,w和b就是全连接层的权重参数,其中w的维度是(输出,输入)

nn.Parameter中会自带梯度求梯度功能

人工智能编程:神经网络的快速搭建模块,以及网络模型参数的获取

获取参数

Net.parameters()表示获取net的所有参数

List表示转换为列表形式,此时这个列表应该是[w0,b0,w1,b1]

人工智能编程:神经网络的快速搭建模块,以及网络模型参数的获取

遍历所有的模型的参数,其中name表示模型的参数,注意这个名字中没有net.1,这是因为nn.ReLU是模型的第二层,但是这里并没有参数,所以net.0之后没有net.1,而直接是net.2

人工智能编程:神经网络的快速搭建模块,以及网络模型参数的获取

Named——children表示获取net的网络的孩子结点

人工智能编程:神经网络的快速搭建模块,以及网络模型参数的获取

获取所有结点,从子结点开始逐渐到孙子结点

自定义展开层

人工智能编程:神经网络的快速搭建模块,以及网络模型参数的获取

class Flatten(nn.Module):

def __init__(self):

super(Flatten, self).__init__()

def forward(self, input):

return input.view(input.size(0), -1)

class TestNet(nn.Module):

def __init__(self):

super(TestNet, self).__init__()

self.net = nn.Sequential(nn.Conv2d(1, 16, stride=1, padding=1),

nn.MaxPool2d(2, 2),

Flatten(),

nn.Linear(1*14*14, 10))

def forward(self, x):

return self.net(x)


分享到:


相關文章: