zoukankan      html  css  js  c++  java
  • 浙大人工智能算法与系统课程作业指南系列(一)终:口罩识别作业的收尾填坑

    浙大人工智能算法与系统课程作业指南系列(一)终:口罩识别作业的收尾填坑

    emmmmm,写的第二篇被从博客园首页撤了,第三篇估计也会被撤掉吧······心情有点复杂,也不知道大家还能不能在搜索引擎搜到。嘛,不管能不能搜到,该写的东西还是要写,总之先把坑填完吧。好了小伙伴们坐好,我们继续讲辣(≧ω≦)

    整个作业从数据处理、模型训练以及模型的大致结构都为大家简单地讲了一下,可能就有小伙伴会问了,这个作业里还能有什么坑啊 ̄ω ̄,事实上,这里坑还真的不少······我们一点点来看一看吧。

    在把前面几个部分看过之后,大家应该大致上能生成一个main.py文件然后按照要求提交到平台的GPU上面,训练完以后在网站上测试过了。但是我相信很多小伙伴应该就只有85-92分的样子,可能运气好能拿到94,但是测试结果应该就提不上去了。而这个评分表现太差,主要就是下面我要介绍的作业里面的一些坑导致的。

    首先是数据集部分。没错,你们没看错,这个作业训练用的数据集里就有错误······我相信大家在训练之前基本没有几个认真看过数据集的,毕竟谁能想到,这个作业会在这里挖坑。虽然我在写这篇文章的时候作业提交平台已经关闭了,但是数据集还是可以下载的,而且我看见里面的错误图片,还是没有改······

    如果大家准备做这个作业的话,打开你们的数据集,在里面找到mask文件夹下的mask96和mask98,如果数据集还是没有更新过的话,这两张图片应该是下面的鬼样子:

    这是标签为mask的图片,mask96,你瞅瞅这哪里有口罩,你信不信我当场把我自己的嘴P上去给她当口罩。而且这个还不是最过分的,最过分的是下面的那张mask98:

    来来来平台老师你给解释一下,之前的mask96虽然标签不对,但起码脸还是有的啊,你瞅瞅这个,人呢?我那么大的一个漂亮老婆呢?(误)。

    然后图片里面还有好几张长得一模一样的图片,然后还有他处理过的根本就不像是人脸的东西,总之数据集里面的数据乱七八糟的,唯一的安慰就是,它确实是我们想要求的160x160的三通道图片······杂七杂八删删减减,最后大概数据集里面mask有280张左右,nomask里面有410张左右,总共不到700个人脸,你叫我训练个模型?而且正类负类的比例差的也稍微有一点点多,真的是搞人心态,╭(╯^╰)╮

    数据集好少,基本上如果你想拿到个还算过得去的成绩的话,大概就只能用预训练模型了······当然事实上如果非要用他示例代码的模型,也是能拿到95以上的,只不过后面还是有坑要排罢了┓( ´∀` )┏

    接下来我们再来看一下代码里面的数据处理部分:

    transforms = T.Compose([
        T.Resize((height, width)),
        T.RandomHorizontalFlip(0.1),  # 进行随机水平翻转
        T.RandomVerticalFlip(0.1),  # 进行随机竖直翻转
        T.ToTensor(),  # 转化为张量
        T.Normalize([0], [1]),  # 标准化
    ])
    

    我们先不管那个鸡肋的随机翻转,也不要管那个张量转换,我们来看一下标准化部分。在第一篇文章中我提到过,这个部分是为了把数据的尺度调整到差不多的程度,这样的话我们的模型训练才会比较稳定。但是······他把均值设置成0,标准差设置成1,那不就是没变嘛。真的当时看到这里我想哭的心都有了。实际上,如果我们真的要做的话有两种思路,一种是我们就真的算一下数据集里面所有图片的各个channel的像素均值和标准差,其实也很好求,就把图片全都读到一个矩阵里面,然后对每个channel求均值就行了,哪怕不用tensor,用numpy也可以啊,总之要自己求一下;第二种思路是,如果你实在是不想求了,那干脆就直接人为给一些数:我们知道像素值都在[0, 1]之间,而且一般来说只要不是特别过分的图片,像素值一般都排布得比较均匀,所以我们干脆直接设置均值为0.5,标准差为0.25,总之稍微处理一下,会让你的图片像素值分布更加均匀,识别效果也会好很多。

    数据处理部分的坑也就差不多这些,接下来我们看一看神经网络这边的坑。

    在神经网络部分,平台的示例代码给的是一个阉割过后的MobileNetV1,可能目的就只是让你熟悉一下神经网络的编写。其实完全没必要用他这个结构,事实上你自己随随便便弄一个两三层的卷积层,然后接两个线性层,线性层之间找个适合于分类问题的激活函数(Tanh或者Sigmoid),效果都会好上不少。但是如果你这么做,你会发现一个问题:模型可能过拟合了。平台上只给出了不到700个数据,然后要求你做一个神经网络出来识别口罩,这个数据量一般来说只会有两个结果:要么不让他过拟合,少训练几代结果欠拟合了;要么直接一头撞死在过拟合的大墙上。那我们肯定是想先看看过拟合,然后再解决过拟合呗,如果需要这样做的话,我们需要重新审视一下优化器的函数:

    optimizer = optim.Adam(model.parameters(), lr = 1.0e-3)
    

    Pytorch就十分贴心,为了不让你自行编写新的含有正则项的损失函数来降低过拟合的风险,它在优化器的里面设置了一个参数叫做weight_decay,这个参数相当于为你在损失函数中增加了一个L2的正则化来减小过拟合风险,L2正则化的相关资料请参照百度或者其他博客。当我们加上正则化之后,我们的优化器应该长这个样子:

    optimizer = optim.Adam(model.parameters(), lr = 1.0e-3, weight_decay = 1.0e-8) #这个值在这里我是随便写的,你们到时候自己调哈
    

    这样在识别口罩的网络上,小伙伴们可能会踩到的坑就基本填完了,然而事情并没有我们想象的这么简单,事实上在识别人脸,将人脸送到识别口罩的这部分代码也出现了问题。

    这个作业的实际网络流程大概是这样的:
    输入一个随便大小的图片 --> 通过MTCNN网络标识出人脸 --> 把识别出的人脸发送给MobileNetV1 --> MobileNetV1识别是否有口罩 -->返回图片中有几个人脸,几个人脸戴着口罩

    从上面的步骤里你有没有看出什么问题?这个坑十分隐晦,如果不仔细看他提供的所有的代码的话,这个问题根本意识不到。emmmmm好吧我摊牌了,他在从第二步到第三步的过程中,并没有把识别出来的人脸的尺寸重新调整。

    事实上,我们在训练MobileNetV1的模型的时候,我们所有的数据集图片尺寸都是160x160的,但是MTCNN抠出来的人脸,出来的尺寸大小不一,就是他在图上框出来多大的人脸,就往MobileNet里面送多大的人脸。所以你会发现,当你用下面的测试函数的时候,test.jpg,就是那个中间有个地中海大脑袋(误)的那个图片,识别结果总是很好;而test1.jpg,就是那个图片里面五个人拉了个远景视角的那个图,口罩识别效果总是特别差。因为test.jpg的图片,即使不调整人脸尺寸,他抠出来的就差不多是160x160的,然而下一张图抠出来的人脸大概就只有几十x几十的像素,这咋搞嘛。

    总结一下,如果想拿稍微好一些的成绩,下面几个事情需要处理一下:

    1. 把数据集里面不正确的图片全都删了,由于notebook里面的datasets文件夹是只读的,所以如果在notebook上训练,就只能换一个新的文件夹,然后把data_path改了,记得在第一篇里讲的ImageFolder的注意事项哟
    2. 将图片处理里面的标准化的方法改一下,一般会有还可以的效果的
    3. 在优化器上添加正则化系数,防止模型训练的过拟合
    4. 修改模型,稍微增加一点复杂度,或者干脆就自己写一个,反正基本方法我已经教了┓( ´∀` )┏
    5. 在人脸识别的模块中,把抠出来的人脸尺寸重置为160x160

    好了,啰啰嗦嗦这么多篇,终于算是把口罩识别的作业的坑排的差不多了,相信通过这几篇指南,大家对于Pytorch的一些基本概念以及操作方法已经有了一个初步的了解,并且也初步学会了怎么查官方的文档,那么我们下一个作业 “作者文风识别” 见吧,拜拜咯~

  • 相关阅读:
    Spark的安装与配置
    mysql的安装过程
    开发笔记-记一个基础logback配置
    开发笔记—钉钉服务商应用isv开发,从应用配置,到获取客户企业通讯录
    钉钉内网穿透工具在windows的使用。
    gradle-技能保存
    linux常用
    提供一种业务系统非核心信息不连表查询解决方案
    调试相关技能
    衡量项目性能的几个指标及其解释
  • 原文地址:https://www.cnblogs.com/JacobDale-TechLearning/p/14140294.html
Copyright © 2011-2022 走看看