一.前言
自己研究了一段时间的深度学习,在GPT的辅助下可以基本看懂代码,但是自己上手才发现学的不清不楚,借此机会做个总结
二.深度学习代码的构成
1.目录树的搭建
在写(抄)代码之前,需要保证有一个合适的目录结构方便我们更好的梳理自己的代码,更好的管理输入和输出数据,不容易沦陷在屎山中,如下图
下面时一个例子,也是个人认为的一个小纲要
└──root
├──数据集
│ ├──shuju.zip(有很多可能的格式,需要相应函数)
│ ├──数据文件夹
│ │ └──可以将训练集/测试集/验证集分开来存,也可以一起
│ │
│ └──标签 ( 如果标签简单的话不需要进行专门储存)
│
├──数据读取器
│ ├──读取数据到数组中(有时需要做切割,部分当训练部分当测试)
│ ├──数据标准化/清洗
│ ├──数据增强 (可能有旋转,调色等等多种手段)-
│
├──定义神经网络
│ ├──激活函数,网络层数,梯度惩罚的选择
│ └──forward(优化模型的定义)
├──模型训练
│ ├──输入-计算-回传-优化-梯度置为0
│ └──涉及正则化和学习率选择等等
│
├──验证accarcy和泛化能力
│ ├──对测试集和训练集测试,记录准确率
│ └──结果画成图 或 打印训练日志
│
└──输出窗口设定(各种输出自行决定)
上面的部分介绍了目录树的搭建,接下来就需要针对各部分的内容进行一些解释
2.项目建立
这一部分的内容主要包括构建储存结构,下载数据集,数据的分类整理。
储存结构的构建涉及到代码的可读性,在整理数据集的时候有一个比较明确的分层结构有助于更好的完成分类,一个相对完整的项目可以由这几部分组成
datasets文件夹:存放需要训练和测试的数据集
dataset.py:加载数据集,将数据集转换为固定的格式,返回图像集和标签集
model.py:根据自己的需求搭建一个深度学习模型,具体搭建方法参考
config.py:将需要配置的参数均放在这个文件中,比如batchsize,transform,epochs,lrtrain.py:加载数据集,训练
predict.py:加载训练好的模型,对图像进行预测
requirements.txt:一些需要的库,建议对版本做一个记录,方便解决版本之间的冲突
readme:记录一些log
log文件:存放训练好的模型
loss文件夹:存放训练记录的loss图像
上面的文件结构树则是《一个相对能跑的项目》,凑合着用咯
在“复现”代码的过程中,先把数据集大小和其他部分调试好,会给后续的操作减少很多麻烦,解压,文件批量重命名,文件转化为np或者是其他的形式在代码开写前期最好就要进行测试,特别是对各个环节拆分出的数组大小进行统一规范化,尽可能考虑到输入模型的不同数据集大小关系。
ps :label和数据的命名部分最好一样!不然很麻烦
3.数据处理和数据增强
a.数据增强
数据增强有很多种不同选择,这里用图片为例
光照变换:随机亮度变换、对比度变换、色彩度变换、饱和度变换、噪声变换。
几何变换:随机缩放、裁剪、翻转、旋转、平移
遮挡变换:
- Random erase(随机删除,在图上随机遮挡某一部分的像素)
- Cutout(按照一定的间隔遮挡N*N像素大小的小格子,类似于给图片加噪声)
- hide and seek(按照更大的间隔遮挡N*N像素大小的小格子,是具有规律的等距间隔的小格子,N一般取值更大一些)
- Grid Mask(网格掩码,采用的方法是先把图像进行分成不同的格子,然后按照一定的方法去挑选遮挡某些格子,增加正样本的权重)
- Dropblock(对图像数据使用dropout,然后再将多个dropout之间连成块,以此达到遮挡的目的)
混合变换:主要是图片直接融合操作
b.数据清洗和数据标准化
数据清洗主要包括数据去噪、脱敏、缺失处理、查重、删除错误数据
数据查重是指数据集中存在着同一条数据,最简单的方法就是统计一下每条数据的均值方差,如果有均值方差相同的数据,就认为是同一条数据,可以直接删除。
数据的缺失处理是指在某些缺失的数据中补全缺失的部分,可以使用插值的方法,也可以通过生成模型来生成新的数据来补全数据,使补全后的数据整体的离差平方和最小。
数据脱敏是指将原数据中对模型训练无用的某些敏感的信息去除,从而能够安全的让训练人员的使用数据,比如医疗数据中的患者的信息就属于敏感信息。
数据去噪是数据清洗过程中最关键的,其主要因素就是如何定义噪声,也就是如何区分模型真正需要数据信息和其他冗余信息。我们需要去除真正的数据噪点,比如高斯噪声、椒盐噪声等,对于这类数据的噪声,一般是平滑滤波去除掉噪声部分,一般噪声部分的梯度要高于其他部分的梯度,去除了噪声,在模型的预测过程中,会让预测精度又更高的提升。
接下来是数据标准化
数据标准化就是统一数据的量纲,让不同维度的数据都能够适应某一规则的约束。减小异常数据对于模型训练的影响,更好的获取数据中有效的特征。
在网络模型训练过程中,对网络层中的特征数据进行标准化是为了防止模型在训练过程中出现梯度爆炸、梯度弥散等情况的发生,也能在一定程度上防止模型的过拟合。在训练过程中做了数据标准化后还会加快模型的训练速度。
在其他一些情况下,我们也可以引入一些函数来改变数据之间的分布,例如我们处理运动员的成绩就可以采取中间平滑,两头斜率大的函数处理,这表示了接近最大值后增长难度大,在计算机认知中,二者的向量距离也因此变得更大了
这里附上亿些函数
4.定义神经网络
【深度学习】——pytorch搭建模型及相关模型_self.conv1 = nn.sequential(-CSDN博客
下面需要涉及一个神经网络模型的具体搭建,通常分为这些步骤
- 选择网络架构:确定网络有多少层,每层有多少节点,以及这些层如何连接。
- 初始化参数:网络中的每个节点都有权重和偏置,它们需要被初始化。
- 选择激活函数:决定每个节点将使用哪种激活函数来引入非线性。
- 定义损失函数:确定一个损失函数来评估网络的表现。
- 选择优化器:选择一个优化算法来调整网络参数,以最小化损失函数。
a.总体认识
首先需要了解的是深度学习网络的大致都成,其中具体的名词解释可以自行查阅
我们需要定义的主要是“神经网络”下面的这些模块
b.选择网络架构
在上图中看到的三个网络是一些比较常见的层级连接方式,代表性的模型有CNN(卷积神经网络)、RNN(循环神经网络)、transform(自注意力神经网络)以一篇论文中的图解为例
这就是结合了循环网络和卷积神经网络的一个模型
在学习深度学习的时候,主要需要理解不同的模块之间结合方式,有助于后续的模型改动
c.激活函数
激活函数是神经网络中非常关键的组成部分,它决定了一个节点是否应该被激活,即输出的信号强度。它们的作用是帮助网络捕捉输入数据中的非线性关系。有很多很多的激活函数,需要根据具体情况选择,选择的时候需要了解一下不同函数的特征(列举几个了
Sigmoid:将输入压缩到0和1之间,常用于输出层的二分类问题。
Tanh:将输入压缩到-1和1之间,形状和Sigmoid类似,但是输出范围更宽。
ReLU:如果输入是正数则直接输出,否则输出0,它解决了梯度消失的问题,让网络能够更深。
d.损失函数
本质上损失函数便是深度学习过程中需要收敛的一个函数,对结果进行一个“不正确评分” ,让这个评分靠近0,就代表着识别的结果变得更加准确,简单的模型中(数字识别)一类损失函数很简单,因为只有“正确”和“不正确”两种结果,下图中的“决策函数”代表的预估的点落在不同部分表示的不同结果,复杂的输出结果可能让loss变得更加有价值。如果是语言大模型则需要引入一些新的东西来评估loss值,loss_fn = nn.MSELoss()(典
e.前馈算法 forward()
这个算法便是数据在进入模型之间需要“经历”的过程,forward也可以简单理解为“画图画出来的模型”,模型搭建就在这里面
class Net(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(SimpleNet, self).__init__()
self.fc1 = nn.Linear(input_size, hidden_size) # 第一层
self.activation = nn.Tanh() # 激活函数
self.fc2 = nn.Linear(hidden_size, output_size) # 输出层
def forward(self, x):
x = self.fc1(x)
x = self.activation(x)
x = self.fc2(x)
return x
f.梯度优化
optimizer = optim.SGD(model.parameters(), lr=0.001) # 随机梯度下降优化器 # 前向传播 y_pred = model(t_u) loss = loss_fn(y_pred, t_c) # 反向传播 optimizer.zero_grad() # 清空之前的梯度 loss.backward() # 计算梯度 optimizer.step() # 更新参数
y_pred就是预测结果,而梯度优化调节主要如下
学习率调整
动量(Momentum)
正则化技术:
- L1和L2正则化:通过在损失函数中添加正则项来防止过拟合。
- Dropout:在训练过程中随机丢弃一些神经元的输出,以增加模型的鲁棒性。
早停(Early Stopping):
- 当验证集上的性能不再提升时停止训练,以避免过拟合。
使用更好的优化器:
- 选择适合问题的优化器,如SGD、RMSProp、Adam、AdaDelta等。
使用学习率预热(Learning Rate Warm-up):
- 在训练初期使用较小的学习率,随着训练的进行逐渐增加学习率。
使用不同的初始化方法:
- 合适的参数初始化可以加速收敛,如He初始化、Xavier初始化等。
使用超参数优化:
- 通过自动化的方法(如网格搜索、随机搜索、贝叶斯优化)来寻找最佳的超参数组合。
5.训练和验证
其实前面的梯度优化等就已经涉及到了训练过程和验证过程,主要是将在训练集上训练出的模型用测试集来“考试”一下
验证集相当于“单元小测”,在每一轮训练结束的时候,就可以检测一轮的学习效率,重点是为了观察“收敛速度”
而测试集合用来观测最终的结果,在全部学习完成后进行检测,重点在于”泛化性“
下面是k折验证法的图,可以了解一下,不同的集分配方法可能也会影响结果
6.打印和美工集合
在训练过程中打印log,画图,各种评估值影响着每个项目的理解,这里列举搜集一些比较重要的知识
tqdm生成训练进度条
一些深度学习训练过程可视化以及绘图工具_深度学习结果数据绘图-CSDN博客
深度学习训练模型时将每个epoch的结果输出到log文件中(涉及知识点loguru包的使用)_深度学习项目训练时打印的参数在哪个文件里-CSDN博客