SINet复刻,第一次深度学习模型训练

写在前面

这是我第一次接触深度学习,起因是我这学期选了学校的人工智能基础专业课的挑战性课程,这个课程要求里面需要我们定期完成一个项目任务,第一个任务就是伪装目标识别,在网上查找了各种实现方案后,选择了 SINet 这个深度学习模型,项目地址:SINet 训练集优秀,模型还算简单,训练时间也短,容错率高。

PS:需要识别的内容如下:

找出图中的猫头鹰

SINET-1.jpg

找出图中的海马

SINET-2.jpg

找出图中的三只青蛙

SINET-3.jpg

下面是我作为一个从来没接触过深度学习,Linux 和 Python 的纯小白从零开始完成项目的全过程,有兴趣的同学也可以按照以下的步骤 1:1 复刻这个项目。

前期准备

  1. Python3 速通。因为有 Java 基础加上以前尝试入门过一段时间 ACM ,速通比较快,三天基本能基础入门,入门教程在这:菜鸟教程——Python3

  2. Linux 速通主要是对 Python 虚拟环境隔离,各种深度学习框架的了解,包管理的应用,需要简单了解的知识如下:Conda 构建虚拟环境,Conda 管理依赖,pip 管理依赖,Linux 上配置对 Nvida 的驱动和加速库 apex.

  3. 一张 Nvidia 的显卡,由于项目年代久远(2020前),所以,建议是租一张 20 系的显卡,我选择的是 AutoDL 平台的 2080Ti 显卡,因为 30 系以后都是新的结构不支持 CUDA10.0 的驱动,而项目是在 CUDA10.0 的环境下运行的,所以不建议用太新的显卡,以免 Nividia 的驱动犯病。

So Nvidia, F__k you!.mp4

环境部署和训练

AutoDL 上租一个 2080Ti 的显卡。

镜像文件选择:PyTorch / 1.1.0 / 3.7(ubuntu18.04) / CUDA10.0

开机后我选择 JupyterLab 进行环境部署和项目运行,也可以选择 PyCharm 和 VScode 的 SSH 远程连接操控服务器,但是可能会出现 SSH 连接中断导致进程中断的问题,相比之下 JupyterLab 就比较稳定。

打开终端,进行环境部署,下面是需要用的指令,可以直接跑在在 Jupyter 的 code cell 里,但由于是一次性设置,我是直接在终端里敲的,后面训练模型的指令可以直接写在 cell 里面方便运行:

# 更改清华源,下载包更快
conda config --add channels http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --add channels http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/
conda config --add channels http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
conda config --add channels http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r/
conda config --add channels http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2/
conda config --set show_channel_urls yes

# 创建虚拟环境
conda create --name Env_COD python=3.6
# 激活虚拟环境
source activate Env_COD
# 关闭虚拟环境
source deactivate Env_COD

#配置虚拟环境中的包(参考requirement.txt的要求),pytorch 用自带的 anaconda 安装,自动配置 CUDA 版本,有两个 pip 装有问题换 conda 装
pip install -r requeriment.txt
pip install pillow==6.2.2
conda install -y torchvision==0.4.2 pytorch==1.3.1

# 安装 apex 需要满足一些依赖关系,例如 CUDA 和 CuDNN,因此请确保环境中已经安装了这些依赖项(无GPU环境无法安装)
# 重置代理(重置失败可以开一个新终端,在 root 终端下重置)
git config --global  --unset https.https://github.com.proxy 
git config --global  --unset http.https://github.com.proxy 

# 安装 apex 回滚旧版本,参考下面的 issues 页面,新版本的 apex 不兼容,用不了,必须回滚旧版本
# So Nvida, F__k you!!!

https://github.com/NVIDIA/apex/issues/802

部署完环境后,将项目 SINetMaster 上传服务器,然后按照代码里的要求,上传 COD10K 训练集,AutoDL 提供了网盘功能,可以先上传网盘后复制过去。JupyterLab 只支持上传文件,不能上传文件夹,上传 zip 文件后解压。

MyTrain.py 中更改一些设置以适配自己的 GPU 环境,单核 GPU 记得设置 GPU 参数为 0 ,以下是我的其他设置:

Defaults for this optimization level are:
enabled                : True
opt_level              : O1
cast_model_type        : None
patch_torch_functions  : True
keep_batchnorm_fp32    : None
master_weights         : None
loss_scale             : dynamic
Processing user overrides (additional kwargs that are not None)...
After processing overrides, optimization options are:
enabled                : True
opt_level              : O1
cast_model_type        : None
patch_torch_functions  : True
keep_batchnorm_fp32    : None
master_weights         : None
loss_scale             : dynamic
------------------------------ 
[Training Dataset INFO]
img_dir: ./Dataset/TrainDataset/Image/
gt_dir: ./Dataset/TrainDataset/GT/
Learning Rate: 0.0001
Batch Size: 18
Training Save: ./Snapshot/2020-CVPR-SINet/
total_num: 162

