本博文適用於初學者,利用深度學習來進行圖像識別的應用數組
對於廣大老司機們來講確定是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')