用卷积优化模型

对于我们的全新网络

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 16, kernel_size=(3, 3), padding=(1, 1))
        self.act1 = nn.ReLU()
        self.pool1 = nn.MaxPool2d(kernel_size=(2, 2))
        self.conv2 = nn.Conv2d(16, 8, kernel_size=(3, 3), padding=(1, 1))
        self.act2 = nn.ReLU()
        self.pool2 = nn.MaxPool2d(kernel_size=(2, 2))
        self.fc1 = nn.Linear(8 * 8 * 8, 32)
        self.act3 = nn.ReLU()
        self.fc2 = nn.Linear(32, 2)

    def forward(self, x):
        out = self.pool1(self.act1(self.conv1(x)))
        out = self.pool2(self.act2(self.conv2(out)))
        out = out.view(-1, 8 * 8 * 8)
        out = self.act3(self.fc1(out))
        out = self.fc2(out)
        return out

我们用

numel_model = [p.numel() for p in model.parameters()]
print(sum(numel_model), numel_model)

来查看这个模型的参数:

output
18090 [432, 16, 1152, 8, 16384, 32, 64, 2]

那么,我们上一篇文章中的模型参数是多少呢?我们用同样的方法查看:

output
1574402 [1572864, 512, 1024, 2]

可以看到之前的全连接模型有150多万个参数…

从卷积公式来看,

    \[\int_{-\infty}^{\infty} f(\tau) g(x - \tau) \, d\tau\]

用卷积核对我们的输入进行变换:

    \[\sum_{i=-m}^{m} \, \sum_{j=-n}^{n} \, \text{I}(x+i,y+j) \, \cdot \, \text{K}(i,j)\]

当我们有k\,\times\,k卷积核,卷积层参数则为

    \[(k\,\times\,k\,\times\,Channel_{in}\,+\,bias)\,\times\,Channel_{out}\]

相比全连接的

    \[dimension_{in}\,\times\,dimension_{out}\,+\,bias\]

减少了极大量的参数。

加之最大池化用以降低特征图尺寸减少计算,以及卷积可以去除冗余信息,增强泛化能力,自然要优于简单的全连接网络。