人工神經(jīng)網(wǎng)絡(luò)訓(xùn)練圖像分類器
我們將僅使用全連接層在20000張圖像上訓(xùn)練圖像分類模型。所以沒有卷積和其他花哨的東西,我們將把它們留到下一篇文章中。
不用說,但你真的不應(yīng)該使用普通的人工神經(jīng)網(wǎng)絡(luò)來分類圖像。圖像是二維的,通過展平圖像,你將失去使圖像可識別的模式。盡管如此,它還是很有趣且可行的,并且會(huì)讓你洞察這種方法的所有錯(cuò)誤。
使用的數(shù)據(jù)集和數(shù)據(jù)準(zhǔn)備
我們將使用Kaggle的狗與貓數(shù)據(jù)集。它是根據(jù)知識共享許可證授權(quán)的,這意味著你可以免費(fèi)使用它:
圖1:狗與貓數(shù)據(jù)集:
該數(shù)據(jù)集相當(dāng)大——25000張圖像均勻分布在不同的類中(12500張狗圖像和12500張貓圖像)。它應(yīng)該足夠大,可以訓(xùn)練一個(gè)像樣的圖像分類器,但不能使用人工神經(jīng)網(wǎng)絡(luò)。
唯一的問題是——它的結(jié)構(gòu)不適合直接使用。你可以按照之前的文章創(chuàng)建一個(gè)適當(dāng)?shù)哪夸浗Y(jié)構(gòu),并將其拆分為訓(xùn)練集、測試集和驗(yàn)證集:
縮小、灰度化和展平圖像
讓我們導(dǎo)入相關(guān)庫。我們需要很多,需要安裝Numpy、Pandas、TensorFlow、PIL和Scikit Learn:
我們不能將圖像直接傳遞到Dense層。單個(gè)圖像是三維的——高度、寬度、顏色通道——而Dense層需要一維輸入。
讓我們看一個(gè)例子。以下代碼加載并顯示訓(xùn)練集中的cat圖像:
src_img = Image.open('data/train/cat/1.jpg')
display(src_img)
圖2——貓的圖片示例
圖像寬281像素,高300像素,有三個(gè)顏色通道(np.a(chǎn)rray(src_img).shape)。
總的來說,它有252900個(gè)像素,在展平時(shí)轉(zhuǎn)化為252900個(gè)特征。讓我們盡可能節(jié)省一些資源。
如果有意義的話,你應(yīng)該對你的圖像數(shù)據(jù)集進(jìn)行灰度化。如果你能對不以顏色顯示的圖像進(jìn)行分類,那么神經(jīng)網(wǎng)絡(luò)也應(yīng)該如此。可以使用以下代碼段將圖像轉(zhuǎn)換為灰色:
gray_img = ImageOps.grayscale(src_img)
display(gray_img)
圖3:灰色貓圖像
顯然,它仍然是一只貓,所以顏色在這個(gè)數(shù)據(jù)集中并沒有起到很大作用。
灰度圖像寬281像素,高300像素,但只有一個(gè)顏色通道。這意味著我們從252,900 像素減少到84,300 像素。仍然很多,但肯定是朝著正確的方向邁出了一步。
數(shù)據(jù)集中的圖像大小不同。這對于神經(jīng)網(wǎng)絡(luò)模型來說是個(gè)問題,因?yàn)樗看味夹枰嗤瑪?shù)量的輸入特征。
我們可以將每個(gè)圖像調(diào)整為相同的寬度和高度,以進(jìn)一步減少輸入特征的數(shù)量。
下面的代碼片段調(diào)整了圖像的大小,使其既寬又高96像素:
gray_resized_img = gray_img.resize(size=(96, 96))
display(gray_resized_img)
圖4:調(diào)整大小的貓圖片
當(dāng)然,圖像有點(diǎn)小而且模糊,但它仍然是一只貓。但是我們的特征減少到9216個(gè),相當(dāng)于將特征的數(shù)量減少了27倍。
作為最后一步,我們需要將圖像展平。你可以使用Numpy中的ravel函數(shù)來執(zhí)行此操作:
np.ravel(gray_resized_img)
圖5:扁平貓圖片
計(jì)算機(jī)就是這樣看待貓的——它只是一個(gè)9216像素的數(shù)組,范圍從0到255。問題是——神經(jīng)網(wǎng)絡(luò)更喜歡0到1之間的范圍。我們將整個(gè)數(shù)組除以255.0即可:
img_final = np.ravel(gray_resized_img) / 255.0
img_final
圖6-扁平和縮放的貓圖像
作為最后一步,我們將編寫一個(gè)process_image函數(shù),將上述所有轉(zhuǎn)換應(yīng)用于單個(gè)圖像:
讓我們在隨機(jī)的狗圖像上進(jìn)行測試,然后反轉(zhuǎn)最后一步,以直觀地表示圖像:
tst_img = process_image(img_path='data/validation/dog/10012.jpg')
Image.fromarray(np.uint8(tst_img * 255).reshape((96, 96)))
圖7:經(jīng)過變換的狗形象
就這樣,這個(gè)函數(shù)就像字面意思。接下來,我們將其應(yīng)用于整個(gè)數(shù)據(jù)集。
將圖像轉(zhuǎn)換為表格數(shù)據(jù)進(jìn)行深度學(xué)習(xí)
我們將編寫另一個(gè)函數(shù)——process_folder——它迭代給定的文件夾,并在任何JPG文件上使用process_image函數(shù)。然后,它將所有圖像合并到一個(gè)數(shù)據(jù)幀中,并添加一個(gè)類作為附加列(貓或狗):
讓我們將其應(yīng)用于訓(xùn)練、測試和驗(yàn)證文件夾。每個(gè)文件夾需要調(diào)用兩次,一次用于貓,一次用于狗,然后連接集合。我們還將把數(shù)據(jù)集轉(zhuǎn)儲(chǔ)到pickle文件中:
下面是訓(xùn)練集的樣子:
# Training set
train_cat = process_folder(folder=pathlib.Path.cwd().joinpath('data/train/cat'))
train_dog = process_folder(folder=pathlib.Path.cwd().joinpath('data/train/dog'))
train_set = pd.concat([train_cat, train_dog], axis=0)
with open('train_set.pkl', 'wb') as f:
pickle.dump(train_set, f)
# Test set
test_cat = process_folder(folder=pathlib.Path.cwd().joinpath('data/test/cat'))
test_dog = process_folder(folder=pathlib.Path.cwd().joinpath('data/test/dog'))
test_set = pd.concat([test_cat, test_dog], axis=0)
with open('test_set.pkl', 'wb') as f:
pickle.dump(test_set, f)
# Validation set
valid_cat = process_folder(folder=pathlib.Path.cwd().joinpath('data/validation/cat'))
valid_dog = process_folder(folder=pathlib.Path.cwd().joinpath('data/validation/dog'))
valid_set = pd.concat([valid_cat, valid_dog], axis=0)
with open('valid_set.pkl', 'wb') as f:
pickle.dump(valid_set, f)
圖8——訓(xùn)練集
數(shù)據(jù)集包含所有貓的圖像,然后是所有狗的圖像。這對于訓(xùn)練集和驗(yàn)證集來說并不理想,因?yàn)樯窠?jīng)網(wǎng)絡(luò)會(huì)按照這個(gè)順序看到它們。
你可以使用Scikit Learn中的隨機(jī)函數(shù)來隨機(jī)排序:
train_set = shuffle(train_set).reset_index(drop=True)
valid_set = shuffle(valid_set).reset_index(drop=True)
下面是它現(xiàn)在的樣子:
圖9——隨機(jī)后的訓(xùn)練集
下一步是將特征與目標(biāo)分離。我們將對所有三個(gè)子集進(jìn)行拆分:
X_train = train_set.drop('class', axis=1)
y_train = train_set['class']
X_valid = valid_set.drop('class', axis=1)
y_valid = valid_set['class']
X_test = test_set.drop('class', axis=1)
y_test = test_set['class']
最后,使用數(shù)字編碼目標(biāo)變量。有兩個(gè)不同的類(cat和dog),因此每個(gè)實(shí)例的目標(biāo)變量應(yīng)該包含兩個(gè)元素。
例如,使用factorize函數(shù)進(jìn)行編碼:
y_train.factorize()
圖10-factorize函數(shù)
標(biāo)簽被轉(zhuǎn)換成整數(shù)——貓為0,狗為1。
你可以使用TensorFlow中的to_category函數(shù),并傳入factorize后的數(shù)組,以及不同類的數(shù)量(2):
y_train = tf.keras.utils.to_categorical(y_train.factorize()[0], num_classes=2)
y_valid = tf.keras.utils.to_categorical(y_valid.factorize()[0], num_classes=2)
y_test = tf.keras.utils.to_categorical(y_test.factorize()[0], num_classes=2)
因此,y_train現(xiàn)在看起來是這樣的:
圖11——目標(biāo)變量
從概率的角度考慮——第一張圖片有100%的幾率是貓,0%的幾率是狗。這些都是真實(shí)的標(biāo)簽,所以概率可以是0或1。
我們現(xiàn)在終于有了訓(xùn)練神經(jīng)網(wǎng)絡(luò)模型所需的一切。
用人工神經(jīng)網(wǎng)絡(luò)(ANN)訓(xùn)練圖像分類模型
我隨機(jī)選擇了層的數(shù)量和每層的節(jié)點(diǎn)數(shù)量,以下2部分不能更改:
· 輸出層——它需要兩個(gè)節(jié)點(diǎn),因?yàn)槲覀冇袃蓚(gè)不同的類。我們不能再使用sigmoid激活函數(shù)了,所以選擇softmax。
· 損失函數(shù)——我們使用分類交叉熵。
其他部分可以隨意更改:
以下是我在100個(gè)epoch后得到的結(jié)果:
圖12:100個(gè)epoch后的ANN結(jié)果
60%的準(zhǔn)確率比猜測稍微好一點(diǎn),但性能一般。盡管如此,我們還是來檢查一下訓(xùn)練期間指標(biāo)發(fā)生了什么變化。
以下代碼片段繪制了100個(gè)epoch中每個(gè)epoch的訓(xùn)練損失與驗(yàn)證損失:
plt.plot(np.a(chǎn)range(1, 101), history.history['loss'], label='Training Loss')
plt.plot(np.a(chǎn)range(1, 101), history.history['val_loss'], label='Validation Loss')
plt.title('Training vs. Validation Loss', size=20)
plt.xlabel('Epoch', size=14)
plt.legend();
圖13:訓(xùn)練損失與驗(yàn)證損失
該模型能很好地學(xué)習(xí)訓(xùn)練數(shù)據(jù),但不能推廣。隨著我們對模型進(jìn)行更多epoch的訓(xùn)練,驗(yàn)證損失繼續(xù)增加,這表明模型不穩(wěn)定且不可用。
讓我們看看準(zhǔn)確度:
plt.plot(np.a(chǎn)range(1, 101), history.history['accuracy'], label='Training Accuracy')
plt.plot(np.a(chǎn)range(1, 101), history.history['val_accuracy'], label='Validation Accuracy')
plt.title('Training vs. Validation Accuracy', size=20)
plt.xlabel('Epoch', size=14)
plt.legend();
圖14:訓(xùn)練準(zhǔn)確度與驗(yàn)證準(zhǔn)確度
類似的圖片。驗(yàn)證精度穩(wěn)定在60%左右,而模型對訓(xùn)練數(shù)據(jù)的擬合度過高。
對于一個(gè)包含20K訓(xùn)練圖像的兩類數(shù)據(jù)集,60%的準(zhǔn)確率幾乎是它所能達(dá)到的最差水平。原因很簡單——Dense層的設(shè)計(jì)并不是為了捕捉二維圖像數(shù)據(jù)的復(fù)雜性。
結(jié)論
現(xiàn)在你知道了——如何用人工神經(jīng)網(wǎng)絡(luò)訓(xùn)練一個(gè)圖像分類模型,以及為什么你不應(yīng)該這么做。這就像穿著人字拖爬山——也許你能做到,但最好不要。
原文標(biāo)題 : 人工神經(jīng)網(wǎng)絡(luò)訓(xùn)練圖像分類器

