0.CNN网络可学习的参数
学习一个网络首先要了解该网络哪些参数是可学习的,这代表着这个网络的智力
在CNN中可学习的参数有以下
卷积层(Conv),卷积核的权重和偏置
批归一化层(BN),缩放和偏置
和全连接层(FC),权重和偏置
输出通道数代表了卷积核的个数
1.按照
- 卷积层
- 归一化层
- 池化层
- 激活函数层
的顺序处理数据
2.小卷积核1、3、5,大卷积核7、11,步长最好小于卷积核,使得卷积过程有覆盖,步长代表提取图像特征的精度。小卷积核更能捕获局部视野,计算量随之减小,大卷积核更注重全局,计算量增大
3.卷积核和图像尺寸不匹配,适当添加padding在图像外圈填充0,不影响结果
3.归一化可以大幅度提升模型训练稳定性,使loss稳定下降降低波动
4.池化层几乎不影响正确率,但降低了图像尺寸大大减少了运算量,使模型跑起来更快
5.激活函数选GELU(),激活函数很重要,多个激活函数组合可以扭曲各层数据的线性组合,将网络变得复杂,扭曲的空间曲面更容易拟合分类边界
6.如果全连接层后在网络内部定义了softmax()会将误差缩小,降低loss梯度的区分度,和梯度消失一样,模型训练不收敛。需要使用概率分布的话,在模型输出后在模型外单独使用softmax()达到想要的效果
7.以下是一个简单的CNN网络
import torch
import torch.nn as nn
class CNN(nn.Module):
def __init__(self, in_channels,out_channels,padding,linear_input_size,out_features):
super(CNN,self).__init__()
# 输入通道数
self.in_channels = in_channels
# 第一层卷积输出通道数
self.out_channels = out_channels
# 边缘填充0圈数
self.padding=padding
# 全连接层输入大小
self.linear_input_size = linear_input_size
# 全连接层输出类别数
self.out_features = out_features
# 卷积层1
self.conv1 = nn.Sequential(
# 卷积层,padding:前向计算时在输入特征图周围添加0的圈数
nn.Conv2d(in_channels=self.in_channels, out_channels=self.out_channels, kernel_size=5, stride=2, padding=self.padding),
# 归一化层
nn.BatchNorm2d(self.out_channels),
# 池化层
nn.MaxPool2d(kernel_size=5, stride=2),
# 激活层
nn.GELU()
)
# 卷积层2
self.conv2 = nn.Sequential(
# 卷积层
nn.Conv2d(in_channels=self.out_channels, out_channels=self.out_channels*2, kernel_size=4, stride=2, padding=self.padding),
# 归一化层
nn.BatchNorm2d(self.out_channels*2),
# 池化层
nn.MaxPool2d(kernel_size=4, stride=2),
# 激活层
nn.GELU()
)
# 卷积层3
self.conv3 = nn.Sequential(
# 卷积层
nn.Conv2d(in_channels=self.out_channels*2, out_channels=self.out_channels*4, kernel_size=3, stride=1, padding=self.padding),
# 归一化层
nn.BatchNorm2d(self.out_channels*4),
# 池化层
nn.MaxPool2d(kernel_size=3, stride=1),
# 激活层
nn.GELU()
)
# 展平层
self.flatten = torch.nn.Flatten()
# 激活层1
self.gelu = nn.GELU()
# 全连接层1
self.fc1 = nn.Linear(self.linear_input_size, self.out_features)
def forward(self,x