情人節(jié)選花神器—深度學(xué)習(xí)指南

大鵬說 :本文約1200字,閱讀需要4分鐘秤标。本文講述了利用深度學(xué)習(xí)原理實(shí)現(xiàn)自動識別花卉品種的過程银伟。成果優(yōu)秀,令人驚奇并徘,絕對是情人節(jié)選花神助手~

關(guān)鍵詞:阿里云 Python 郵件 星座

p.s.文末有源代碼分享

轉(zhuǎn)眼,一年一度的情人節(jié)又到了扰魂。每個(gè)情人節(jié)我總要面臨一個(gè)問題:如何給我的女盆友們買花麦乞?花店里琳瑯滿目的花蕴茴,我又不認(rèn)識,萬一買錯(cuò)品種了姐直,我將會永遠(yuǎn)失去她們倦淀。我決定搞一個(gè)模型來幫我完成花的識別工作。

1. 學(xué)習(xí)素材準(zhǔn)備

為了掌握花卉的鑒別能力声畏,我特地找了海量的花卉圖片以供賞析撞叽。

一共14個(gè)品種的花:


image

每個(gè)品種共1000張艷照,共計(jì)14000張:


image

如何讓機(jī)器能夠準(zhǔn)確識別這些花的品種插龄,很簡單愿棋,一遍一遍反復(fù)的學(xué)習(xí),直到能認(rèn)準(zhǔn)為止——“一遍一遍反復(fù)學(xué)習(xí)”這一行為均牢,我們稱之為深度學(xué)習(xí)糠雨。

學(xué)習(xí)要講究方法,比如如何區(qū)分玫瑰和菊花徘跪,很簡單甘邀,玫瑰一般為紅色,花朵是卷起來的,而菊花是黃燦燦的垮庐,花朵的形狀…大家都懂的松邪。這種提取特征的學(xué)習(xí)方法,我們通常稱之為卷積哨查。

2. 模型建立

先導(dǎo)入用于深度學(xué)習(xí)的python包逗抑,我們使用Keras框架

from keras.models import Sequential
from keras.layers import Conv2D,MaxPool2D,Activation,Dropout,Flatten,Dense
from keras.optimizers import Adam
from keras.preprocessing.image import ImageDataGenerator,img_to_array,load_img
from keras.models import load_model

因?yàn)镵eras框架本身是基于tensorflow構(gòu)建的,性能卓著解恰,又不需要tensorflow超高難度的代碼編寫锋八,封裝十分徹底,用法與skitlearn類似护盈。

在開始組織神經(jīng)網(wǎng)絡(luò)前挟纱,我們先定義一些參數(shù),方便調(diào)試與修改腐宋。

IMG_W = 224 #定義裁剪的圖片寬度
IMG_H = 224 #定義裁剪的圖片高度
CLASS = 14 #圖片的分類數(shù)
EPOCHS = 5 #迭代周期
BATCH_SIZE = 64 #批次大小
TRAIN_PATH = 'data/train' #訓(xùn)練集存放路徑
TEST_PATH = 'data/test' #測試集存放路徑
SAVE_PATH = 'flower_selector' #模型保存路徑
LEARNING_RATE = 1e-4 #學(xué)習(xí)率
DROPOUT_RATE = 0 #抗擬合紊服,不工作的神經(jīng)網(wǎng)絡(luò)百分比

下面是每個(gè)參數(shù)的解釋:

IMG_W,IMG_H:用于模型學(xué)習(xí)的圖片尺寸。
因?yàn)槲覀兊臉颖緢D片尺寸各不相同胸竞,而模型學(xué)習(xí)需要大小統(tǒng)一的圖片欺嗤,所有這里設(shè)定其寬高。研究表明正方形的圖片在模型擬合方面卫枝,效果優(yōu)于長方形的圖片煎饼,所以這里長寬設(shè)置相同。特別注意校赤,圖片尺寸越大吆玖,訓(xùn)練花費(fèi)時(shí)間越久筒溃,所以千萬不要設(shè)置如1920*1920分辨率大小,否則就算等到天荒地老模型也訓(xùn)練不完沾乘。