在虚拟环境中运行 MyTrain.py 文件就可以了,假如模型训练正常,日志输出会是这样的:

[2023-03-13 22:00:27.224874] => [Epoch Num: 001/040] => [Global Step: 0000/0162] => [Loss_s: 0.7317 Loss_i: 0.7316]
[2023-03-13 22:00:32.736549] => [Epoch Num: 001/040] => [Global Step: 0010/0162] => [Loss_s: 0.6896 Loss_i: 0.6328]
[2023-03-13 22:00:38.236188] => [Epoch Num: 001/040] => [Global Step: 0020/0162] => [Loss_s: 0.5505 Loss_i: 0.5523]
[2023-03-13 22:00:43.877760] => [Epoch Num: 001/040] => [Global Step: 0030/0162] => [Loss_s: 0.5084 Loss_i: 0.4677]
[2023-03-13 22:00:49.472075] => [Epoch Num: 001/040] => [Global Step: 0040/0162] => [Loss_s: 0.4314 Loss_i: 0.3850]
......

模型训练的时候可能会遇到以下日志信息:

Gradient overflow.  Skipping step, loss scaler 0 reducing loss scale to 8192.0
Gradient overflow.  Skipping step, loss scaler 0 reducing loss scale to 4096.0
Gradient overflow.  Skipping step, loss scaler 0 reducing loss scale to 2048.0
[2023-03-13 22:26:59.133189] => [Epoch Num: 016/040] => [Global Step: 0130/0162] => [Loss_s: 0.4977 Loss_i: 0.3282]
Gradient overflow.  Skipping step, loss scaler 0 reducing loss scale to 1024.0
Gradient overflow.  Skipping step, loss scaler 0 reducing loss scale to 512.0
Gradient overflow.  Skipping step, loss scaler 0 reducing loss scale to 256.0
[2023-03-13 22:27:04.482682] => [Epoch Num: 016/040] => [Global Step: 0140/0162] => [Loss_s: 0.3705 Loss_i: 0.5197]
Gradient overflow.  Skipping step, loss scaler 0 reducing loss scale to 128.0
[2023-03-13 22:27:10.019387] => [Epoch Num: 016/040] => [Global Step: 0150/0162] => [Loss_s: 0.3254 Loss_i: 0.4969]
[2023-03-13 22:27:15.629497] => [Epoch Num: 016/040] => [Global Step: 0160/0162] => [Loss_s: 0.3327 Loss_i: 0.3445]
[2023-03-13 22:27:24.814023] => [Epoch Num: 017/040] => [Global Step: 0000/0162] => [Loss_s: 0.2841 Loss_i: 0.3088]
[2023-03-13 22:27:31.884748] => [Epoch Num: 017/040] => [Global Step: 0010/0162] => [Loss_s: 0.3426 Loss_i: 0.4250]
Gradient overflow.  Skipping step, loss scaler 0 reducing loss scale to 64.0

Gradient overflow 表示梯度爆炸,损失函数 loss 飙上八千多,其实就是趋近无穷大,这个是 ResNet50 里面常见的问题,假如 Gradient overflow 次数不多,那问题还不大,但如果 Gradient overflow 经常出现,则表示梯度严重溢出,会导致模型严重不稳定,影响训练效果,至于如何解决,上网搜搜吧(我也不是很清楚)。

训练的时间大概为一个小时,所以还挺快的。

训练结束后,会多一个文件夹 ./Snapshot/2020-CVPR-SINet/ ,里面 .path 文件就是训练的模型,训练好后可以用原项目里提供的几种的测试集测试效果,MyTest.py 里面加上测试集文件夹就行,假如想直接测试自己的样本图片的识别效果(无 GT 参考),就把自己的样本图片复制一遍在 GT 文件夹里,然后直接运行 MyTest.py 就行,生成的灰度图(置信图)会在 result 文件夹里。

参考结果

这是我自己的训练结果:
SINET-11.png

SINET-22.png

SINET-33.png

结果汇总:

SINET-final.jpg


写在最后

最后看到自己的结果还不错,感觉还是挺有成就感的,虽然时间很紧迫,道路也很挫折,各种各样的 BUG 也很折磨,不过算的上是摸到了门槛,另外这个训练模型我也保存 AutoDL 的镜像,大家需要的话邮件给我发自己的 AutoDL 用户 ID ,我看到后会分享自己的镜像的。

最后,Nvidia 你的软件支持做的真的烂透了!