模型构建
自定义模型子模块
扩展 Module 类,需要定义两个方法:
- init:定义模块属性
- forward :设置如何处理来自前一层的任何输入数据
class MyConvBlock(nn.Module):
def __init__(self, in_ch, out_ch, dropout_p):
kernel_size = 3
super().__init__()
self.model = nn.Sequential(
nn.Conv2d(in_ch, out_ch, kernel_size, stride=1, padding=1),
nn.BatchNorm2d(out_ch),
nn.ReLU(),
nn.Dropout(dropout_p),
nn.MaxPool2d(2, stride=2)
)
def forward(self, x):
return self.model(x)
flattened_img_size = 75 * 3 * 3
# Input 1 x 28 x 28
base_model = nn.Sequential(
MyConvBlock(IMG_CHS, 25, 0), # 25 x 14 x 14
MyConvBlock(25, 50, 0.2), # 50 x 7 x 7
MyConvBlock(50, 75, 0), # 75 x 3 x 3
# Flatten to Dense Layers
nn.Flatten(),
nn.Linear(flattened_img_size, 512),
nn.Dropout(.3),
nn.ReLU(),
nn.Linear(512, N_CLASSES)
)
展平图片 nn.Flatten()
把多维数据“压扁”成一维或二维,让数据能塞进某些只能处理简单结构的模型里(比如全连接神经网络)。
nn.Flatten默认的start_dim是1,即从第2维[1]及向后开始展平(相乘)
layers = [
nn.Flatten()
]
layers
>>> [Flatten(start_dim=1, end_dim=-1)]
除非设置从第1维[0]开始,如下
nn.Flatten(start_dim=0)(test_matrix)
构建模型 nn.Sequential()
把多个神经网络层按顺序组装成一个模型
# 构建层
n_classes = 10
layers = [
nn.Flatten(),
nn.Linear(input_size, 512), # Input
nn.ReLU(), # Activation for input
nn.Linear(512, 512), # Hidden
nn.ReLU(), # Activation for hidden
nn.Linear(512, n_classes) # Output
]
layers
>>> [Flatten(start_dim=1, end_dim=-1),
>>> Linear(in_features=784, out_features=512, bias=True),
>>> ReLU(),
>>> Linear(in_features=512, out_features=512, bias=True),
>>> ReLU(),
>>> Linear(in_features=512, out_features=10, bias=True)]
# 将所有层按顺序组合成一个神经网络模型
```python
model = nn.Sequential(*layers)
model
>>>Sequential(
>>> (0): Flatten(start_dim=1, end_dim=-1)
>>> (1): Linear(in_features=784, out_features=512, bias=True)
>>> (2): ReLU()
>>> (3): Linear(in_features=512, out_features=512, bias=True)
>>> (4): ReLU()
>>> (5): Linear(in_features=512, out_features=10, bias=True)
>>>)
卷积神经网络组合
nn.Sequential构建的,可能包含多个卷积块和一个全连接部分。每个卷积块里有卷积层、批归一化、激活函数、池化,可能还有Dropout。然后展平,接全连接层。
卷积块举例如下:
Conv → Norm → ReLU → Pooling 模式
nn.Conv2d(25, 50, kernel_size=3, stride=1, padding=1), # 输入25,输出50通道
nn.BatchNorm2d(50), # 稳定梯度,加速收敛
nn.ReLU(), # 激活函数
nn.Dropout(0.2), # 随机丢弃20%神经元,防过拟合,增强泛化能力
nn.MaxPool2d(2, 2) # 池化窗口2x2,步长2
卷积后尺寸:(W - K + 2P)/S + 1
通道数逐层增加,逐步提取从简单到复杂的特征。
空间尺寸逐层减小,保留关键信息,降低计算量。
例如:手指边缘 → 手指形态 → 整个手部姿态
全连接分类层
nn.Flatten(), # 将一个多维的层输出展平成一维数组(特征向量),将连接到最终的分类层。
nn.Linear(flattened_img_size, 512), # 以特征向量为输入,学习哪些特征将对特定分类有贡献
nn.Dropout(.3),
nn.ReLU(),
nn.Linear(512, n_classes) # 最终的分类层,输出我们的预测结果