CLASS:圖片的分類數(shù)量怜奖,
我們一共有14種花,所以翅阵,設(shè)置為14歪玲。

EPOCHS:訓(xùn)練周期。
模型把所有樣本圖片都訓(xùn)練一次為一周期掷匠,而需要訓(xùn)練成一個(gè)準(zhǔn)確率較高的模型滥崩,一個(gè)周期顯然不行。這里我們可以自由設(shè)置周期大小槐雾,我一般設(shè)置5-40個(gè)周期夭委,循環(huán)結(jié)束保存模型,接著繼續(xù)募强。

BATCH_SIZE:批次大小株灸。
按理說一個(gè)周期里,我們可以把所有圖片一股腦丟給機(jī)器訓(xùn)練擎值,但是我們顯卡的顯存或者CPU的內(nèi)存只有那么大慌烧,放多了容易溢出,也就是常說的爆顯存鸠儿,所以我們要設(shè)置個(gè)批次屹蚊,把圖片一批一批喂給模型訓(xùn)練,我這里設(shè)置為一批64張圖片进每,如果你的顯卡性能略差可以設(shè)置成32或者更小汹粤。

TRAIN_PATH:存放訓(xùn)練集的路徑。

TEST_PATH:存放測試集的路徑田晚。

LEARNING_RATE:學(xué)習(xí)率嘱兼,模型學(xué)習(xí)的速度。
并不是越快越好(數(shù)字越大)贤徒,越快容易造成模型震蕩芹壕,無法收斂,也就是沒有訓(xùn)練效果接奈。1e-4是科學(xué)計(jì)數(shù)法踢涌,為0.0001。這里學(xué)習(xí)率一般設(shè)置有幾個(gè)選擇1e-1,1e-2,1e-3,1e-4序宦。通常探索階段睁壁,設(shè)置的小一點(diǎn)。

DROPOUT_RATE:每次訓(xùn)練不工作的神經(jīng)元百分比。
在模型訓(xùn)練中堡僻,我們通常會遇到一個(gè)問題糠惫,過擬合。也就是說在訓(xùn)練集上準(zhǔn)確率很高钉疫,而測試集上準(zhǔn)確率很低。這里設(shè)置一個(gè)DROPOUT參數(shù)巢价,定義每一次訓(xùn)練牲阁,隨機(jī)一定百分比的部分不參與訓(xùn)練,這樣會起到抵抗過擬合的效果壤躲。

主要是定義訓(xùn)練集和測試集的圖片標(biāo)準(zhǔn)城菊。兩者都有的一個(gè)參數(shù)為rescale,因?yàn)閳D片是RGB色彩碉克,顏色范圍從0-255凌唬,rescale,使數(shù)據(jù)歸一化為0-1的范圍漏麦。但是在訓(xùn)練集中我們還定義了旋轉(zhuǎn)客税,平移,縮放等功能撕贞,這些操作的目的是隨機(jī)變換輸入的圖片樣式更耻,增加樣本量。注意捏膨!這一步操作僅僅只是確定了功能秧均,并沒有對任何圖片進(jìn)行操作,相當(dāng)于先構(gòu)建了一個(gè)模具号涯。

然后目胡,我們開始搭建神經(jīng)網(wǎng)絡(luò):

model = Sequential() #創(chuàng)建一個(gè)神經(jīng)網(wǎng)絡(luò)對象

