利用神經網絡來鑒黃


本博文適用於初學者,利用深度學習來進行圖像識別的應用

對於廣大老司機們來說肯定是so easy啦

ON.1

首先准備大量樣本,樣本?從哪找,這個我相信老司機本絕對比我在行,嘻嘻

這個我碰到過一個坑,初學者們准備樣本時,正常照片和非正常照片(非正常照片?我們不是鑒黃嗎?嗯嗯),本來博主准備幾w張圖片一起訓練但是發現太麻煩了,圖片中有很多臟數據,剔除臟數據就花了我很長的時間,太辣(sex)眼(feeling)了

好啦不多說了,看代碼

這里我准備了2000張非正常圖片,和2000張正常圖片(本來抓取了2w張,結果訓練時直接過擬合了,刪到2000張時穩定了下來)

我這里使用的是keras ,有人問我為什么不用tensorflow,keras后段可以選擇tensorflow和theano,這里我使用的是tensorflow,keras的一個好處就是搭建神經網絡簡單快捷,相比tensorflow要節儉很多行代碼,對於初學者來說很方便

ON.2

樣本不夠,沒關系我們可以根據已有的圖片來生成一些

在這里我們使用keras的ImageDataGenerator,這是一個圖片生成器,可以根據已有的圖片來生成一些新的圖片

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我們使用了很多參數,它們都是什么意思呢

  •  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')

 

凈化網絡環境,自覺拒絕誘惑,擁抱美麗青春,^_^


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM