字符识别模型
对于字符识别任务,我们已经在前面提出了三种思路,这里我们主要基于思路一来讲解如何利用pytorch搭建深度学习模型。
思路回顾
我们的思路是将字符识别转换为定长字符识别模型,经过数据分析可以得到字符为6个的图片仅有一张,因此我们确定定长字符个数为5个,对于不到五个字符的我们将余下的字符填充为10,我们的模型要从数据集中学习到如何从一张图片中识别出5个字符,对于这类视觉问题,我们主要使用卷积神经网络模型。
预备知识
利用pytorch我们可以很快速地搭建CNN模型,主要利用pytorch实现这些结构:
卷积层
- 输入图片大小 n × n n\times n n×n
- 滤波器尺寸 f × f f\times f f×f
- padding p
- stride s
输出大小为
⌊ n + 2 p − f s + 1 ⌋ × ⌊ n + 2 p − f s + 1 ⌋ \lfloor \frac{n+2p-f}{s}+1 \rfloor \times \lfloor \frac{n+2p-f}{s}+1 \rfloor ⌊sn+2p−f+1⌋×⌊sn+2p−f+1⌋
卷积层pytorch实现
使用nn.conv2d实现:
nn.conv2d(in_channels,out_channels,kernel_size,padding)
这里需要注意padding的使用,若padding=p,则表示在输入的高和宽两个方向分别填充p行(相当于一共填充了2p行),padding=(h,w)表示在两个方向分别填充h、w行。上面式子中的p指的不是在某个方向上一共填充的行数而是一侧填充的数目。
池化层
池化层的提出是为了为了缓解卷积层对位置的过度敏感性,同时可以扩大深层网络的感受野,能够更好地学习全局特征。
nn.MaxPool2d(pooling_size,padding,stride)
pooling_size为池化窗口的尺寸,padding为填充的数目,stride为池化操作的步长。
(
n
−
f
)
/
s
+
1
(n-f)/s+1
(n−f)/s+1
上面给出的是最大池化,读者也可以查阅pytorch官方文档了解其他池化方式。
代码实现
接下来我们就可以进行模型的构建
class SVHN_Model1(nn.Module):
def __init__(self):
super(SVHN_Model1, self).__init__()
model_conv = models.resnet18(pretrained=True)
model_conv.avgpool = nn.AdaptiveAvgPool2d(1)
model_conv = nn.Sequential(*list(model_conv.children())[:-1])
self.cnn = model_conv
self.fc1 = nn.Linear(512, 11)
self.fc2 = nn.Linear(512, 11)
self.fc3 = nn.Linear(512, 11)
self.fc4 = nn.Linear(512, 11)
self.fc5 = nn.Linear(512, 11)
def forward(self, img):
feat = self.cnn(img)
# print(feat.shape)
feat = feat.view(feat.shape[0], -1)
c1 = self.fc1(feat)
c2 = self.fc2(feat)
c3 = self.fc3(feat)
c4 = self.fc4(feat)
c5 = self.fc5(feat)
return c1, c2, c3, c4, c5
这里我们使用了预训练模型,根据研究,采用预训练模型对网络参数初始化可以加快模型收敛的速度。