#添加一個(gè)卷積層,傳入固定寬高三通道的圖片链快,以32種不同的卷積核構(gòu)建32張?zhí)卣鲌D誉己,
# 卷積核大小為3*3,構(gòu)建特征圖比例和原圖相同久又,激活函數(shù)為relu函數(shù)巫延。
model.add(Conv2D(input_shape=(IMG_W,IMG_H,3),filters=32,kernel_size=3,padding='same',activation='relu'))
#再次構(gòu)建一個(gè)卷積層
model.add(Conv2D(filters=32,kernel_size=3,padding='same',activation='relu'))
#構(gòu)建一個(gè)池化層,提取特征地消,池化層的池化窗口為2*2炉峰,步長為2。
model.add(MaxPool2D(pool_size=2,strides=2))
#繼續(xù)構(gòu)建卷積層和池化層脉执,區(qū)別是卷積核數(shù)量為64疼阔。
model.add(Conv2D(filters=64,kernel_size=3,padding='same',activation='relu'))
model.add(Conv2D(filters=64,kernel_size=3,padding='same',activation='relu'))
model.add(MaxPool2D(pool_size=2,strides=2))
#繼續(xù)構(gòu)建卷積層和池化層,區(qū)別是卷積核數(shù)量為128。
model.add(Conv2D(filters=128,kernel_size=3,padding='same',activation='relu'))
model.add(Conv2D(filters=128,kernel_size=3,padding='same',activation='relu'))
model.add(MaxPool2D(pool_size=2, strides=2))

model.add(Flatten()) #數(shù)據(jù)扁平化
model.add(Dense(128,activation='relu')) #構(gòu)建一個(gè)具有128個(gè)神經(jīng)元的全連接層
model.add(Dense(64,activation='relu')) #構(gòu)建一個(gè)具有64個(gè)神經(jīng)元的全連接層
model.add(Dropout(DROPOUT_RATE)) #加入dropout婆廊,防止過擬合迅细。
model.add(Dense(CLASS,activation='softmax')) #輸出層,一共14個(gè)神經(jīng)元淘邻,對應(yīng)14個(gè)分類

先用Sequential()定義一個(gè)模型對象茵典,再往里面添加神經(jīng)網(wǎng)絡(luò)層。模型結(jié)構(gòu)大致為兩個(gè)卷積層宾舅,一個(gè)池化層统阿,共三組,再增加兩個(gè)全連接層筹我,最終輸出為10大類扶平。

我再把網(wǎng)絡(luò)結(jié)構(gòu)進(jìn)行可視化,以便更直觀地觀察模型蔬蕊。

from keras.utils.vis_utils import plot_model
from keras.models import load_model
import matplotlib.pyplot as plt

model = load_model('flower_selector.h5')

plot_model(model,to_file="model.png",show_shapes=True,show_layer_names=True,rankdir='TB')
plt.figure(figsize=(10,10))
img = plt.imread("model.png")
plt.imshow(img)
plt.axis('off')
plt.show()

繪制的結(jié)構(gòu)圖如下:


image

再來講一講如何構(gòu)建合理的網(wǎng)絡(luò)結(jié)構(gòu)结澄。一般為1-2個(gè)卷積層,加1個(gè)池化層岸夯,共2-3組麻献,最后增加1-2個(gè)全連接層輸出,結(jié)構(gòu)沒有定式囱修,但如果樣本太少赎瑰,建議層數(shù)不宜過多,容易過擬合破镰。

設(shè)置好網(wǎng)絡(luò)結(jié)構(gòu)餐曼,我們設(shè)置優(yōu)化器,這里使用adam優(yōu)化器鲜漩,使用梯度下降法優(yōu)化模型源譬,并返回準(zhǔn)確率。

adam = Adam(lr=LEARNING_RATE) #創(chuàng)建Adam優(yōu)化器

model.compile(optimizer=adam,loss='categorical_crossentropy',metrics=['accuracy']) #使用交叉熵代價(jià)函數(shù)孕似,adam優(yōu)化器優(yōu)化模型踩娘,并提取準(zhǔn)確率

lr:學(xué)習(xí)率,數(shù)值為腳本開頭設(shè)置的數(shù)值大小喉祭。

loss:損失函數(shù)养渴,用于衡量模型誤差,模型訓(xùn)練的目的就是讓損失函數(shù)的值盡可能小泛烙,這里我們使用交叉熵代價(jià)函數(shù)理卑。

metrics:返回準(zhǔn)確率。

