本博文适用于初学者,利用深度学习来进行图像识别的应用数组
对于广大老司机们来讲确定是so easy啦网络
首先准备大量样本,样本?从哪找,这个我相信老司机本绝对比我在行,嘻嘻app
这个我碰到过一个坑,初学者们准备样本时,正常照片和非正常照片(非正常照片?咱们不是鉴黄吗?嗯嗯),原本博主准备几w张图片一块儿训练可是发现太麻烦了,图片中有不少脏数据,剔除脏数据就花了我很长的时间,太辣(sex)眼(feeling)了函数
好啦很少说了,看代码学习
这里我准备了2000张非正常图片,和2000张正常图片(原本抓取了2w张,结果训练时直接过拟合了,删到2000张时稳定了下来)优化
我这里使用的是keras ,有人问我为何不用tensorflow,keras后段能够选择tensorflow和theano,这里我使用的是tensorflow,keras的一个好处就是搭建神经网络简单快捷,相比tensorflow要节俭不少行代码,对于初学者来讲很方便编码
样本不够,不要紧咱们能够根据已有的图片来生成一些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
这里咱们使用的图片大小是(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调小一点一次传入少许的图片就能够啦
简单来讲咱们把数据格式为(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通常用于二分类问题
这里咱们建立一个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%的识别率,这里你们能够在进行一些优化或者增长训练的次数
博主你出来第三个是什么~
放出全部的代码
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')