https://zh-v2.d2l.ai/index.html
性质
空间不变性
平移不变性:不管目标出现在图像汇总的哪个位置,神经网络的前几层应该对相同的图像区域具有相似的响应,即平移不变性
局部性:神经网络的前面几层应该只探索输入图像中的局部区域,而不过度关注图像中相隔较远区域的关系,即局部性。最终聚合这些局部特征,以在整个图像级别进行预测
互相关
约定俗成为卷积运算
感受野
之前所有层中,影响当前层中该元素计算的,所有元素
特征图计算公式
h + 2 p a d d i n g − k s i z e s t r i d e + 1 \frac{h+2padding-k_{size}}{stride}+1 strideh+2padding−ksize+1
w + 2 p a d d i n g − k s i z e s t r i d e + 1 \frac{w+2padding-k_{size}}{stride}+1 stridew+2padding−ksize+1
卷积核
多个卷积核的旨在实现对不同特征的响应,并实现特征之间的相关性分析
池化层
降低卷积层对位置的敏感性
降低对空间降采样表示的敏感性
https://blog.csdn.net/L_fengzifei/article/details/124949093
block概念的提出,简化模型够早
小卷积核更有效
聚合不同的卷积层,提取不同的特征
resnet – 还要再看
关于残差块的解释
从复杂度的角度分析:https://zh-v2.d2l.ai/chapter_convolutional-modern/resnet.html
从恒等映射的角度分析:https://zh-v2.d2l.ai/chapter_convolutional-modern/resnet.html
残差块的简洁实现
class ResidualBlock(nn.Module):
def __init__(self,input_channels,num_channels,use_1x1conv=False,strides=1)
super(ResidualBlock,self).__init__():
self.conv1=nn.Conv2d(input_channels,num_channels,kernel_size=3,padding=1,stride=strides)
self.conv2=nn.Conv2d(input_channels,num_channels,kernel_size=3,padding=1)
if use_1x1conv:
self.conv3=nn.Conv2d(input_channels,num_channels,kernel_size=1,stride=strides)
else:
self.conv3=None
self.bn1=nn.BatchNorm2d(num_channels)
self.bn2=nn.BatchNorm2d(num_channels)
def forward(self,x):
Y=F.relu(self.bn1(self.conv1(x)))
Y=self.bn2(self.conv2(Y))
if self.conv3:
x=self.conv3(x)
Y+=x
return F.relu(Y)
def resnet_block(input_channels,num_channels,num_residuals,first_block=False):
blk=[]
for i in range(num_residuals):
if i==0 and not first_block:
blk.append(Residual(input_channels,num_channels,use_1x1conv=True,strides=2))
else:
blk.append(Residual(num_channels,num_channels))
return blk
b1=nn.Sequential(nn.Conv2d(1,64,kernel_size=7,stride=2,padding=3),
nn.BatchNorm2d(64),nn.Relu(),
nn.MaxPool2d(kernel_size=3,stride=2,padding=1))
b2=nn.Sequential(*residual_block(64,64,2,first_block=True))
b3=nn.Sequential(*residual_block(64,128,2))
b4=nn.Sequential(*residual_block(128,256,2))
b5=nn.Sequential(*residual_block(256,512,2))
net=nn.Sequential(b1,b2,b3,b4,b5,
nn.AdaptiveAvgPool2d(1,1),
nn.Flatten(),nn.Linear(512,10))
def conv_block(input_channels,num_channels):
return nn.Sequential(nn.BatchNorm2d(input_channels),nn.Relu(),
nn.Conv2d(input_channels,num_channels,kernel_size=3,padding=1))
# 当个dense块
class DenseBlock(nn.Module):
def __init__(slef,num_convs,input_channels,num_channels):
super(DenseBlock,self).__init__()
layer=[]
for i in range(num_convs):
layer.append(conv_block(num_channels*i+input_channels,num_channels))
self.net=nn.Sequential(*layer)
def forward(self,x):
for blk in self.net:
Y=blk(x)
x=torch.cat((x,Y),dim=1)
return x
def transition_block(input_channels,num_channels):
return nn.Sequential(nn.BatchNorm2d(input_channels),nn.Relu(),
nn.Conv2d(input_channels,num_channels,kernel_size=1),
nn.Avgpool2d(kernel_size=2,stride=2))
其他参考
https://www.kaggle.com/code/aleksandradeis/data-augmentation-packages-overview/notebook
https://github.com/aleju/imgaug/issues/406
https://mp.weixin.qq.com/s/tdNlCxmz_s1Wwls2qoQXDQ
https://www.kaggle.com/code/jmcslk/pytorch-classification-model-based-on-imgaug/notebook