毕设快要结束了,一路走来一直记录着点点滴滴的技术内容,主要想写给自己看吧,作为一个项目整理的大致框架,改完最终定稿,再填补每一部分的细节。
另外如果以后有做这个方向的朋友看到了,希望能提供一点小小的帮助吧,在下面附上了整个学习路线的各种视频课程的链接和自己的学习笔记链接,万福噢!欢迎批评指正不正确的内容和笔记里的错误。
前言
1、因为论文读的少,研究的深度不够,导致内容整体看下来很肤浅,体现的工作量很小,给人的感觉不过是调用了API,修改了一下参数,跑了遍数据集而已,没有任何的新颖的添加。————实验结果的结论写的太肤浅,不够深入。我认为是我的路线走的有些问题,学习内容安排不合理。到后期实在是跑完三个模型的各两组数据集就不想再动了,前期研究代码的过程,对于输入 / 输出数据维度的分析,各种涉及的原理,维度,以及研究2维与3维区别等等耗费了我特别多的时间,我不知道搞清楚他们的原理有没有必要,但我觉得还是很有意义的,起码在希望根据自己的意愿,搭建属于自己的2维网络模型方面很有帮助。————毕设过分关注实践即代码的实现了,而弱化了对论文的研究和对理论的深入理解与挖掘。
因此想写一篇总结,也算是帮自己做一个学习路线的梳理,告诉自己存在的不足,当然还有收获
工作总结
1月初 寒假前
完成了开题报告
搭建好了深度学习的环境pytorch,弄好了conda
WIN10下pytorch环境配置
关于Anaconda实现对Python环境管理过程中遇到的系列问题及其解决方案
2月中下旬到3月初
学习b站刘二大人的 《PyTorch深度学习实践》完结合集,并未上机操作——效果非常差
python光速入门课
- 大致了解了python的基本语法,如列表,字典,元组,以及本质是指针而非赋值。这也为后来的调试工作,对每一个数据结构,形态清晰,以及操作修改打下基础。后期的操作修改有如:取标签与颜色对应的索引表、加载下载数据集、修改visdom可视化、读写修改文件open、os.joinpath、类class、with等等debug起到帮助
开学3月10日到3月16日
每天3到4个lesson的进度,回顾寒假只在纸上学习的刘二大人的实践课(原先的笔记分享链接,太乱了orz。为了复习,整理了重要的内容,上传博客了)
-
第一阶段
-
从自建梯度下降到后来难度提升的图像分类的数据集加载
-
学习阶段遇到的障碍很多:
- 对于梯度下降、反向传播backward()课,最基本的原理又产生了疑惑:计算图与tensor的关系tensor的关系、grad(在后面一个项目中,比如迁移学习,只会出现手动设置require_grad=true之类的)
- 最大的困难就是——从文本数据集到图像数据集的加载问题:从torch自带dataset到自定义dataset的类——>整明白加载数据集的机制dataloader读batch大小数据以及sample采样器shuffle索引得到随机的batch和dataset里的getitem函数要的是一个索引表以及针对三种情况下的图像数据集(以图像为级别的)的加载处理(lesson 8.2和8.3和0.3)——>想办法写出来generate_txt和reorg整理数据到不同类别的文件夹等函数(lesson 0.2 文件操作)
- 分类任务中的target标签问题,这个的理解在后面分析像素级别的分类——语义分割时也有很帮助,以及离散化标签——onehot
- 每个iteration数据集是多大的——batch size,在dataloader中体现——index,batch与iteration与epoch关系等原理
-
其他学习内容:添加在了python光速入门的文件夹里
-
-
第二阶段
-
进入到全连接baseline和卷积神经网络2D conv中
-
针对input output 做了详细的研究,通过debug断点调试,看到了整个训练过程中各tensor的shape,为后面调试hyperspectral 的项目打下基础
-
学习卷积神经网络基本知识,清楚了卷积的与全连接的区别,卷积的好处是权值共享,参数减少,有重点的提取特征,而全连接则是所有神经元都连接在一起,参数很多,容易过拟合。
-
卷积:
- 经典vgg、Alex net、Googlenet等
- 自己搭最简单的卷积net
- 使用inception搭较复杂的卷积神经网络
- 残差网络( lesson 11.1 )
-
-
3月16日到4月6日 pytorch_lesson文件夹 中间陪复试和清明大约闲置了一周
学习了50个lesson的b站另一个特别好的实践课,是一个男博士 (强推)Pytorch深度学习实战教学
其实所有的项目,最最让我纠结的就是不同分类任务情况中的数据集加载问题,数据集是什么样的?做的是什么分类,怎么加载,dataset怎么写类等
第一阶段
- 卷积神经网络基础知识(lesson 10.1)作用,卷积结果计算、特征图、感受野等
- 卷积网络的参数分析,分析了2D卷积层输入的tensor,通过自己动手搭建NET 类,明白了init函数与前向传播函数的区别
- 残差网络的学习resnet提出的原因——深层网络层数越多效果反而不好了和梯度消失,所以想出了一个输出与输入的连接的办法。训练效果确实更好了
第二阶段 项目实战
-
flower分类的实践课 数据集太大了并且网络太深了用的resnet152,训练一个epoch就要两个多小时
-
数据增强,在dataset类里面进行transform
-
学习到了 迁移学习!————load and save checkpoint ,预训练,从torchvision中选择经典的模型,这在后面的hyperspectral项目中通过修改也用到了。冻住前面的几层,添加适用于当前数据集的分类任务的fc,预加载前面层的参数,只训练这一层,然后再次保存整个模型参数,解锁所有层,将刚刚保存的模型参数重新加载,重新训练,epoch几次就可以达到效果。
-
迁移学习有两种
- 第一种是自己的网络模型,先预训练样本数特别多的数据集,保存网络参数,再加载到样本数少的数据集的任务中,前提是 两种数据集存在很大的特征相似性,比如都是对遥感图像的特征提取,猫狗图像的特征提取(对于图像级别分类和像素级别分类有了较清楚的区别了)
- 第二种是加载经典的网络模型,已经有预训练参数的,如vgg、resnet等,需要首先通过url下载网络模型,然后load,再进行迁移学习
-
-
人脸识别的gender预测项目
- 最大的障碍就是数据集的加载问题(lesson8.3 三种源数据),因为他的标签都在csv文件中而图片没有任何类别的区分的全部集中在一个文件中,需要自己定义dataset类,进行文件操作,分割出train和test集,制作图片的相对路径–标签索引表txt,这与以往的:不同类别已经区分在不同文件夹中——image folder 不同
中途遇到各种使用问题,都记录在了纯应用文件夹中
jupyernotebook使用
conda安装包 找不到channel
同一个项目project中import不同py文件一开始出现的愚蠢问题,对envs文件夹有了认识,不要在一个项目project中建许多个directory文件夹以代表不同项目,一个任务就要单独建一个项目,有一个自己的envs。而一个项目中不同的directory是代表不同的功能,但本质还是同一个项目
pycharm里的终端问题
另外tensorflow的环境也安装了(没想到再安装一个环境这么简单。。)
4.21 中途还出现过内存溢出?无法分配超大内存给某个array之类的。。很玄学,后来修改了环境变量,重启了电脑之后就莫名好了。。。(还不知道到底因为什么)
以及debug也可通过各种print来操作,也比较直观
4月7日到4月23日 中间闲置了大约4天
开始了漫长的论文题目的项目实践,从CSDN上找到了一个窝工的博主(ID:Harry嗷 [高光谱] (6w字巨详细) GitHub开源项目Hyperspectral-Classification的解析)和西安的博主(ID:焦海龙 基于卷积神经网络的高光谱分类 CNN+高光谱+印度松数据集),下载了GitHub上的hyper spectral项目的代码。这里也做了文件夹记笔记,写的不条理暂时不分享了。
每个阶段都有不同的目标
第一阶段
- 就希望能运行通即可。所以一开始研究清楚别人写的代码什么意思花费了不少时间。这里非常幸运,参考的这个工程的代码结构非常完整,条理,但比较复杂,很容易弃坑。参考着readme和窝工的博主的main帖子,逐渐理解了每个函数在做什么,模仿了窝工博主记录下了整个函数流程。
- 第一次接触到了args解释器,原来在pycharm的terminal就可以运行,输入-h还能看到自己定义的args的各参数内容(即help),一开始是下载数据集和visdom可视化里的变量名,搞懂之后就理解了整个代码在运行时是在干啥了,一次一个数据集和一个model。也见识到了很简洁的赋值语句,对字典的操作等。归功于前期打下的debug基础,看代码的执行顺序,看各变量的情况以及感谢窝工博主的技术文档。
- 通过debug也看到了image三维数据的样子,和gt是什么。一个是三维的一个是二维的
第二阶段 这里也花了大约一周半的时间一直在思考咋可视化,期间有许多疑惑
-
1遇到的一个障碍同样是对数据集的疑惑,疑惑
-
看到了HyperXdataset类里面get_item得到的是每个像素的(x,y)我才恍然大悟原来高光谱的图像分类是以像素级别的,gt中每一个像素都有人工标记的标签。
-
这里就要详细说一下图像级分类如猫狗识别与像素级分类区别了:
- 图像级,dataset是以整幅图像作为输入的,处理的也是像素值,但标签对应的是每张图对应的标签。所以它的损失函数计算的是对整幅图各个像素进行卷积运算后得到的值在不同类别中的概率分布值output先经过softmax非负归一化后与整幅图对应的标签target进行onehot的值。batch size是指每次iteration时,同时处理多少张图。
- 像素级,dataset是以单个像素(适用于一维卷积,仅一个沿着光谱的特征向量)或者patch size的像素区域,代表空间域的像素区域。第一次出现patch还是很懵逼的,看到代码之后,就理解了。标签对应的是中心点处的像素点对应的标签,当然仍然存在batch size,在这里batch就指的是每次iteration时,输入多少个patch大小的图像块。
- 当我研究到这里时,我才恍然大悟他与之前做了那么久的图像分类任务的区别,于是去查资料找图像分类、分割、目标检测等各种任务的区别,才发现高光谱图像分类更像是语义分割任务,因此有mask掩模版应用。
- 另外,高光谱图像数据集是.mat文件,通过debug也发现了,image是一个矩阵,存储着不同波段下空间域中每一个像素位置上的灰度值。而gt标签文件则是二维的,表示每一个像素位置上的标签类别。
-
-
2另一个疑惑是模型,输入是什么,卷积核是什么前向传播是什么?以及如何加载自定义模型
-
一开始非常排斥研究这个,感觉都已经忘记之前学的内容了,只有真操实练才发现很容易,因为要加一个论文里的PCA的2D模型,于是就根据3D的论文与model里的init和输入参数进行比对,区分出了input(是全部光谱XpatchXpatch)卷积层参数设置(如 输入通道数X卷积核深度X卷积核大小,这里对比3D与2D卷积输入也花了一点时间 见 HSI代码分析文件夹 ,一个是5维输入一个是4维输入,另外在看了论文看到用explicit的公式来表示3D和2D卷积时,就非常理解什么意思了!)另外照着论文复现结构也比较清晰明朗了,网络的结构体现在forward函数里,定义在init函数里。
-
加载自定义模型只需
- 在get_model函数里初始化一下hyperparameter字典的参数,比如batch、patch 、epoch、学习率之类的
- 然后再单独写一个自定义模型的类,里面先定义初始化权值,再定义init不同层,再有一个得到全连接层输入的tensor的size的函数,最后是网络结构的搭建——前向传播forward
-
-
3还有疑惑就是颜色与标签怎么对应的,怎么上色进行可视化的?
- 在main.py里的palette,仔细研究了一下这个变量,知道这是个字典,并且也熟悉了怎么得到k和v。自己写了个for循环,借鉴的之前的generate_txt函数,将颜色与标签一一读出来写进了一个csv文件里,然后就在论文里自己写了个表格,手动设置的颜色与标签对应。。不会用程序画出像混淆矩阵那样的(在修改记录里也有记这个问题的思考过程,最终想出了两种方法,一种是上面的,另一个是想到了flower里的json文件,没有尝试
- 可视化,是用的invert_color函数,每个像素位置都上上与标签对应的颜色,背景板就是(0,0,0)
-
最后基本功能整完之后就开始考虑过程可视化了
-
项目自带的许多功能:
- 损失函数、验证集准确率和可视化分类效果图,混淆矩阵它做的很不好,于是我移植了西安博主的程序进行的plot展示
- 还有特别好的地方在于,网络中间训练的参数个数展示,网络层级结构打印,以及tqcm进度条的可视化能告诉你当前在第几轮第几次iteration中训练
-
我通过移植flower的时间程序,打印了训练的花费时间
-
最后就是在论文中考虑如何添加效果图
- 一个是标签对应颜色的表:程序导出对应RGB值之后,手动画表格。。
- 一个是模型可视化:想了两种方法,尝试后都未果。。tensorboard和另一个可视化工具(在blog里)然后就手动processon画了类似于刘二大人的框图了。。
- 可视化这里是个很了不起的工具,值得再研究,涉及到许多变量,你要去懂他是什么类型,shape?然后才能为你所用
-
4月24日到4月30日实际写论文,完成草稿的过程
- 前期一直在跑程序,做实验,保存结果,看的论文并不多,只看了要实现的三种模型的相关论文,没有跟进前沿技术,没有看许多近几年的提出的特别新颖的论文。不过一步一个脚印吧,要先学会爬才能站起来走不是吗哈哈
这里附几个IEEE比较新的文章吧
基于CNN的多层空间光谱特征融合和具有局部和非局部约束的样本增强,用于高光谱图像分类
深金字塔形残差网络用于光谱-空间高光谱图像分类。
感觉研究生不会想做这个方向了。。可能会去尝试做视频检测一类的?深度学习。。感觉入门门槛好低呀?orz。。 - 只要结果都得到了,写论文就快了。最初的时候已经构建好自己的论文框架了,有了结果后,就可以开始分析了。
总结
-
缺点:
-
整个过程下来,注重的是实践,能出结果,实现出来,而忽视了论文的阅读量,因此,在实现了各种维度的卷积模型的分类任务之后,完成草稿的定稿之后,发现论文看起来好像很肤浅的样子,倒像是一篇方法的综述orz。。没有做出更深入的挖掘,原因就是在学习过程中,重实践而轻了理论的学习。不过项目过程也确实是在实际的造东西。还是很充实的,而且也确实是按照设想的内容实现出来了绝大部分。
-
总结就是:因为研究的深度不够,导致内容整体看下来很肤浅,体现的工作量很小,给人的感觉不过是调用了API,修改了一下参数,跑了遍数据集而已,没有任何的新颖的添加。————实验结果的结论写的太肤浅,不够深入,没有读很多文献。不过最基本的三篇1D PCA-2D 3D都读了,还有又读了遍西电的,她做的确实是比较严谨的,对于参数的选择都通过了交叉验证的实验进行了判断。
-
还有许多需要深挖优化的地方,比如对于数据集的预处理,在实验中并没有什么操作和注意。(1)数据集太小的话,如果数据集切分的不均匀,或者说训练集和测试集的分布不均匀,如果模型能够正确捕捉到数据内部的分布模式话,这可能造成训练集的内部方差大于验证集,会造成训练集的误差更大。这时你要重新切分数据集或者扩充数据集,使其分布一样。(2)由Dropout造成,它能基本上确保您的测试准确性最好,优于您的训练准确性。Dropout迫使你的神经网络成为一个非常大的弱分类器集合,这就意味着,一个单独的分类器没有太高的分类准确性,只有当你把他们串在一起的时候他们才会变得更强大。因为在训练期间,Dropout将这些分类器的随机集合切掉,因此,训练准确率将受到影响。在测试期间,Dropout将自动关闭,并允许使用神经网络中的所有弱分类器,因此,测试精度提高。
-
-
优点:
- 对于整个过程而言,极大锻炼了自主学习和解决问题能力,快速找到切入点,上手一个项目。有迹可循的完成一项任务,循序渐进。遇到问题可以多方解决,无论是找博主求教,还是自己搜各种帖子博客,还是自己想办法debug试验,或是看视频学习,能较好的解决绝大部分问题。养成了所有学习过程都记笔记的好习惯,细分类各文件夹,这个习惯还要感谢 稚辉君。
- 不光我的模型有了迁移学习,我本人也有了迁移学习能力哈哈,学前面的基础视频课程的时候,接触到的内容都在后面起到了作用。
- 通过前面课程学习的迁移学习,自己想到了用大样本的PU数据集预训练网络模型,迁移学习到IP数据集上。
- 考虑到了3D模型的自身的参数通过交叉验证实验筛选出效果更好的数
展望
- 半监督 计划研究潜在的更有效的基于3D-CNN的HSI分类技术,可以利用未标记的样本。在HSI中,未标记的样本比已标记的样本更容易获取。基于3D-CNN的监督分类方法未能充分利用这种未标记的样本。基于3D-CNN的无监督和半监督分类方法的集成有望更好地解决这个问题。
- 另一 方面, 考虑将生成式对抗网络 (Generative adversarial network, GAN) 引入到高光谱图像分类 中来. 对每个类别都建立一个生成式对抗网络, 利用 该网络生成符合该类别特点的新的样本数据, 以此增加该类别的标注数据的数据量, 建立具有大量标注数据的数据集, 最后利用该数据集对深度学习网络模型进行训练。
- 无论采用哪种深度网络模型, 主要依靠多次对比实 验分析选择合适的参数. 如何根据高光谱图像本身 的空间分辨率, 光谱分辨率及采集场景等信息, 指导 空间邻域大小的选取, 网络规模的设计等是值得关 注的一个问题.(我的最后一个实验组就是这个意思)
- 从分类结果上来说, 高光谱图像分类与自然 图像处理问题中的语义分割非常类似. 但是数据特点等有所不同, 深度学习中有大量的效果非常显著 的语义分割的方法, 目前暂时还没有发现 有基于深度学习的语义分割的方法应用在高光谱图 像分类上的文章, 在后续的工作中, 这是一个非常值 得考虑的方向.
- 本文用的3DCNN模型结构非常简单,没有用到残差网络,因为是小样本学习不建议用太深的网络模型,但不知道加入残差网络能否减轻这种问题。。让模型结构更深层一些,提取的特征更深一些会不会效果更好,
参考文献:
张号逵, 李映, 姜晔楠. 深度学习在高光谱图像分类领域的研究现状与展望. 自动化学报, 2018, 44(6): 961−977
XMind - Trial Version