使用fastai完成圖像分類

Wenqi Sun
by Wenqi Sun
1 min read

Categories

Tags

1. 使用現有數據集進行分類

圖像數據爲Oxford-IIIT Pet Dataset(12類貓和25類狗,共37類),這裏僅使用原始圖片集images.tar.gzjavascript

數據準備

import numpy as np
from fastai.vision import *
from fastai.metrics import error_rate

path_img = 'data/pets/images'
bs = 64 #batch size
fnames = get_image_files(path_img) #get filenames(absolute path) from path_img
pat = re.compile(r'/([^/]+)_d+.jpg$') #get labels from filenames(e.g., 'american_bulldog' from 'data/pets/images/american_bulldog_20.jpg')
### ImageDataBunch
### 使用正則表達式pat從圖像文件名fnames中提取標籤,並和圖像對應起來
### ds_tfms: 圖像轉換(翻轉、旋轉、裁剪、放大等),用於圖像數據加強(data augmentation)
### size: 最終圖像尺寸, bs: batch size, valid_pct: train/valid split
### normalize: 使用提供的均值和標準差(每一個通道對應一個均值和標準差)對圖像數據進行歸一化
np.random.seed(2)
data = ImageDataBunch.from_name_re(path_img, fnames, pat, ds_tfms=get_transforms(), size=224, bs=bs, valid_pct=0.2).normalize(imagenet_stats)
data.show_batch(rows=3, figsize=(7,6)) #grab a batch and display 3x3 images

模型搭建和訓練

使用Resnet34進行遷移學習,首先經過lr_find肯定最大學習率,再經過fit_one_cycle(1-Cycle style)進行訓練java

lr_find: 在前面幾回的迭代中將學習率從一個很小的值逐漸增長,選擇損失函數(train loss)處於降低趨勢之中而且距離損失中止降低的拐點有必定距離的點作爲模型的最大學習率max_lrpython

fit_one_cycle: 共分爲兩個階段,在第一階段學習率從max_lr/div_factor線性增加到max_lr,momentum線性地從moms[0]降到moms[1];第二階段學習率以餘弦形式從max_lr降爲0,momentum也一樣按餘弦形式從moms[1]增加到moms[0]。第一階段的迭代次數佔總迭代次數的比例爲pct_startgit

學習率和momentum: , , , 其中是要更新的參數,G爲梯度, 爲學習率, 爲momentumgithub

### Use Resnet34 to classify images
learn = create_cnn(data, models.resnet34, metrics=error_rate)
print(learn.model) #model summary
learn.lr_find()
learn.recorder.plot() #由左上圖能夠看出max_lr可選擇函數fit_one_cycle的默認值0.003
learn.fit_one_cycle(4, max_lr=slice(0.003), div_factor=25.0, moms=(0.95, 0.85), pct_start=0.3) #4 epochs
learn.recorder.plot_lr(show_moms=True) #中上圖(學習率)和右上圖(momentum), x軸表示迭代次數
learn.save('stage-1') #save model
### Unfreeze all the model layers and keep training
learn.unfreeze()
learn.lr_find()
learn.recorder.plot() #左下圖
### 由左下圖能夠看出max_lr可選擇1e-6, 可是模型的不一樣層能夠設置不一樣的學習率加速訓練
### 模型的前面幾層的學習率設置爲max_lr, 後面幾層的學習率能夠適當增長(例如能夠設置成比上一個fit_one_cycle的學習率小一個量級)
### slice(1e-6,1e-4)表示模型每層的學習率由1e-6逐漸增長過渡到1e-4
learn.fit_one_cycle(2, max_lr=slice(1e-6,1e-4), div_factor=25.0, moms=(0.95, 0.85), pct_start=0.3) #2 epochs
learn.recorder.plot_lr(show_moms=True) #中下圖(模型最後一層的學習率)和右下圖(momentum)

img

可視化

interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix(figsize=(12,12), dpi=60) #confusion matrix
print(interp.most_confused(min_val=2)) #從大到小列出混淆矩陣中非對角線的最大的幾個元素

2. 從谷歌圖片下載數據並進行分類

得到圖片連接

打開谷歌圖片,輸入想要下載的圖像類別,頁面上出現的圖片即爲可下載的圖片正則表達式

打開JavaScript Console(Windows/Linux:Ctrl+Shift+J, Mac:Cmd+Opt+J),運行下面的命令獲取圖片連接app

大專欄  使用fastai完成圖像分類 class="nx">urls = Array.from(document.querySelectorAll('.rg_di .rg_meta')).map(el=>JSON.parse(el.textContent).ou);
window.open('data:text/csv;charset=utf-8,' + escape(urls.join('n')));

分別搜索teddy bears、 black bears、 grizzly bears, 將下載的保存連接的文件分別命名爲urls_teddys.txt、 urls_black.txt、 urls_grizzly.txtdom

下載圖片

import numpy as np
from fastai.vision import *
from fastai.metrics import error_rate
### 創建目錄並下載圖片
path = Path('data/bears')
folders = ['teddys', 'black', 'grizzly']
files = 'urls_teddys.txt', 'urls_black.txt', 'urls_grizzly.txt'
for i,folder in enumerate(folders):
    dest = path/folder
    dest.mkdir(parents=True, exist_ok=True)
    download_images(files[i], dest, max_pics=200)
print(path.ls())
### 刪除不能被打開的圖片
for folder in folders:
    verify_images(path/folder, delete=True, max_size=500)

訓練模型

np.random.seed(42)
data = ImageDataBunch.from_folder(path, train=".", valid_pct=0.2, ds_tfms=get_transforms(), size=224, bs=64, num_workers=4).normalize(imagenet_stats)
print(data.classes)
learn = create_cnn(data, models.resnet34, metrics=error_rate)
learn.lr_find()
learn.recorder.plot() #左圖
learn.fit_one_cycle(4)
learn.save('stage-1')
learn.unfreeze()
learn.lr_find()
learn.recorder.plot() #右圖
learn.fit_one_cycle(2, max_lr=slice(3e-5,3e-4)) #若數據量較小,該步不必定有正效果
learn.save('stage-2')
learn.load('stage-1') #選擇stage-1
interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix()

img

根據訓練好的模型去除錯誤圖片

模型預測效果很差不必定是由於模型自己的問題,還多是因爲圖片自身的問題(例以下載了錯誤的圖片,圖片標籤有誤),須要進行檢查和處理ide

from fastai.widgets import *
### ds: 訓練圖片集, idxs: 具備最大損失的訓練圖片索引
ds, idxs = DatasetFormatter().from_toplosses(learn, n_imgs=200) #選出前200個具備最大損失的訓練圖片
ImageCleaner(ds, idxs, path) #手動處理,處理好的文件被存入path/cleaned.csv(該文件僅包含通過處理後的訓練圖片集,不包含驗證圖片)

可根據具體狀況對處理以後的數據從新進行訓練函數

保存模型並預測

learn.export() #將模型存入learn.path/export.pkl
learn = load_learner(path) #從path中讀取模型
img = open_image(path/'black'/'00000021.jpg') #以訓練集中的一個圖片爲例
pred_class,pred_idx,outputs = learn.predict(img) #預測圖片
print(pred_class) #輸出類別
print(outputs) #輸出每一個類的機率



Previous

GAN應用於半監督學習

Next

使用fastai進行圖像多標籤分類和圖像分割
相關文章
相關標籤/搜索