通过 resnet 实现对色情图片&性感图片的识别(代码/调优/数据)

Posted 我爱大猫咪

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过 resnet 实现对色情图片&性感图片的识别(代码/调优/数据)相关的知识,希望对你有一定的参考价值。

零:代码

https://github.com/yangbisheng2009/nsfw-resnet (绝对良心代码,欢迎 star)

一、背景

线上海量图片,需要将其中性感图片、色情图片识别出来

比如:

性感
普通图片

二、调研

在经过一些列调研之后,确定了以下几种方案:

  1. 机器学习方法,利用p_hash或者图片hog特征或者傅里叶变化、小波变换抽取图片向量特征,采用传统机器学习的方法直接有监督分类
  2. 直接采用卷积神经网络方法,如 resnet、inception 等方法做有监督分类。或者对于我这种初学者来讲,不用深层卷积神经网络,直接采用 卷积层 + 池化 + 全连接 的基础神经网络结构。

列举了上述两种方法,经过调研大牛们的实现,决定不走弯路,直接上inception、resnet方法。并且最终确定了resnet101 + pytorch的组合(当然了,其它的实现,也有亲自试验,后面会讲到)

三、resnet原理

resnet就是一个做了一些小技巧的多层卷积神经网络,如果对基本的  卷积层-池化层-全连接层  结构不太了解,建议你可以先学习一下基础。我这里会对resnet原理一笔带过,因为网络上也有大批文章做介绍。

前提:深层网络对图片的分类效果好(实践证明,业界公认,尚无理论支撑)

问题:深层网络无法避免的梯度消失问题,导致深层神经网络模型可能效果还不如浅层效果

现在问题梳理清楚了,也就是只要我们能够解决梯度消失问题,那么就可以畅快的使用深层神经网络了。解决这个问题,就用到了残差。

假设现有一个比较浅的网络(Shallow Net)已达到了饱和的准确率,这时在它后面再加上几个恒等映射层(Identity mapping,也即y=x,输出等于输入),这样就增加了网络的深度,并且起码误差不会增加,也即更深的网络不应该带来训练集上误差的上升。通过“shortcut connections(捷径连接)”的方式,直接把输入x传到输出作为初始结果,输出结果为H(x)=F(x)+x,当F(x)=0时,那么H(x)=x,也就是上面所提到的恒等映射。于是,ResNet相当于将学习目标改变了,不再是学习一个完整的输出,而是目标值H(X)和x的差值,也就是所谓的残差F(x) = H(x)-x,因此,后面的训练目标就是要将残差结果逼近于0,使到随着网络加深,准确率不下降。

也就是说,即使我并不知道多少层是最佳,我通过残差模块,即使已经错过最佳深度我至少模型的精度不会有影响。起初看到这种网络模型很是奇怪,如果是一个浅层网络就能达到饱和,那么后面的残差结构目标是学习一个恒等映射,那么学习目标为F(x)接近为0。既然这样,为什么要去学习这个映射?直接写个恒等函数,或者直接设置F(x)=0 输出为x不就行了?残差网络的目的是学到y=x恒等映射函数,那么不就相当于加上的残差网络在最后没起到作用吗?那么为什么会有效呢?
首先这个饱和的浅层网络本身就不好寻找,有可能在达到饱和浅层网络深度之前,由于误差的原因模型精度已经下降。那么为什么持续增加层,让模型学习一个恒等映射就会使得模型表达变好呢?
假设:如果不使用残差网络结构,这一层的输出F'(5)=5.1 期望输出 H(5)=5 ,如果想要学习H函数,使得F'(5)=H(5)=5,这个变化率较低,学习起来是比较困难的。但是如果设计为H(5)=F(5)+5=5.1,进行一种拆分,使得F(5)=0.1,那么学习目标是不是变为F(5)=0,一个映射函数学习使得它输出由0.1变为0,这个是比较简单的。也就是说引入残差后的映射对输出变化更敏感了。
进一步理解:如果F'(5)=5.1 ,现在继续训练模型,使得映射函数F'(5)=5。(5.1-5)/5.1=2%,也许你脑中已经闪现把学习率从0.01设置为0.0000001。浅层还好用,深层的话可能就不太好使了。如果设计为残差结构呢?5.1变化为5,也就是F(5)=0.1变化为F(5)=0.这个变化率增加了100%。引入残差后映射对输出变化变的更加敏感了,这也就是为什么ResNet虽然层数很多但是收敛速度也不会低的原因。明显后者输出变化对权重的调整作用更大,所以效果更好。残差的思想都是去掉相同的主体部分,从而突出微小的变化,看到残差网络我第一反应就是差分放大器。这也就是当网络模型我们已经设计到一定的深度,出现了精准度下降,如果使用残差结构就会很容易的调节到一个更好的效果,即使你不知道此刻的深度是不是最佳,但是起码准确度不会下降。代码实现也比较简单,原本的输出结果由F(x)替换为输出F(x)+X,如果维度相同则直接相加,如果维度不同则利用1*1的卷积核变换。当然残差网络还有很多细节, 比如使用预batch normalize ,ResNet-v1 由relu非线性变换,替换为ResNet-v2恒等变换。

四、具体实现

这是我的代码库,里面有完整的代码实现:https://github.com/yangbisheng2009/nsfw-resnet

强烈建议大家使用pytorch来做图像相关的处理呦,性能高、灵活。

我采用加载预训练好的resnet101模型,通过样本数据,做全局finetune(后续你们也可以尝试局部finetune,只把微调深层网络参数)。

数据来源:

好心人提供的开源数据,给个赞:https://github.com/alexkimxyz/nsfw_data_scraper

数据标签:

  • porn - 色情
  • hentai - 动漫色情、图画
  • sexy - 性感
  • neutral - 普通
  • drawings - 普通动漫、图画

一些能够提升准召的tips:

  • 尽可能调大batch_size,我在我的P40机器上,设置了512
  • 我最终选用了resnet101 pretrained model,它在诸多的方案中,表现最好
  • 在整体finetune后,可以lock模型前面的N层,重新finetune一次。为什么这么做能带来更好的效果,我想你们都懂的
  • 根据你的数据集、模型选择等因素,动态调整你的learning rate
  • 我采用了很多数据增强的方法,如颜色变换、高斯噪声点、旋转、平移、剪切、色调对比度变换。但是结果发现这些方法,并没有太大的卵用(针对这个工程而言),最终只保留一小部分

效果:

五、和其它模型的对比

我尝试了resnet101、resnet50、inceptionv3、手写单层cnn 等三种方法。

resnet101效果最好,但是稍微比resnet50慢一点。但是可以接受

手写单层cnn稍后会把代码放出来,非常有助于大家对图片分类的理解

 

欢迎留言提问 或者 邮箱联系我: yangbisheng2009@gmail.com

以上是关于通过 resnet 实现对色情图片&性感图片的识别(代码/调优/数据)的主要内容,如果未能解决你的问题,请参考以下文章

浙大&川大提出脉冲版ResNet:继承ResNet优势,实现当前最佳

AI 这么优秀,连我鉴黄师的饭碗都抢了

PyTorch ResNet 实现图片分类

Python爬虫实战-性感gif图数据采集

HTML+CSS+JS实现 ❤️鼠标悬停性感美女图片特效❤️

PyTorch 深度学习实战 | 基于 ResNet 的花卉图片分类