目录
一、网络中的网络(NiN)
1、LeNet、AlexNet和VGG都有一个共同的设计模式:通过一系列的卷积层与汇聚层来提取空间结构特征;然后通过全连接层对特征的表征进行处理。然而,如果使用了全连接层,可能会完全放弃表征的空间结构。
全连接层参数多占用空间,带来过拟合 ;参数实际上就是来算梯度的变量,卷积层的变量就是卷积,也就是那个矩阵(还有个偏差这里没算),所以需要cico个k*k的卷积;
为了解决上面的问题,NiN就说完全不要全连接层;
2、第二遍看明白了,其实就是共享参数的全连接层,但是参数少了很多;即将空间维度中的每个像素视为单个样本,将通道维度视为不同特征(feature)。
我的理解,每个像素是三个通道(R,G,B),然后(W1,W2,W3),分别作用到三个通道
3、NiN的架构,无全连接层;
NiN和AlexNet之间的一个显著区别是NiN完全取消了全连接层。 相反,NiN使用一个NiN块,其输出通道数等于标签类别的数量。最后放一个全局平均汇聚层(global average pooling layer),生成一个对数几率 (logits)。
NiN设计的一个优点是,它显著减少了模型所需参数的数量。然而,在实践中,这种设计有时会增加训练模型的时间。
4、总结
二、代码实现
import torch
from torch import nn
from d2l import torch as d2l
# 定义NiN块
def nin_block(in_channels, out_channels, kernel_size, strides, padding):
return nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size, strides, padding),
nn.ReLU(),
#1*1的卷积层,不改变输入和输出通道
nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU(),
nn.Conv2d(out_channels, out_channels, kernel_size=1), nn.ReLU())
net = nn.Sequential(
nin_block(1, 96, kernel_size=11, strides=4, padding=0),
nn.MaxPool2d(3, stride=2), # 输入输出高宽减半
nin_block(96, 256, kernel_size=5, strides=1, padding=2),
nn.MaxPool2d(3, stride=2),
nin_block(256, 384, kernel_size=3, strides=1, padding=1),
nn.MaxPool2d(3, stride=2),
nn.Dropout(0.5),
# 标签类别数是10
nin_block(384, 10, kernel_size=3, strides=1, padding=1),
#全局的平均池化层,这个函数是自适应池化,这俩参数是指定输出的维度
nn.AdaptiveAvgPool2d((1, 1)),
# 将四维的输出转成二维的输出,其形状为(批量大小,10)
nn.Flatten())
X = torch.rand(size=(1, 1, 224, 224))
for layer in net:
X = layer(X)
print(layer.__class__.__name__,'output shape:\t', X.shape)
#训练模型
lr, num_epochs, batch_size = 0.1, 10, 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=224)
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())
三、问答总结
- NiN,降低模型复杂度,提高了泛化性,但是收敛变慢