最后蔽氨,生成訓(xùn)練集和測試集的迭代器藐唠,用于把圖片按一定批次大小傳入模型訓(xùn)練帆疟。

train_generator = train_datagen.flow_from_directory( #設(shè)置訓(xùn)練集迭代器
    TRAIN_PATH, #訓(xùn)練集存放路徑
    target_size=(IMG_W,IMG_H), #訓(xùn)練集圖片尺寸
    batch_size=BATCH_SIZE #訓(xùn)練集批次
    )

test_generator = test_datagen.flow_from_directory( #設(shè)置測試集迭代器
    TEST_PATH, #測試集存放路徑
    target_size=(IMG_W,IMG_H), #測試集圖片尺寸
    batch_size=BATCH_SIZE, #測試集批次
    )

增加判定機(jī)制,如果文件夾下沒有已訓(xùn)練的模型宇立,那么從頭開始訓(xùn)練踪宠,如果已有訓(xùn)練過的模型,那么在此基礎(chǔ)上妈嘹,繼續(xù)訓(xùn)練:

try:
    model = load_model('{}.h5'.format(SAVE_PATH))  #嘗試讀取訓(xùn)練好的模型柳琢,再次訓(xùn)練
    print('model upload,start training!')
except:
    print('not find model,start training') #如果沒有訓(xùn)練過的模型,則從頭開始訓(xùn)練

構(gòu)建好所有內(nèi)容润脸,使用fit_generator()擬合模型:

model.fit_generator( #模型擬合
                    train_generator,  #訓(xùn)練集迭代器
                    steps_per_epoch=len(train_generator), #每個(gè)周期需要迭代多少步(圖片總量/批次大小=11200/64=175)
                    epochs=EPOCHS, #迭代周期
                    validation_data=test_generator, #測試集迭代器
                    validation_steps=len(test_generator) #測試集迭代多少步
                    )

傳入訓(xùn)練集和測試集迭代器染厅,傳入周期,傳入迭代的步數(shù)津函。

模型擬合完畢,保存模型結(jié)構(gòu)孤页,用于預(yù)測和再次訓(xùn)練:

model.save('{}.h5'.format(SAVE_PATH)) #保存模型
print('finish {} epochs!'.format(EPOCHS))

3.模型訓(xùn)練

運(yùn)行腳本~


image

這里會先顯示訓(xùn)練集和測試集的樣本大小尔苦,分類數(shù)量,分類名稱行施。如果是使用GPU訓(xùn)練模型允坚,這里還會顯示顯卡參數(shù)。強(qiáng)烈建議使用GPU模式蛾号。因?yàn)楦鶕?jù)運(yùn)行后的結(jié)果稠项,模型在訓(xùn)練200個(gè)周期以上后,準(zhǔn)確率才能達(dá)到80%鲜结,一個(gè)周期平均1分鐘展运,而使用CPU模式,則要30分鐘左右精刷,效率差距巨大拗胜。

接下來,正式開始訓(xùn)練怒允,會顯示批次埂软,步數(shù),準(zhǔn)確率等信息纫事,一開始準(zhǔn)確率是很低的勘畔。只有7%,約等于1/14丽惶,完全隨機(jī):


image

訓(xùn)練一段時(shí)間后炫七,準(zhǔn)確率會上升:


image

這里我訓(xùn)練超過200個(gè)周期以后,準(zhǔn)確率達(dá)到約80%蚊夫。這里注意诉字,前200個(gè)周期我設(shè)置了0.5的dropout,發(fā)現(xiàn)模型提升速度比較慢,建議數(shù)值可以設(shè)置小一點(diǎn)壤圃,甚至為0陵霉。

經(jīng)過漫長的訓(xùn)練,我訓(xùn)練了約400個(gè)周期伍绳。模型最終效果如圖所示:


image

