第一次机器学习的作业完成了,按照先前做实作的习惯来写一下总结和思考。
作业要求:对COIL20
,Yale_32x32
,data_batch_1(Cifar)
三个数据集,分别运用KMeans对其中的图片进行自动聚类。其中Cifar
为(r,g,b)
彩图,其余为灰度图数据集已给出了正确标签以作为评估验证。
此外,作业要求组成来自不同学院的3-4人的小队,以提交实验报告的方式考评。
组内队员:yxy,cjx,wzh,zsy(笔者)
开题:看到KMeans其实并不陌生,知道是务监督的聚类方法,实现过对二维坐标(x,y)
的聚类,老实讲,效果还是很不错的。但是这次一看到是图片,特别是有彩图我就猜到KMeans聚类出来,可能会雪崩,结果也是验证了我的猜想。
实作过程:KMeans的码量小,思路简单,可是说就是个暴力算法,在考虑到效果可能不优的情况下,和同班同学zxg同学进行了讨论,一致同意先做特征提取,然后去跑KMeans,这也是被这次作业卡到怀疑人生的开始,确切地说,是被特征提取效果卡到心态失衡的一次作业。
实作的心路历程:特征提取,并不陌生,但是没有实作过,zxg同学采用了ae(auto-encoder)进行特征提取,不得不说,zxg同学的选择应该是正确的,因为最后效果zxg同学的ae较为出色地完成了特征的提取,评估结果不优的原因极可能是因为层数过低,毕竟pc很难跑到比较可观的层数(zxg同学向我吐槽12层就死机了,hhh),而我的提取惨不忍睹。为什么当初我没有选择ae?第一、ae我仅在视频中听过其作用,确切地说,是在讲到vae的时候,ae被提及了,我才知道有个这个东西。第二、虽然ae本质也是nn,实现过2层nn的笔者感觉应该是可以掌握的,但是作为刚刚结束了opencv简单操作学习的,对于opencv功能之强大,操作之绚丽,结果之夺目的忠实opencv粉丝。我毫不犹豫地选择了用opencv中的SIFT作为我的特征提取算法,期许能像在之前学习一样,让我眼前一亮。因为sift做了高斯模糊,又弄了图像金字塔,这些在数字图象处理书中高大上的方法,都看到了,个人觉得效果一定不会差。
而至于为什么会选择SIFT,其实原因很简单,SIFT是基于尺度不变的,就是说对于一些简单的数据增强(旋转,平移,缩放)都表现出了良好的结果。而在分类之前我有可视化过COIL20的前100张图,发现确实有旋转的增强数据,而有几张图看起来并无二致,推测是subsample之后再进行还原,所以肉眼看不出来有何区别。所以坚持了SIFT做特征提取,开始踩坑之路。
踩坑:
1、是创建sift,我跟随了很多博客的cv2.SIFT()
,发现不行才知道cv更新之后需要使用cv2.xfeatures2d.SIFT_create()
的创建方法。
2、对于features的数量是可以限定的,一开始没有限定,跑出了300w的特征,至今不知道为什么会这么大。
3、sift提取的特征可能为nan,之前因为这个问题考虑过很久,为什么一个特征提取算法会对一幅图片,竟然提取不出特征?发现网上的代码也都有判断,不知道是什么机制。
4、sift提取的特征不一定shape相同,所以如果算两幅图的特征距离,需要弄成等大(np.r_[]
,np.c_[]
)。
5、学一门语言,一定要懂怎么处理异常,至少得会用,可以避免很多输出debug。
6、学东西怎么用,一定要多看,想理解背后机理,则需要多深入挖掘,我一定要搞懂sift!
总结:首先,之前对于opencv的学习可以说比较顺利,没有踩到这么多的坑,每个坑我都切切实实地踏进去,踏地非常深,一度自闭。就感觉别人用的好好的api,自己踩了很多坑才能正常运转,更不要说跑出所描述的样子,就感觉很没有成就感,没有coding的感觉。其次,认识到了opencv的一些不足,不知道个人这样理解对不对,opencv更侧重于用图像图形的方法来处理图像,就拿灰度变换来说。直方图均衡,或者自适应均衡,或是用函数映射,更加侧重得是图像的本质。意思是说在图像本来的基础上,根据周围的来尽可能地还原图像,而一些深度学习方法,个人认为更像是重新在位置上创造,基于大量样本的学习,来表现出一种更加优秀的还原。不得不说,虽然很热衷于opencv,以及一些图像处理的非机器学习的方法,但是目前的机器学习算法确实效果拔群。热衷的原因在于,个人感觉这些数字图像处理的变换或是技巧是根本,学习了图像、视觉的机理,了解一些处理的发展历史,十分有趣之余,才可以更好地学习之后基于机器学习的方法,而不仅仅停留在调用的层次。