利用神经网络来鉴黄

本博文适用于初学者,利用深度学习来进行图像识别的应用数组

对于广大老司机们来讲确定是so easy啦网络

ON.1

首先准备大量样本,样本?从哪找,这个我相信老司机本绝对比我在行,嘻嘻app

这个我碰到过一个坑,初学者们准备样本时,正常照片和非正常照片(非正常照片?咱们不是鉴黄吗?嗯嗯),原本博主准备几w张图片一块儿训练可是发现太麻烦了,图片中有不少脏数据,剔除脏数据就花了我很长的时间,太辣(sex)眼(feeling)了函数

好啦很少说了,看代码学习

这里我准备了2000张非正常图片,和2000张正常图片(原本抓取了2w张,结果训练时直接过拟合了,删到2000张时稳定了下来)优化

我这里使用的是keras ,有人问我为何不用tensorflow,keras后段能够选择tensorflow和theano,这里我使用的是tensorflow,keras的一个好处就是搭建神经网络简单快捷,相比tensorflow要节俭不少行代码,对于初学者来讲很方便编码

ON.2

样本不够,不要紧咱们能够根据已有的图片来生成一些spa

在这里咱们使用keras的ImageDataGenerator,这是一个图片生成器,能够根据已有的图片来生成一些新的图片code

datagen = ImageDataGenerator(rescale=1./255,horizontal_flip=True,vertical_flip=True,shear_range=.2,width_shift_range=.2,height_shift_range=.2,data_format='channels_last')

ImageDataGenerator咱们使用了不少参数,它们都是什么意思呢orm

  •  data_format:分为channel_first和channel_last,这里咱们可不要选错了,channel_first是theano所使用的格式,channel_last是tensorflow所使用的格式,以128x128的RGB图像为例,“channel_first”应将数据组织为(3,128,128),而“channel_last”应将数据组织为(128,128,3)
  •  rescale:重放缩因子,默认为None,若是为None或0则不进行放缩
  •  horizontal_flip:布尔值,进行随机水平翻
  •    vertical_flip:布尔值,进行随机竖直翻转
  •    shear_range:浮点数,剪切强度(逆时针方向的剪切变换角度)
  •    width_shift_range:浮点数,图片宽度的某个比例,数据提高时图片水平偏移的幅度
  •    height_shift_range:浮点数,图片高度的某个比例,数据提高时图片竖直偏移的幅度

这里咱们使用的图片大小是(150,150)

img_width, img_height = 150, 150

train_data_dir = 'py/Scrapy/classifier/img/abnormal'
validation_data_dir = 'py/Scrapy/classifier/img/test'

datagen = ImageDataGenerator(rescale=1./255,horizontal_flip=True,vertical_flip=True,shear_range=.2,width_shift_range=.2,height_shift_range=.2,data_format='channels_last')

train_generator = datagen.flow_from_directory(
        train_data_dir,
        target_size=(img_width, img_height),
        batch_size=32,
        class_mode='binary')

validation_generator = datagen.flow_from_directory(
        validation_data_dir,
        target_size=(img_width, img_height),
        batch_size=32,
        class_mode='binary')

batch_size是batch数据的大小,这里咱们是32,即一次传入多上张图片

class_mode:"categorical", "binary", "sparse"或None之一. 默认为"categorical. 该参数决定了返回的标签数组的形式, "categorical"会返回2D的one-hot编码标签,"binary"返回1D的二值标签."sparse"返回1D的整数标签,若是为None则不返回任何标签, 生成器将仅仅生成batch数据

由于咱们是一个二分类的问题,因此咱们选择binary

如今咱们的样本问题解决了,开始搭建咱们的神经网络模型吧

 

有些人担忧本身的设备内存会爆掉,不用担忧ImageDataGenerator实际上是Python的迭代器,把咱们的batch_size调小一点一次传入少许的图片就能够啦

 

NO.3