訓(xùn)練集準(zhǔn)確率大于90%踊挠,而測試集準(zhǔn)確率約84%。我發(fā)現(xiàn)再繼續(xù)訓(xùn)練冲杀,訓(xùn)練集準(zhǔn)確率還能再提高效床,但測試集準(zhǔn)確率幾乎提高不了了,過擬合情況越來越嚴(yán)重权谁,這時(shí)剩檀,果斷停止訓(xùn)練。

4.結(jié)果展示

模型訓(xùn)練好了旺芽,那么我們采用實(shí)際的案例來測試下效果沪猴。我從花店拍了一些不同花卉的照片如下:


image

寫一個(gè)簡單的腳本,功能為導(dǎo)入訓(xùn)練好的模型采章,再把用于預(yù)測的圖片轉(zhuǎn)換成模型的對應(yīng)格式运嗜。比如尺寸為224*224~

from keras.models import load_model
from keras.preprocessing.image import img_to_array,load_img
import numpy as np
import os
# 載入模型
model = load_model('flower_selector.h5')
label = np.array(['康乃馨','杜鵑花','桂花','桃花','梅花','洛神花','牡丹','牽牛花','玫瑰','茉莉花','荷花','菊花','蒲公英','風(fēng)信子'])
def image_change(image):
    image = image.resize((224,224))
    image = img_to_array(image)
    image = image/255
    image = np.expand_dims(image,0)
    return image

然后悯舟,遍歷文件夾下的圖片進(jìn)行預(yù)測:

for pic in os.listdir('./predict'):
    print('圖片真實(shí)分類為',pic)
    image = load_img('./predict/' + pic)
    image = image_change(image)
    print('預(yù)測結(jié)果為',label[model.predict_classes(image)])
    print('----------------------------------')

結(jié)果如下:


image

預(yù)測準(zhǔn)確率達(dá)到百分之百担租,鼓掌~!5衷酢7芫取!便贵!

經(jīng)過了層層挑戰(zhàn)菠镇,我終于完成了機(jī)器識花的工作,準(zhǔn)備去給我的女盆友們買花了承璃!大家也快關(guān)注“大鵬教你玩數(shù)據(jù)”后在后臺回復(fù)【30】利耍,獲取源代碼和學(xué)習(xí)素材學(xué)起來吧~

免費(fèi)獲取【1.6G AI學(xué)習(xí)資料】和其他福利,請加QQ群:837627861
轉(zhuǎn)載請?jiān)诠娞柡笈_聯(lián)系小編盔粹,請勿擅自轉(zhuǎn)載隘梨。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市舷嗡,隨后出現(xiàn)的幾起案子轴猎,更是在濱河造成了極大的恐慌,老刑警劉巖进萄,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捻脖,死亡現(xiàn)場離奇詭異锐峭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)可婶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門沿癞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人矛渴,你說我怎么就攤上這事椎扬。” “怎么了具温?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵蚕涤,是天一觀的道長。 經(jīng)常有香客問我铣猩,道長揖铜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任达皿,我火速辦了婚禮蛮位,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鳞绕。我一直安慰自己,他們只是感情好尸曼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布们何。 她就那樣靜靜地躺著,像睡著了一般控轿。 火紅的嫁衣襯著肌膚如雪冤竹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天茬射,我揣著相機(jī)與錄音鹦蠕,去河邊找鬼。 笑死在抛,一個(gè)胖子當(dāng)著我的面吹牛钟病,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播刚梭,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼肠阱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了朴读?” 一聲冷哼從身側(cè)響起屹徘,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎衅金,沒想到半個(gè)月后噪伊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體簿煌,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年鉴吹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了姨伟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拙寡,死狀恐怖授滓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情肆糕,我是刑警寧澤般堆,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站诚啃,受9級特大地震影響淮摔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜始赎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一和橙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧造垛,春花似錦魔招、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至杆逗,卻和暖如春乡翅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背罪郊。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工蠕蚜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人悔橄。 一個(gè)月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓靶累,卻偏偏與公主長得像,于是被迫代替她去往敵國和親癣疟。 傳聞我的和親對象是個(gè)殘疾皇子尺铣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容