利用 torch 实现 ResNet34 网络
import torch as t
from torch import nn
from torch.nn import functional as F
class ResidualBlock(nn.Module):
“”"
实现子 module:Residual Block
“”"
def __init__(self, inchannel, outchannel, stride=1, shortcut=None):
super(ResidualBlock, self).__init__()
# 由于 Residual Block 分为左右两部分,因此定义左右两边的 layer
# 定义左边
self.left = nn.Sequential(
# Conv2d 参数:in_channel,out_channel,kernel_size,stride,padding
nn.Conv2d(inchannel, outchannel, 3, stride, 1, bias=False),
nn.BatchNorm2d(outchannel),
nn.ReLU(inplace=True),
nn.Conv2d(outchannel, outchannel, 3, 1, 1, bias=False),
nn.BatchNorm2d(outchannel))
# 定义右边
self.right = shortcut
def forward(self, x):
out = self.left(x)
residual = x if self.right is None else self.right(x) # 检测右边直连的情况
out += residual
return F.relu(out)
class ResNet(nn.Module):
“”"
实现主 module:ResNet34
ResNet34 包含多个 layer,每个 layer 又包含多个 residual block
用子 module 实现 residual block,用 _make_layer 函数实现 layer
“”"
def __init__(self, num_classes=1000):
super(ResNet, self).__init__()
# 前几层图像转换
self.pre = nn.Sequential(
nn.Conv2d(3, 64, 7, 2, 3, bias=False),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.MaxPool2d(3, 2, 1),
)
# 重复的 layer 分别有 3,4,6,3 个 residual block
self.layer1 = self._make_layer(64, 128, 3)
self.layer2 = self._make_layer(128, 256, 4, stride=2)
self.layer3 = self._make_layer(256, 512, 6, stride=2)
self.layer4 = self._make_layer(512, 512, 3, stride=2)
# 分类用的全连接
self.fc = nn.Linear(512, num_classes)
def _make_layer(self, inchannel, outchannel, block_num, stride=1):
"""
构建 layer,包含多个 residual block
"""
shortcut = nn.Sequential(
nn.Conv2d(inchannel, outchannel, 1, stride, bias=False),
nn.BatchNorm2d(outchannel))
layers = []
layers.append(ResidualBlock(inchannel, outchannel, stride, shortcut))
for i in range(1, block_num):
layers.append(ResidualBlock(outchannel, outchannel))
return nn.Sequential(*layers)
def forward(self, x):
x = self.pre(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = F.avg_pool2d(x, 7)
x = x.view(x.size(0), -1)
return self.fc(x)
res_net = ResNet()
inp = t.autograd.Variable(t.randn(1, 3, 224, 224))
output = res_net(inp)
output.size()
torch.Size([1, 1000])
不到 50 行代码便实现了这样一个网络,看起来是那么不可思议,如果对此感兴趣的同学还可以取消尝试实现 Google 的 Inception 网络。
三、torchvision 中的 resnet34网络调用
前面我们讲过一个 hub 模块,里面存储了很多网络结构。不仅如此,和 torch 配套的图像工具包 torchvision 也实现了深度学习中的大多数经典的模型,其中就包括了 ResNet34,非常简单,可以通过以下两行代码调用这个网络:
from torchvision import models
res_net = models.resnet34()
inp = t.autograd.Variable(t.randn(1, 3, 224, 224))
output = res_net(inp)
output.size()
torch.Size([1, 1000])
本例中的 ResNet34 的实现参考了 torchvision 中的实现并做了一定的调整,有兴趣的同学可以去阅读相对应的源码。
USB Microphone https://www.soft-voice.com/
Wooden Speakers https://www.zeshuiplatform.com/
亚马逊测评 www.yisuping.cn
深圳网站建设www.sz886.com