简单来讲咱们把数据格式为(150,150,3)的数据传入到神经网络中,(150,150,3)这个是什么意思,这个是(img_width,img_height,图片通道),彩色图片通道是3,灰色图片的为1

model=Sequential()
model.add(Conv2D(32,3,3,input_shape=(img_width,img_height,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(32,3,3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(64,3,3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))

Activation('relu')即激活层,这里咱们添加一个relu的激活函数

MaxPooling2D是池化层,池化层每每跟在卷积层后面,池化层把以前卷基层获得的特征图作一个聚合统计,100*100的大小选择一个2*2的区域作不重叠的最大池化,池化层回输出50*50的那么大的图来达到下降数据量的目的,这里咱们是150*150,通过最大池化后池化层输出75*75

通过三层卷积层,池化操做后通过Flateen()

Flateen():把多位的输入变成一维的,一般在卷积层到全lian jie ceng全链接层的过分,Flatten不影响batch的大小

Dense:全链接层

Dropout:在训练过程当中每次更新参数时按必定几率(rate)随机断开输入神经元,Dropout层用于防止过拟合

直接咱们的输出层大小为1,即咱们只输出一个数据Dense(1),输出层的激活函数为sigmoid,sigmoid通常用于二分类问题

 

NO.4

这里咱们建立一个Callback用于记录咱们的loss值

from keras.callbacks import Callback
class LossHistory(Callback):
    def on_train_begin(self, logs={}):
        self.losses = []

    def on_batch_end(self, batch, logs={}):
        self.losses.append(logs.get('loss'))

下面进入正题开始训练

history_loss=LossHistory()
model.compile(loss='binary_crossentropy',optimizer='rmsprop',metrics=['accuracy'])
nb_epoch=10
nb_train_smaple=4668
nb_validation_samples=392
model.fit_generator(train_generator,samples_per_epoch=nb_train_smaple,nb_epoch=nb_epoch,validation_data=validation_generator,nb_val_samples=nb_validation_samples,callbacks=[history_loss])

由于咱们是个二分类问题因此损失函数咱们选择binary_crossentropy

激活函数这里咱们再也不讲解你们能够自行百度,这里使用rmsprop或者adam,使用adam则相对好一些

nb_epoch是训练的次数这里作个演示咱们仅仅训练10轮

validation_data要填写咱们咱们验证的生成器函数

samples_per_epoch即每个epoch样本数达到多少时记一个epoch结束

通过训练后

 

达到了92%的识别率,这里你们能够在进行一些优化或者增长训练的次数

 博主你出来第三个是什么~

 

NO.4

放出全部的代码

from keras.preprocessing.image import ImageDataGenerator,array_to_img,img_to_array,load_img
from keras.models import Sequential
from keras.layers import Dense,Flatten,Conv2D,MaxPooling2D,Dropout,Activation


img_width, img_height = 150, 150

train_data_dir = 'py/Scrapy/classifier/img/abnormal'
validation_data_dir = 'py/Scrapy/classifier/img/test'

datagen = ImageDataGenerator(rescale=1./255)




train_generator = datagen.flow_from_directory(
        train_data_dir,
        target_size=(img_width, img_height),
        batch_size=32,
        class_mode='binary')

validation_generator = datagen.flow_from_directory(
        validation_data_dir,
        target_size=(img_width, img_height),
        batch_size=32,
        class_mode='binary')

model=Sequential()
model.add(Conv2D(32,3,3,input_shape=(img_width,img_height,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(32,3,3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(64,3,3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
nb_epoch=10
nb_train_smaple=4668
nb_validation_samples=392
model.fit_generator(train_generator,samples_per_epoch=nb_train_smaple,nb_epoch=nb_epoch,validation_data=validation_generator,nb_val_samples=nb_validation_samples)
model.save_weights('./abnormal.h5')

from keras.utils import plot_model
plot_model(model,to_file='./model.png')

 

净化网络环境,自觉拒绝诱惑,拥抱美丽青春,^_^

相关文章
相关标签/搜索