在學習了python中的一些機器學習的相關模塊后,再一次開始了深度學習之旅。不過與上次的TensorFlow
框架不同,這一次接觸的是fast.ai
這樣一個東西。這個框架還不穩定,網上也沒有相關的中文文檔。唯一一個學習站點就是 fastai 這樣一個論壇,另外就是里面的公開課程。
性別識別模型使用體驗: http://www.ctsch.cn/?page_id=11
請確認上傳的圖片中有人,否則對於其他類型的圖片,也就當男女論處,目前在它的世界中只有男女。
附上fastai項目的相關連接:
- Github項目地址: https://github.com/fastai/fastai
- fastai論壇: http://forums.fast.ai/
- fastai課程:http://course.fast.ai/lessons/lesson1.html
注意:
- 在配置環境時使用 Anaconda,安裝方法可以自行百度
- 使用安裝fastai訓練模型時要安裝GPU版本(前提是你有支持GPU的顯卡),否則建議你不要用來訓練模型,使用cpu訓練會非常非常慢。當然GPU需要安裝cuda和cudnn(安裝步驟可以自行百度)。
Github上有相關的安裝教程,能夠成功安裝,有問題可以在本文后留言,我會盡力回復。
在該課程的第一課就是一個利用神經網絡識別貓狗。在這中間使用了resnet34模型進行訓練。這個模型是在ImageNet數據集比賽上獲得過優異成績的模型,這個預訓練使我們不需要自己構建神經網絡,只要我們能會使用就可以了。這也算是第一課的基礎導入吧。
下面要講的內容,在視頻中都可以找到,這里主要寫一些我覺的使用fastai比較重要和特殊的地方
1
2
3
4
5
6
|
# 在fastai要建立一個model,只需要下面的三行就可以了,第四行是訓練model
arch=resnet34 # 使用model
data = ImageClassifierData.from_paths(PATH, tfms=tfms_from_model(arch, sz)) # 圖片數的組織類別
learn = ConvLearner.pretrained(arch, data, precompute=True) # 卷積神經網絡的容器
learn.fit(0.01, 3) # 訓練model
|
- 要點一:訓練、驗證和預測數據的文件組織架構
圖片數據的存放形式:
在每個分類(如:male、female)中存放的就是樣本圖片了。 -
要點二: 解釋上面代碼中的
learn.fit(0.01, 3)
:
我們現在使用的resnet34模型是一個在ImageNet數據集上訓練好了的model,里面權重數據一個非常好了,不需要我們在進行改善什么,但我們需要根據我們自己的實際數據訓練神經網絡的最后一層權重。所以上面這個代碼是訓練model的最后一層。至於為什么,那是因為,resnet34預訓練模型是使用ImageNet數據集訓練的,他們的類別可能有1000類,所以模型的最后一層默認是1000維的,但是我們的數據分類只有兩類—貓和狗。因此我們需要這一步驟。 -
要點三: fastai中ConvLearner類有一個自動尋找最優學習率的函數 learn.lr_fint()
我們知道,在神經網絡中,學習率是一個非常重要的超參數,調節的不好,會導致模型不能收斂或者收斂的太慢。通過這個函數,它可以幫助我們在指定范圍內自動找到最合適的學習率。我們可以通過learn.sched.plot_lr()
函數繪制出學習率與訓練輪數的關系;也可以通過learn.sched.plot()
繪制出學習率與損失值得變化情況,從而選擇出最合適的學習率。
以上是一些學習記錄,下面開始訓練性別識別模型。
使用resnet34訓練性別識別模型
在訓練之前首先要做的就是收集數據,數據是使用 GoogleImageDownloader 工具自動爬取的,在Google上爬了大概3500張圖片,里面有些圖片質量不夠好,刪除了之后大概還有2400張左右。
data and code url: 鏈接: https://pan.baidu.com/s/1TbvupSigvKJoQp8JrIFFOA 密碼: sxqc
具體代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
import sys
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
sys.path.append("/Volumes/05/jupyter/fastai")
from fastai.imports import *
from fastai.torch_imports import *
from fastai.transforms import *
from fastai.conv_learner import *
from fastai.model import *
from fastai.dataset import *
from fastai.sgdr import *
from fastai.plots import *
PATH = 'data/malefemale/'
sz = 224
# 使用resnet34model
arch = resnet34
data = ImageClassifierData.from_paths(PATH,tfms=tfms_from_model(arch, sz))
learn = ConvLearner.pretrained(arch, data, precompute=True)
# 第一次輕微訓練最后一層
learn.fit(0.01, 3)
learn.fit(0.05, 5, cycle_len=1, cycle_mult=2)
|
在這一次的訓練中,發現模型損失還有0.29,模型在驗證上的正確率才到93%,模型還有優化的空間。
下面再一次構造模型並訓練:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
tfms = tfms_from_model(resnet34, sz,aug_tfms=transforms_side_on, max_zoom=1.1) # 通過轉變角度,增加樣本
data = ImageClassifierData.from_paths(PATH, tfms=tfms)
learn = ConvLearner.pretrained(resnet34, data, precompute=True)
learn.fit(0.01, 3)# 第一次訓練最后一層,試探性
learn.fit(0.05, 5, cycle_len=1, cycle_mult=2) # 發現第一次訓練有效果,在進一步訓練
learn.precompute = False # 開啟全部層都可以訓練,對每層進行微訓練
learn.fit([1e-4,1e-3,1e-2], 4, cycle_len=1) # 初步訓練
learn.unfreeze()
learn.fit([1e-3,1e-3, 1e-2], 5, cycle_len=1, cycle_mult=2) # 發現上一次有效果,在進行深度訓練
|
最后 模型在訓練集上的loss到達了0.025,在驗證集上的loss達到了0.18,在驗證集上的正確率達到了 94.9%。在我多次訓練后,發現這是最好的了,所以就沒有再進行改進了。
但是,現在還沒有完,我們現在要看看模型在數據集上的表現到底怎么樣。下面,使用matplotlib庫進行可視化分析:
可視化分析
首先獲得模型的預測數據:
1
2
3
4
5
6
7
8
9
|
log_preds = learn.predict() # 預測所有的驗證集,返回的 ln pi的數據
prob_preds = np.exp(log_preds) # 將對數概率轉回正常的概率
y_pred = np.argmax(np.exp(prob_preds), 1) # 獲取預測的分類,這里面是0,1數據,0表示女性,1表示男性
male_df = pd.DataFrame({'image':data.val_ds.fnames,'y_true':data.val_y, 'y_pred':y_pred, 'y_prob_female':prob_preds[:,0], 'y_prob_male':prob_preds[:,1]}) # 將所有的數據合並成pandas的DataFrame
male_df.head() # 輸出下DataFrame
|
說明:
- image 圖片樣本的路徑
- y_true 樣本的真實類別
- y_pred 樣本的預測類別
- y_prob_female 模型預測該樣本為女性的概率
- y_prob_male 模型預測該樣本為男性的概率
1、查看模型的混淆矩陣
1
2
3
4
5
6
|
from sklearn.metrics import confusion_matrix
import seaborn as sns
mat = confusion_matrix(data.val_y, y_pred)
plot_confusion_matrix(mat, data.classes)
|
可以看到,在152個女性樣本和143個男性樣本中,有10張女性樣本被錯誤的分成了男性,但僅有5個男性樣本被錯誤的分詞女性,可以看出模型在男性特征的學習中學習的較充足,到對女性特征學習還有待提高。出現這個情況的原因是在訓練樣本中男性樣本比女多了近200個樣本,因此模型學習男性的特征較多,因此判斷更有把握。
2、查看模型在驗證集中預測最有把握的樣本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
# 最有把握的女性
mostly_female = male_df[male_df['y_true']==0].sort_values(by='y_prob_female', ascending=False)
print('mostly female:')
fig, axes = plt.subplots(4,4, figsize=(20, 10))
for i,ax in enumerate(axes.flat):
src = mostly_female.iloc[i]['image']
ax.imshow(plt.imread(f'{PATH}{src}'))
ax.text(0, 0, str(mostly_female.iloc[i]['y_prob_female']), fontsize=16)
ax.axis('off')
# 最有把握的男性
mostly_male = male_df[male_df['y_true']==1].sort_values(by='y_prob_male', ascending=False)
print('mostly male:')
fig, axes = plt.subplots(4,4, figsize=(20, 10))
for i,ax in enumerate(axes.flat):
src = mostly_male.iloc[i]['image']
ax.imshow(plt.imread(f'{PATH}{src}'))
ax.text(0, 0, str(mostly_male.iloc[i]['y_prob_male']), fontsize=16)
ax.axis('off')
|
在這些樣本中,男性和女性的外在特征都比較明顯的顯示出來了,因此模型的判斷概率都是100%。
3、查看模型在驗證集中預測錯誤最明顯的的樣本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
# 預測出錯最明顯的女性
incorrect_female = male_df[(male_df['y_true']==0) & (male_df['y_pred']==1)].sort_values(by='y_prob_female', ascending=False)
print('incorrect female to predict male:')
fig, axes = plt.subplots(2,4, figsize=(20, 10))
for i,ax in enumerate(axes.flat):
src = incorrect_female.iloc[-i-1]['image']
ax.imshow(plt.imread(f'{PATH}{src}'))
ax.text(0, 0, str(incorrect_female.iloc[-i-1]['y_prob_female']), fontsize=16)
ax.axis('off')
# 預測出錯最明顯的男性
incorrect_male = male_df[(male_df['y_true']==1) & (male_df['y_pred']==0)].sort_values(by='y_prob_male', ascending=False)
print('incorrect male to predict female:')
fig, axes = plt.subplots(1,4, figsize=(20, 10))
for i,ax in enumerate(axes.flat):
src = incorrect_male.iloc[-i-1]['image']
ax.imshow(plt.imread(f'{PATH}{src}'))
ax.text(0, 0, str(incorrect_male.iloc[-i-1]['y_prob_male']), fontsize=16)
ax.axis('off')
|
從上面兩幅圖中可以看出,模型對於男女特征沒有明顯展示出來的樣本(如馬尾頭發的樣本)出錯概率最大,另外從第一幅圖的第四個樣本看出,模型將具有肌肉的這樣特征的樣本認為是男性,這與我們生活中一般常識—–女性一般沒有肌肉是吻合的。
在男性的錯誤樣本中,我們可以看出模型在男性樣本上的預測是很不錯的。男性的第一個樣本具有欺騙性,包括人類去識別可能也會出錯,其他幾個樣本就是沒有顯示出男性特征,所以這個出錯是可以容忍的。
總的來說,模型在預測時的表現是非常不錯的,一般的有特征的圖片都能正確識別,讀者可以自行上傳圖片去試試。地址就在下面。
體驗地址,上傳圖片就可以使用了。 http://www.ctsch.cn/?page_id=11