作者:耶丝儿小丶姐 | 来源:互联网 | 2023-08-20 18:40
想用PyTorch来训练模型,我们首先需要把你想要用的网络结构,在PyTorch上实现出来。还是先学习60MinuteBlitz的例子。题外话:可以import的单位是packag
想用PyTorch来训练模型,我们首先需要把你想要用的网络结构,在PyTorch上实现出来。还是先学习60 Minute Blitz的例子。
题外话:可以import的单位是package
和module
;可以from...import...
的单位是package
,module
和class
/function
。而.py文件就是一个module.
首先是定义class,然后继承nn.Module,super().init_()是调用father class的初始化函数。定义了conv1的变量,属性是nn.Conv2d()的对象。调用这个函数需要参数列表。
可以看到nn.Conv2d, nn.Linear的参数是怎样的格式。Conv2d:第一个参数是 input’s channel, 第二个参数是output’s channel, 第三个参数是size of convolutional kernel ; Linear:
这个类里面还要定义forward()方法。感谢Ref[1][2]的解释,对数据操作需要函数,第一行x = self.conv(x)
实际上为x = self.conv.forward(x)
,调用了nn.Conv2d()
的forward()
函数,由于大家都继承了nn.Module
父类,根据nn.Module
的使用方法,.forward()
不写,直接写object(input)
。然后调用Function的relu, max_pool2d(input,(size of pooling)).x.view函数将Tensor x变形成一维的向量形式,总特征数与x 相同,后面就是全连接层了。
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)
self.conv2 = nn.Conv2d(6, 16, 5)
# 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))
# If the size is a square you can only specify a single number
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
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)
上面是Lenet的网络,比较简单,我们再来看看更加复杂的网络结构FCN的网络模型。这个网络定义了自己的_init()函数,参数列表中使用了预训练模型pretrained_net,和分类的数量。首先是ReLu的inplace操作。(inplace operation在pytorch中是指改变一个tensor的值的时候,不经过复制操作,而是直接在原来的内存上改变它的值。可以把它成为原地操作符。-ref[3])。反卷积层:nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True, dilation=1)。
![《PyTorch搭建网络》](https://img.php1.cn/3cd4a/1eebe/cd5/3e641eb5f5c8cd90.webp)
![《PyTorch搭建网络》](https://img.php1.cn/3cd4a/1eebe/cd5/3e641eb5f5c8cd90.webp)
在forward函数中,self.pretrained_net(x)有5个pooling层的输出,并用x1到x5提取出来。第一次score是x5反卷积之后,经过relu和bn1得到。这个score和x4具有相同的size.一次类推,就实现了论文中多个Pooling层,反卷积后叠加,得到和input大小相同的output
class FCNs(nn.Module):
def __init__(self, pretrained_net, n_class):
super().__init__()
self.n_class = n_class
self.pretrained_net = pretrained_net
self.relu = nn.ReLU(inplace=True)
self.deconv1 = nn.ConvTranspose2d(512, 512, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1)
self.bn1 = nn.BatchNorm2d(512)
self.deconv2 = nn.ConvTranspose2d(512, 256, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1)
self.bn2 = nn.BatchNorm2d(256)
self.deconv3 = nn.ConvTranspose2d(256, 128, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1)
self.bn3 = nn.BatchNorm2d(128)
self.deconv4 = nn.ConvTranspose2d(128, 64, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1)
self.bn4 = nn.BatchNorm2d(64)
self.deconv5 = nn.ConvTranspose2d(64, 32, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1)
self.bn5 = nn.BatchNorm2d(32)
self.classifier = nn.Conv2d(32, n_class, kernel_size=1)
# classifier is 1x1 conv, to reduce channels from 32 to n_class
def forward(self, x):
output = self.pretrained_net(x)
x5 = output['x5']
x4 = output['x4']
x3 = output['x3']
x2 = output['x2']
x1 = output['x1']
score = self.bn1(self.relu(self.deconv1(x5)))
score = score + x4
score = self.bn2(self.relu(self.deconv2(score)))
score = score + x3
score = self.bn3(self.relu(self.deconv3(score)))
score = score + x2
score = self.bn4(self.relu(self.deconv4(score)))
score = score + x1
score = self.bn5(self.relu(self.deconv5(score)))
score = self.classifier(score)
return score
Ref
[1].Pytorch搭建网络
[2].超简单!pytorch入门教程(三):构造一个小型CNN – cathy_mu – 博客园
[3].在PyTorch中in-place operation的含义
[4].[论文快读] FCN (2014)