深度学习个人知识点总结
目录
23.1: 修改pytorch提供的现有的模型,并对这些模型进行修改
1.卷积(nn.Conv2d)
1.1卷积的定义与功能
nn.Conv2d 功能:对多个二维信号进行二维卷积
定义:
卷积运算:卷积核在输入信号(图像)上滑动,相应位置上进行乘加;
卷积核:又称为滤波器,过滤器,可认为是某种模式,某种特征;
卷积维度:一般情况下,卷积核在几个维度上滑动,就是几维卷积
功能:
卷积过程类似于用一个模板去图像上寻找与他相似的区域,与卷积核模式越相似,激活值越高,从而实现特征提取;
过程:卷积核(类似于一个模板)在图像上划动相应位置上乘加,从而实现特征提取
主要参数(包含默认值):
in_channels:输入通道数
out_channels:输出通道数,等价于卷积核个数
kernel_size:卷积核尺寸
stride=1:步长
padding=0:填充个数
dilation=1:空调卷积大小
groups=1:分组卷积设置
bias=True:偏置
padding_mode='zeros': 填充模式
1.2 Padding、Stride
Out_channels计算:
Eg:input: 5x5 kernel:3x3 stride:3 padding:2
Output : (input+padding*2-stride)/stride + 1
1x1的卷积设置步长也能实现高宽减半
2. 池化层 Pooling Layer
2.1 最大池化 nn.MaxPool2d(不改变通道数)
2.2 平均值池化 nn.AvgPool2d
2.3 最大池化上采样 nn.MaxUnpool2d
池化层:通过池化操作可以保留图像中重要特征的同时减少噪声和不重要的细节。如最大池化操作会选择每个池化窗口中的最大值作为输出,从而保留突出的特征。
3. 线性层 (全连接层)
线性层又称全连接层,其每个神经元与上一层所有神经元相连实现对前一层的线性组合,线性变换.
In_features(输入结点数):比如说形状为[N, M]的张量,其中N表示样本数量,M表示每个样本的特征维度,则输入结点数为M,线性层的输入结点数决定了权重矩阵的列数,即每个输入特征与权重之间的连接数量。这些连接用于将输入特征与线性层的权重进行相乘,生成线性变换后的输出特征。输入结点数也决定了线性层的输入维度,进而影响了输出维度和模型的表达能力
线性层(Linear Layer)通常位于卷积层之后,也称为全连接层(Fully Connected Layer)。线性层负责将卷积层或者池化层提取到的特征进行展平,并通过矩阵乘法和偏置项的加法进行线性变换,最终输出网络的预测结果
Out_features: y=x*WT+bias
一般分类模型最后一步就是线性层,用来输出类别:
(head): Linear(in_features=448, out_features=6, bias=True)
4. 归一化
4.1 归一化作用:
- 加速收敛速度: 归一化可以将输入特征缩放到相对较小的范围内,使得优化算法(如梯度下降)更容易找到全局最优解或局部最优解,从而加速模型的收敛速度。
- 减少梯度消失/爆炸问题: 在深度神经网络中,反向传播过程中可能出现梯度消失或梯度爆炸的情况,导致训练困难。归一化可以使得网络层之间的梯度更加稳定,减少梯度消失或梯度爆炸的发生。
- 提高模型泛化能力: 归一化可以减少特征之间的相关性,降低模型对特定特征的依赖程度,从而提高模型的泛化能力,使得模型在未见过的数据上表现更好。
- 抑制过拟合: 归一化可以起到一定的正则化作用,有助于抑制模型的过拟合,提高模型的泛化能力。
- 处理梯度消失/爆炸问题: 在 RNNs 或深度 CNNs 等网络中,由于层次较多,容易出现梯度消失或梯度爆炸的情况。归一化能够在一定程度上缓解这些问题,使得网络更容易训练。
- 批量归一化和层归一化
4.2 对全连接层进行批量归一化
4.3 对卷积网络进行批量归一化
4.4 对序列性网络进行批量归一化
5. 激活函数层 Activation Layer
(常用的激活函数包括 Sigmoid、Tanh、ReLU(Rectified Linear Unit)、Leaky ReLU、ELU(Exponential Linear Unit)等。每种激活函数都有其独特的特性和适用场景,具体选择取决于问题的性质和实验的结果)
5.1 nn.Sigmoid
变换效果如图:
5.2 nn.tanh
5.3 nn.ReLu
5.4 其他激活函数
5.5激活函数的作用
- 引入非线性特性:线性变换(如全连接层或卷积层)只能表示线性关系,而激活函数能够引入非线性特性,从而使神经网络能够表示更复杂的函数。
- 解决非线性可分问题:许多实际问题都是非线性可分的,即用线性模型无法很好地拟合的问题。激活函数的非线性变换可以帮助神经网络学习并拟合这些非线性关系。
- 增强模型的表达能力:通过引入非线性变换,激活函数可以增强神经网络的表达能力,使其能够学习到更复杂的特征和模式。
- 一些激活函数具有抑制过拟合的作用抑制过拟合:一些激活函数具有抑制过拟合的作用,例如 Dropout 和 Batch Normalization 等激活函数,它们可以在训练过程中降低模型的复杂度,从而提高模型的泛化能力。
6. 正则化
torch.nn.Dropout(p=0.5, inplace=False)
功能: 随机性失活
参数:
p:被舍弃的概率,失活概率,默认0.5
nn.Dropout
功能:Dropout层
参数:
P:
被舍弃概率,失活概率
7. 采样:
下采样和池化应该是包含关系,池化属于下采样,而下采样不局限于池化,如果卷积 stride=2,此时也可以把这种卷积叫做下采样
7.1上采样(Upsampling):
上采样是指增加信号或图像的采样率或分辨率,从而使其变得更大。它通过插值或填充新的数据点来增加采样点的数量。
在图像处理中,上采样可以用于放大图像,增加图像的尺寸或分辨率。一种常见的上采样方法是使用插值技术(如双线性插值、三次样条插值等)来估算新像素的值。
在神经网络中,上采样也经常用于进行反卷积操作,例如转置卷积(Transposed Convolution),以便从低分辨率特征图中恢复高分辨率特征图,用于图像分割、超分辨率重建等任务。
7.2下采样(Downsampling):
下采样是指减少信号或图像的采样率或分辨率,从而使其变得更小。它通过跳过或合并数据点来减少采样点的数量。
在图像处理中,下采样可以用于缩小图像,减少图像的尺寸或分辨率。常见的下采样方法包括平均池化(Average Pooling)和最大池化(Max Pooling),它们通过在图像区域上取平均值或最大值来降低分辨率。
在神经网络中,下采样也经常用于卷积层中的步幅(stride)操作,或者池化层(Pooling Layer),用于缩小特征图的尺寸并提取更高级别的特征。
8. 一些改边维度的常用的函数
x = x.view(b_s, nq, self.h, self.d_k),
这一步首先使用 view 方法对x张量进行形状变换。具体地,将x张量重塑为一个四维张量,其中 b_s 是批大小(batch size),nq 是查询数量(number of queries),self.h 是头数(number of heads),self.d_k 是查询的深度(depth of queries)
x = x.permute(0,2,1,3)
output = torch.reshape(imgs, (1, 1, 1, -1))
也可以将reshape(imgs, (1, 1, 1, -1))改成reshape(imgs, (-1,))就和flatten(imgs)效果一样
使用 permute 方法对张量的维度进行置换。这里的参数 (0, 2, 1, 3) 指定了维度的新顺序。具体来说,原始的张量维度顺序是 (b_s, nq, self.h, self.d_k),经过置换后,变为 (b_s, self.h, nq, self.d_k)。换句话说,原来在第二维的x数量现在在第三维,原来在第三维的头数现在在第二维
综合起来,这行代码的作用是将原始的查询张量重塑为一个四维张量,并将查询数量和头数的维度进行置换,以满足后续计算操作的需求
9. 关于类调用
class SimplifiedScaledDotProductAttention(nn.Module):
def __init__(self, d_model, h,dropout=.1):
def init_weights(self):
def forward(self, queries, keys, values, attention_mask=None, attention_weights=None):
if __name__ == '__main__':
ssa = SimplifiedScaledDotProductAttention(d_model=512, h=8)
#会默认调用def __init__( ):,然后把参数传递到这个函数里面去
如果这个函数里面有self. init_weights(self)、forward(self, queries, keys, values, attention_mask=None, attention_weights=None):,则也会同时执行这两个函数
如果print(ssa),则由于类没有定义自定义的 __str__ 方法,因此打印 ssa 实例对象时,会默认输出类名以及对象的内存地址,要想让 print(se) 输出更有意义的信息,你可以在 SKAttention 类中自定义 __str__ 方法,返回你希望打印的字符串信息。例如:
def __str__(self):
return "SKAttention module with channel={}, reduction={}".format(self.channel, self.reduction)
如果再往ssa里传参数, output=ssa(input,input,input),则#会默认调用类中的forward( ):,然后把参数传递到这个函数里面去
而如果想要类中的init_weights(self):执行的话,要么就是在其他函数中调用了这个函数,然后被顺带执行,要么就得专门得去调用这个方法才能被执行,而不会通过实例化被默认执行
10. nn.Flatten()函数详解及示例
input = torch.randn(32, 1, 5, 5)
# With default parameters
m = nn.Flatten()
output = m(input)
output.size()
#torch.Size([32, 25])
# With non-default parameters
m = nn.Flatten(0, 2)
output = m(input)
output.size()
#torch.Size([160, 5])
11. 简单的基本网络架构
12. 损失函数
常见的损失函数有:nn.L1Loss、nn.MSELoss、nn.CTCLoss、nn.NLLLoss、nn.CrossEntropyLoss
交叉熵一般会和softmax回归一起使用
在深度学习中,交叉熵损失通常用于衡量模型输出的概率分布与真实标签之间的差异。模型的目标是最小化交叉熵损失,以使其输出的概率分布尽可能地接近真实标签的分布。因此,当交叉熵损失越小时,模型的预测结果与真实标签的匹配程度就越好,模型的性能也就越好。
- 优化器
优化器就是损失函数进行反向传播后,根据反向传播(forward)的梯度值,来调整参数,使其损失函数降低
optimizer = torch.optim.AdamW(param_groups, lr=args.lr, betas=(0.9, 0.95))
1.关于前面说的loss怎么和优化器关联
4.loss函数在其中只是起到了一个提供梯度的作用,而这个梯度就藏在optim中
14. Dense层
Dense层可在model中添加神经网络层,model.add(Dense())。
下图(从网上找的图)的黑圆圈为神经元,输入层的神经元会将输入数据直接传递给下一层,在下一层的神经元中对输入值进行处理。因此用Dense层作为输入层时,同时增加了输入层和隐藏层。
13.dim、chanel 、depth
Dim = (B,N,C)中的
Depth =分类、分割中有好几个stage,depth为其中一个stage有好几个Block,depth为一个stage中Block的个数
15. 特征融合方式
Cat
Add
16. 数据预处理
图片转化分辨率大小
17. 模型正确性检验
18. 模型的保存与加载
保存
加载
自己的模型用第一种
19. 网络架构
20. 分类模型
21. 微调
22. 可视化模型
# 可视化模型
# writer = SummaryWriter("./logs_sql")
# inputt = torch.randn(2,3,224,224).to(device)
# writer.add_graph(model,inputt)
# writer.close()
23. 修改网络结构
23.1: 修改pytorch提供的现有的模型,并对这些模型进行修改
教程:
23.2:对从github上下载的模型进行修改
一般都是先去找到他的model.py文件,然后去它的类里面添加/删除一些层
24. backward()
backward()是对loss使用的计算grad梯度 反向传播
所以是反向传播来计算梯度,根据梯度来更新参数,实现loss最小化
25. GPU OR CPU train
AMD显卡用 import torch_directml device = torch_directml.device()
26. 小tips
一般卷积后跟relu(激活函数),卷积(一般都是增加维度outchannel)->激活->池化(也叫下采样,池化一般会减小H、W,损失的长宽通过卷积增加维度弥补回来)
只有带参数运算的才能算作为一层神经网络(CONV 、全连接层算),通常我们在卷积后要先进行归一化batchnorm2d 操作,再激活函数的时候,压力就比较小(送进去的数据比较规范),同时也会避免一定程度的梯度爆炸或梯度消失。
- 增加维度使用卷积,如只想改边维度不改变长宽,可以使用(1x1的卷积核)
conv1x1 = nn.Conv2d(x.size(1), C_y:输出通道数, kernel_size=1).to(device)
- 如果我们只想改边H、W的话,我们可以使用池化进行上采用(增加H、W,Bilinear Interpolation、Nearest Neighbor Interpolation)或者下采样(降低H、W,Average Pooling、Max Pooling)
self.Block = nn.Sequential(
nn.MaxPool2d(3, stride=1, padding=1),
nn.Conv2d(input_channels, pool_proj, kernel_size=1),
nn.BatchNorm2d(pool_proj),
nn.ReLU(inplace=True)
)
import torch
import torch.nn as nn
class MyModel(nn.Module):
def __init__(self, num_classes=10):
super(MyModel, self).__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=1)
self.bn1 = nn.BatchNorm2d(32)
# 添加其他层...
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = torch.relu(x)
# 继续前向传播...
return x
class ResidualBlock(nn.Module):
def __init__(self, in_channels):
super(ResidualBlock, self).__init__()
self.conv1 = nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(in_channels)
self.relu = nn.ReLU(inplace=True)
self.conv2 = nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(in_channels)
def forward(self, x):
residual = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
out += residual
out = self.relu(out)
return out
class SelfAttention(nn.Module):
def __init__(self, in_dim):
super(SelfAttention, self).__init__()
self.query_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim // 8, kernel_size=1)
self.key_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim // 8, kernel_size=1)
self.value_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim, kernel_size=1)
self.softmax = nn.Softmax(dim=-1)
def forward(self, x):
batch_size, C, width, height = x.size()
query = self.query_conv(x).view(batch_size, -1, width * height).permute(0, 2, 1)
key = self.key_conv(x).view(batch_size, -1, width * height)
value = self.value_conv(x).view(batch_size, -1, width * height)
attention = self.softmax(torch.bmm(query, key))
out = torch.bmm(value, attention.permute(0, 2, 1))
out = out.view(batch_size, C, width, height)
return out
[1] Lu和Weng, 《A Survey of Image Classification Methods and Techniques for Improving Classification Performance》.