請輸入評論內(nèi)容...
請輸入評論/評論長度6~500個(gè)字
最新活動(dòng)更多
-
3月27日立即報(bào)名>> 【工程師系列】汽車電子技術(shù)在線大會(huì)
-
4月30日立即下載>> 【村田汽車】汽車E/E架構(gòu)革新中,新智能座艙挑戰(zhàn)的解決方案
-
5月15-17日立即預(yù)約>> 【線下巡回】2025年STM32峰會(huì)
-
即日-5.15立即報(bào)名>>> 【在線會(huì)議】安森美Hyperlux™ ID系列引領(lǐng)iToF技術(shù)革新
-
5月15日立即下載>> 【白皮書】精確和高效地表征3000V/20A功率器件應(yīng)用指南
-
5月16日立即參評 >> 【評選啟動(dòng)】維科杯·OFweek 2025(第十屆)人工智能行業(yè)年度評選
推薦專題
- 1 UALink規(guī)范發(fā)布:挑戰(zhàn)英偉達(dá)AI統(tǒng)治的開始
- 2 北電數(shù)智主辦酒仙橋論壇,探索AI產(chǎn)業(yè)發(fā)展新路徑
- 3 降薪、加班、裁員三重暴擊,“AI四小龍”已折戟兩家
- 4 “AI寒武紀(jì)”爆發(fā)至今,五類新物種登上歷史舞臺(tái)
- 5 國產(chǎn)智駕迎戰(zhàn)特斯拉FSD,AI含量差幾何?
- 6 光計(jì)算迎來商業(yè)化突破,但落地仍需時(shí)間
- 7 東陽光:2024年扭虧、一季度凈利大增,液冷疊加具身智能打開成長空間
- 8 地平線自動(dòng)駕駛方案解讀
- 9 封殺AI“照騙”,“淘寶們”終于不忍了?
- 10 優(yōu)必選:營收大增主靠小件,虧損繼續(xù)又逢關(guān)稅,能否乘機(jī)器人東風(fēng)翻身?