人工神經網(wǎng)絡訓練圖像分類器
我們將僅使用全連接層在20000張圖像上訓練圖像分類模型。所以沒有卷積和其他花哨的東西,我們將把它們留到下一篇文章中。
不用說,但你真的不應該使用普通的人工神經網(wǎng)絡來分類圖像。圖像是二維的,通過展平圖像,你將失去使圖像可識別的模式。盡管如此,它還是很有趣且可行的,并且會讓你洞察這種方法的所有錯誤。
使用的數(shù)據(jù)集和數(shù)據(jù)準備
我們將使用Kaggle的狗與貓數(shù)據(jù)集。它是根據(jù)知識共享許可證授權的,這意味著你可以免費使用它:
圖1:狗與貓數(shù)據(jù)集:
該數(shù)據(jù)集相當大——25000張圖像均勻分布在不同的類中(12500張狗圖像和12500張貓圖像)。它應該足夠大,可以訓練一個像樣的圖像分類器,但不能使用人工神經網(wǎng)絡。
唯一的問題是——它的結構不適合直接使用。你可以按照之前的文章創(chuàng)建一個適當?shù)哪夸浗Y構,并將其拆分為訓練集、測試集和驗證集:
縮小、灰度化和展平圖像
讓我們導入相關庫。我們需要很多,需要安裝Numpy、Pandas、TensorFlow、PIL和Scikit Learn:
我們不能將圖像直接傳遞到Dense層。單個圖像是三維的——高度、寬度、顏色通道——而Dense層需要一維輸入。
讓我們看一個例子。以下代碼加載并顯示訓練集中的cat圖像:
src_img = Image.open('data/train/cat/1.jpg')
display(src_img)
圖2——貓的圖片示例
圖像寬281像素,高300像素,有三個顏色通道(np.array(src_img).shape)。
總的來說,它有252900個像素,在展平時轉化為252900個特征。讓我們盡可能節(jié)省一些資源。
如果有意義的話,你應該對你的圖像數(shù)據(jù)集進行灰度化。如果你能對不以顏色顯示的圖像進行分類,那么神經網(wǎng)絡也應該如此。可以使用以下代碼段將圖像轉換為灰色:
gray_img = ImageOps.grayscale(src_img)
display(gray_img)
圖3:灰色貓圖像
顯然,它仍然是一只貓,所以顏色在這個數(shù)據(jù)集中并沒有起到很大作用。
灰度圖像寬281像素,高300像素,但只有一個顏色通道。這意味著我們從252,900 像素減少到84,300 像素。仍然很多,但肯定是朝著正確的方向邁出了一步。
數(shù)據(jù)集中的圖像大小不同。這對于神經網(wǎng)絡模型來說是個問題,因為它每次都需要相同數(shù)量的輸入特征。
我們可以將每個圖像調整為相同的寬度和高度,以進一步減少輸入特征的數(shù)量。
下面的代碼片段調整了圖像的大小,使其既寬又高96像素:
gray_resized_img = gray_img.resize(size=(96, 96))
display(gray_resized_img)
圖4:調整大小的貓圖片
當然,圖像有點小而且模糊,但它仍然是一只貓。但是我們的特征減少到9216個,相當于將特征的數(shù)量減少了27倍。
作為最后一步,我們需要將圖像展平。你可以使用Numpy中的ravel函數(shù)來執(zhí)行此操作:
np.ravel(gray_resized_img)
圖5:扁平貓圖片
計算機就是這樣看待貓的——它只是一個9216像素的數(shù)組,范圍從0到255。問題是——神經網(wǎng)絡更喜歡0到1之間的范圍。我們將整個數(shù)組除以255.0即可:
img_final = np.ravel(gray_resized_img) / 255.0
img_final
圖6-扁平和縮放的貓圖像
作為最后一步,我們將編寫一個process_image函數(shù),將上述所有轉換應用于單個圖像:
讓我們在隨機的狗圖像上進行測試,然后反轉最后一步,以直觀地表示圖像:
tst_img = process_image(img_path='data/validation/dog/10012.jpg')
Image.fromarray(np.uint8(tst_img * 255).reshape((96, 96)))
圖7:經過變換的狗形象
就這樣,這個函數(shù)就像字面意思。接下來,我們將其應用于整個數(shù)據(jù)集。
將圖像轉換為表格數(shù)據(jù)進行深度學習
我們將編寫另一個函數(shù)——process_folder——它迭代給定的文件夾,并在任何JPG文件上使用process_image函數(shù)。然后,它將所有圖像合并到一個數(shù)據(jù)幀中,并添加一個類作為附加列(貓或狗):
讓我們將其應用于訓練、測試和驗證文件夾。每個文件夾需要調用兩次,一次用于貓,一次用于狗,然后連接集合。我們還將把數(shù)據(jù)集轉儲到pickle文件中:
下面是訓練集的樣子:
# 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——訓練集
數(shù)據(jù)集包含所有貓的圖像,然后是所有狗的圖像。這對于訓練集和驗證集來說并不理想,因為神經網(wǎng)絡會按照這個順序看到它們。
你可以使用Scikit Learn中的隨機函數(shù)來隨機排序:
train_set = shuffle(train_set).reset_index(drop=True)
valid_set = shuffle(valid_set).reset_index(drop=True)
下面是它現(xiàn)在的樣子:
圖9——隨機后的訓練集
下一步是將特征與目標分離。我們將對所有三個子集進行拆分:
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ù)字編碼目標變量。有兩個不同的類(cat和dog),因此每個實例的目標變量應該包含兩個元素。
例如,使用factorize函數(shù)進行編碼:
y_train.factorize()
圖10-factorize函數(shù)
標簽被轉換成整數(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——目標變量
從概率的角度考慮——第一張圖片有100%的幾率是貓,0%的幾率是狗。這些都是真實的標簽,所以概率可以是0或1。
我們現(xiàn)在終于有了訓練神經網(wǎng)絡模型所需的一切。
用人工神經網(wǎng)絡(ANN)訓練圖像分類模型
我隨機選擇了層的數(shù)量和每層的節(jié)點數(shù)量,以下2部分不能更改:
· 輸出層——它需要兩個節(jié)點,因為我們有兩個不同的類。我們不能再使用sigmoid激活函數(shù)了,所以選擇softmax。
· 損失函數(shù)——我們使用分類交叉熵。
其他部分可以隨意更改:
以下是我在100個epoch后得到的結果:
圖12:100個epoch后的ANN結果
60%的準確率比猜測稍微好一點,但性能一般。盡管如此,我們還是來檢查一下訓練期間指標發(fā)生了什么變化。
以下代碼片段繪制了100個epoch中每個epoch的訓練損失與驗證損失:
plt.plot(np.arange(1, 101), history.history['loss'], label='Training Loss')
plt.plot(np.arange(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:訓練損失與驗證損失
該模型能很好地學習訓練數(shù)據(jù),但不能推廣。隨著我們對模型進行更多epoch的訓練,驗證損失繼續(xù)增加,這表明模型不穩(wěn)定且不可用。
讓我們看看準確度:
plt.plot(np.arange(1, 101), history.history['accuracy'], label='Training Accuracy')
plt.plot(np.arange(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:訓練準確度與驗證準確度
類似的圖片。驗證精度穩(wěn)定在60%左右,而模型對訓練數(shù)據(jù)的擬合度過高。
對于一個包含20K訓練圖像的兩類數(shù)據(jù)集,60%的準確率幾乎是它所能達到的最差水平。原因很簡單——Dense層的設計并不是為了捕捉二維圖像數(shù)據(jù)的復雜性。
結論
現(xiàn)在你知道了——如何用人工神經網(wǎng)絡訓練一個圖像分類模型,以及為什么你不應該這么做。這就像穿著人字拖爬山——也許你能做到,但最好不要。
原文標題 : 人工神經網(wǎng)絡訓練圖像分類器
請輸入評論內容...
請輸入評論/評論長度6~500個字
最新活動更多
-
即日-11.13立即報名>>> 【在線會議】多物理場仿真助跑新能源汽車
-
11月28日立即報名>>> 2024工程師系列—工業(yè)電子技術在線會議
-
12月19日立即報名>> 【線下會議】OFweek 2024(第九屆)物聯(lián)網(wǎng)產業(yè)大會
-
即日-12.26火熱報名中>> OFweek2024中國智造CIO在線峰會
-
即日-2025.8.1立即下載>> 《2024智能制造產業(yè)高端化、智能化、綠色化發(fā)展藍皮書》
-
精彩回顧立即查看>> 【限時免費下載】TE暖通空調系統(tǒng)高效可靠的組件解決方案
推薦專題
-
5 夾縫中的文遠知行
- 高級軟件工程師 廣東省/深圳市
- 自動化高級工程師 廣東省/深圳市
- 光器件研發(fā)工程師 福建省/福州市
- 銷售總監(jiān)(光器件) 北京市/海淀區(qū)
- 激光器高級銷售經理 上海市/虹口區(qū)
- 光器件物理工程師 北京市/海淀區(qū)
- 激光研發(fā)工程師 北京市/昌平區(qū)
- 技術專家 廣東省/江門市
- 封裝工程師 北京市/海淀區(qū)
- 結構工程師 廣東省/深圳市