DANet(Dual Attention Network for Scene Segmentation)在语义分割领域多个数据集上取得了STOA的结果,值得大家关注。
【废话两段】
由于之前没跑过语义分割的网络,github上的介绍对于我来说过于简单,花了两天时间才跑通DANET的代码,这里记录一下踩过的坑。
大神可以直接看官方github的内容 https://github.com/junfu1115/DANet
话不多说,我的电脑配置4x2080Ti
,操作系统Ubuntu 16.04
, 按照模型作者推荐的使用conda搭建的一个python3.6
虚拟环境,运行setup.py中的程序包。然后就开始遇到各种问题了
文章目录
代码调试
RuntimeError: Ninja is required to load C++ extension
google上搜到一个可行的解决方案如下
wget https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-linux.zip
sudo unzip ninja-linux.zip -d /usr/local/bin/
sudo update-alternatives --install /usr/bin/ninja ninja /usr/local/bin/ninja 1 --force
参考:https://github.com/zhanghang1989/PyTorch-Encoding/issues/167
ImportError: No module named ‘ipdb’
这个问题的解决比较直接
pip install ipdb
参考
https://stackoverflow.com/questions/34804121/importerror-no-module-named-ipdb
cityscapes数据集的预处理
这里就比较费功夫了,作者在github只说了到cityscapes上下载数据集然后再转换成19类的数据,具体的操作就只字没提了。
这里作者可能默认大家都是搞语义分割的高手,基本操作就直接忽略了。
在这我就重点分享一下这里的操作细节:
数据集下载
去cityscapes官网的Download页面下载:gtFine_trainvaltest.zip (241MB) [md5]
和leftImg8bit_trainvaltest.zip (11GB) [md5]
两个数据集
下载完成后解压,关于数据的详细面熟可以在cityscapes数据介绍和处理获得
标签处理
这一步很关键:cityscapes原数据共定义了34类,而DANET只使用了19类。因此需要对监督学习的输出图像进行处理。
cityscapes数据介绍和处理为用户提供了相关的数据处理程序,用户根据自己的需求减少已有的类别,生成新的标签数据集合。真的不是要太贴心!!!
我直接安装cityscapesscripts,然后运行createTrainIdLabelImgs.pyj就可实现新数据的转换
python -m pip install cityscapesscripts
python createTrainIdLabelImgs.py
详细介绍和操作流程可参考:
https://blog.youkuaiyun.com/chenzhoujian_/article/details/106874950
生成数据索引txt文件
完成数据转换以后,将数据放到./experiments/cityscapes
目录下,距离成功还差最后的数据索引txt文件
根据encoding/datasets/cityscapes.py中可以确定需要生成如下三个重要的文件:
train_fine.txt
val_fine.txt
test.txt
这里直接放我的代码,生成以后就可以按照github上的初始配置训练了
import glob
def make_txtfile(num, mode=None):
i = 0
# for the DANET the txt filename
if mode == "train" or "val":
txt_name = mode+"_fine"
else:
txt_name = mode
imgs = glob.glob("./datasets/cityscapes/leftImg8bit/"+ mode + "/*/*.png")
with open("./datasets/cityscapes/"+ txt_name +".txt", "w") as f:
for path in imgs:
path = path[22:] # delete "./datasets/cityscapes/"
data = path + "\t" + path.replace("leftImg8bit", "gtFine").replace("gtFine.png", "gtFine_labelTrainIds.png") + "\n"
f.write(data)
i +=1
if i == num:
break
print('write the ', "./datasets/cityscapes/"+ mode+".txt")
if __name__ == '__main__':
train_num = 2975
val_num =500
test_num =1525
make_txtfile(train_num, mode='train')
make_txtfile(val_num, mode='val')
make_txtfile(test_num, mode='test')
参考:
https://blog.youkuaiyun.com/chenzhoujian_/article/details/106873451
https://www.cnblogs.com/leviatan/p/10683325.html
https://blog.youkuaiyun.com/wang27623056/article/details/106631196
代码解析
个人觉得模型的亮点就是具有两组self-attention机制的注意力模块,所以先介绍两个模块的计算流程,再介绍总体框架的部署情况。
Position Attention Module
数学原理
数学计算流程如下:
- 对于深度卷积网络的某一特征层 A ∈ R C × H × W A\in \mathbb{R}^{C \times H \times W} A∈RC×H×W分别进行卷积操作得到三组新的特征层 { B , C , D } ∈ R C × H × W \{\mathbf{B}, \mathbf{C}, \mathbf{D}\} \in \mathbb{R}^{C \times H \times W} { B,C,D}∈RC×H×W
- 将 { B , C , D } \{\mathbf{B}, \mathbf{C}, \mathbf{D}\} { B,C,D}reshape成 { B , C } ∈ R C × N \{\mathbf{B}, \mathbf{C}\}\in\mathbb{R}^{C\times N} { B,C}∈RC×N,其中 N = H × W N=H\times W N=H×W
- 将 B T ∈ R N × C \mathbf{B}^\mathrm{T}\in\mathbb{R}^{N \times C} BT∈R