FastAI 2019课程学习笔记 lesson 2:自行获取数据并创建分类器
文章目錄
- 數(shù)據(jù)獲取
- google_images_download 的安裝和使用
- 掛載google 個(gè)人硬盤到Google colab中
- 刪除不能打開(kāi)文件
- 創(chuàng)建ImageDataBunch
- 訓(xùn)練模型
- 解釋模型
- 將模型投入生產(chǎn)
- 可能出故障的情況
- 學(xué)習(xí)率太高(Learning rate too high)
- 學(xué)習(xí)率太低(Learning rate too low)
- Too few epochs
- Too many epochs
數(shù)據(jù)獲取
數(shù)據(jù)集在深度學(xué)習(xí)模型的訓(xùn)練過(guò)程中有著重要的影響,本次課程教大家如何利用google的圖片搜索功能來(lái)創(chuàng)建簡(jiǎn)單的圖片數(shù)據(jù)集。
本人使用了Google colab作為學(xué)習(xí)fastai的平臺(tái),所以你需要科學(xué)上網(wǎng)。本人在實(shí)驗(yàn)的過(guò)程中發(fā)現(xiàn)fastai官方教程提供的獲取google image的json文件不好用,所以找了一個(gè)開(kāi)源的google image開(kāi)源庫(kù)來(lái)代替官方的圖片獲取方案。
google_images_download 的安裝和使用
通過(guò)下面代碼在Google colab中安裝google_images_download:
!pip install google_images_download
我們現(xiàn)在需要制作黑熊,棕熊,泰迪熊的數(shù)據(jù)集,希望最終的模型可以區(qū)分這三種熊,所以我們通過(guò)如下的代碼來(lái)從Google image上獲取這三種熊的圖片。
from google_images_download import google_images_download #importing the libraryresponse = google_images_download.googleimagesdownload() #class instantiationarguments = {"keywords":"black bear,grizzly bear,teddy bear","limit":100,"print_urls":True} #creating list of arguments
paths = response.download(arguments) #passing the arguments to the function
print(paths
在這段代碼中我們需要注意的是"limit":100,由于這個(gè)庫(kù)的問(wèn)題,在下載100張以內(nèi)圖片時(shí)候是不需要安裝selenium 庫(kù)和 chromedriver 擴(kuò)展的,但是差不多100張的圖片也足夠我們需要了。
下載的文件在google colab中一般放在/content/downloads/目錄下,為了方便下次我們對(duì)數(shù)據(jù)的使用,我們可以將這些數(shù)據(jù)永久保存在我們自己Google 硬盤之中
掛載google 個(gè)人硬盤到Google colab中
from google.colab import drive
drive.mount('/content/gdrive', force_remount=True)
root_dir = "/content/gdrive/My\ Drive/"
可以通過(guò)如下代碼實(shí)現(xiàn)掛載google硬盤到google colab中
然后我們可以通過(guò)如下代碼將下載的圖片文件拷貝到個(gè)人的文件夾中,后面的目標(biāo)文件夾大家可以自行更改:
!cp -r /content/downloads/* /content/gdrive/My\ Drive/pytorch/Fast_AI_learning/data/bears/
刪除不能打開(kāi)文件
通過(guò)以下的程序?qū)崿F(xiàn)刪除不能打開(kāi)的文件,當(dāng)然我們也可以自己去https://drive.google.com下去找到對(duì)應(yīng)的文件夾,看看是否存在圖片不能打開(kāi)的情況,如果存在則刪除這些圖片
path = Path("/content/gdrive/My Drive/pytorch/Fast_AI_learning/data/bears")
classes = ['black bear','grizzly bear','teddy bear']
for c in classes:print(c)verify_images(path/c, delete=True, max_size=500)
創(chuàng)建ImageDataBunch
與lesson 1類似,我們創(chuàng)建ImageDataBunch:
np.random.seed(42)
data = ImageDataBunch.from_folder(path, train=".", valid_pct=0.2,ds_tfms=get_transforms(), size=224, num_workers=4).normalize(imagenet_stats)
在我們?cè)趧?chuàng)建data bunch時(shí)候,如果不知道分離的驗(yàn)證集和訓(xùn)練集,就默認(rèn)當(dāng)前文件夾是訓(xùn)練集,但是我們應(yīng)該留出20%的數(shù)據(jù)作為驗(yàn)證集,所以我們自動(dòng)的、隨機(jī)的創(chuàng)建一個(gè)驗(yàn)證集。在我們隨機(jī)創(chuàng)建一個(gè)驗(yàn)證集時(shí)候,我們總是提前設(shè)置一個(gè)固定的隨機(jī)種子,這意味著每次我執(zhí)行這段代碼的時(shí)候都會(huì)得到同樣的驗(yàn)證集結(jié)果。
隨機(jī)性是一個(gè)非常重要的部分來(lái)找出穩(wěn)定的解,每次你運(yùn)行它的時(shí)候它都會(huì)起作用。但重要的是,你總是有相同的驗(yàn)證集,否則當(dāng)你正試圖決定這個(gè)超參數(shù)改變改善我的模型,但你有一組不同的數(shù)據(jù)測(cè)試,那么你不知道也許這組數(shù)據(jù)恰好是有點(diǎn)簡(jiǎn)單。
這就是為什么總是把隨機(jī)的種子放在這里。
通過(guò)下面代碼顯示出一部分圖像結(jié)果:
data.show_batch(rows=3, figsize=(7,8))
通過(guò)下面代碼顯示數(shù)據(jù)種類結(jié)果以及訓(xùn)練集和驗(yàn)證集的數(shù)量:
data.classes, data.c, len(data.train_ds), len(data.valid_ds)
得到:
(['black bear', 'grizzly bear', 'teddy bear'], 3, 204, 51)
訓(xùn)練模型
根據(jù)lesson 1的訓(xùn)練模型方式,我們通過(guò)resnet34模型來(lái)進(jìn)行訓(xùn)練:
learn = cnn_learner(data, models.resnet34, metrics=error_rate)
learn.fit_one_cycle(4)
得到如下的結(jié)果:
然后我們先保存當(dāng)前狀態(tài),然后通過(guò)運(yùn)行學(xué)習(xí)率尋找工具并繪制出學(xué)習(xí)率:
learn.save('stage-1')
learn.unfreeze()
learn.lr_find()
learn.recorder.plot()
最后得到這樣的圖像:
通過(guò)圖像我們發(fā)現(xiàn)在區(qū)間[1e-4, 1e-3]中間loss是下降最快的,所以我們通過(guò)下面的代碼進(jìn)一步的優(yōu)化模型:
learn.fit_one_cycle(2, max_lr=slice(3e-5,3e-4))
經(jīng)過(guò)我們到現(xiàn)在的努力,我們的錯(cuò)誤率維持在了1.9%,這已經(jīng)是一個(gè)相對(duì)來(lái)說(shuō)比較好的結(jié)果的了。我們通過(guò)google image創(chuàng)建了一個(gè)數(shù)據(jù)集,然后創(chuàng)建了一個(gè)分類器,最后我們得到了1.9%的錯(cuò)誤率,現(xiàn)在我們保存下這個(gè)狀態(tài)。
learn.save('stage-2')
解釋模型
learn.load('stage-2')
interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix()
繪制得到混淆矩陣如下:
我們發(fā)現(xiàn)其中有個(gè)黑熊被我們預(yù)測(cè)成了棕熊
將模型投入生產(chǎn)
首先將模型導(dǎo)出:
learn.export()
這會(huì)在目錄中創(chuàng)建一個(gè)名為export.pkl的文件,它包含了部署模型所需要的所有內(nèi)容(模型,權(quán)重以及一些元數(shù)據(jù))
我們可以選擇再cpu上執(zhí)行這個(gè)預(yù)測(cè)程序,當(dāng)我們的機(jī)器沒(méi)有gpu時(shí)候,這是自行發(fā)生的
defaults.device = torch.device('cpu')
我們可以選擇一張圖片:
img = open_image(path/'grizzly bear/2.grizzly_pam-hartman_0_epv0457.jpg')
img
我們?cè)诒WC路徑下包含的export.pkl,然后我們?cè)谏a(chǎn)環(huán)境中創(chuàng)建學(xué)習(xí)器:
learn = load_learner(path)
然后我們就可以進(jìn)行我們的預(yù)測(cè)工作了
pred_class, pred_idx, outputs = learn.predict(img)
pred_class
我們得到如下結(jié)果,預(yù)測(cè)表明這張圖片表示的是棕熊。
Category grizzly bear
可能出故障的情況
在大多數(shù)情況之下,我們按照官方指定的教程去運(yùn)行程序是沒(méi)有產(chǎn)生正確的結(jié)果的,所以我們來(lái)談?wù)劗?dāng)我們遇到問(wèn)題時(shí)候會(huì)發(fā)生什么?這就是我們?yōu)槭裁撮_(kāi)始學(xué)習(xí)一些理論的原因,因?yàn)闉榱朔奖阄覀兝斫鉃槭裁磿?huì)有這些問(wèn)題以及我們?nèi)绾谓鉀Q這些問(wèn)題。
首先我們先看下一些典型的問(wèn)題案例,如下:
- 你的學(xué)習(xí)率太高或者太低
- 你的epoch的數(shù)量太多或者太少
所以我們來(lái)學(xué)習(xí)下這意味著什么以及為什么他們發(fā)揮重要的作用。
學(xué)習(xí)率太高(Learning rate too high)
所以讓我們用我們的泰迪熊探測(cè)器來(lái)提高我們的學(xué)習(xí)速度。默認(rèn)的學(xué)習(xí)率是0.003,這在大多數(shù)情況下是可行的。如果我們?cè)囍褜W(xué)習(xí)率設(shè)為0.5,這是非常大的,會(huì)發(fā)生什么呢?我們的驗(yàn)證損失相當(dāng)大,它通常是1以下的數(shù)。如果你看到你的驗(yàn)證損失,在我們知道驗(yàn)證損失是什么之前,只要出現(xiàn)這樣的情況,證明你的learning rate就太高了,你只需要知道這些讓它更低就可以了。不管你經(jīng)歷了多少個(gè)epoch,如果發(fā)生這種情況,就沒(méi)有辦法挽回了,你必須回去重新建立你的神經(jīng)網(wǎng)絡(luò),從零開(kāi)始適應(yīng)一個(gè)較低的學(xué)習(xí)率(learning rate)。
learn = create_cnn(data, models.resnet34, metrics=error_rate)
learn.fit_one_cycle(1, max_lr=0.5)
學(xué)習(xí)率太低(Learning rate too low)
如果我們傳入的最大的學(xué)習(xí)率不是 0.003而是0.00001呢?
learn = create_cnn(data, models.resnet34, metrics=error_rate)
learn.fit_one_cycle(5, max_lr=1e-5)
雖然使用很低的學(xué)習(xí)率,我們的錯(cuò)誤率有所下降但是下降的速度非常的緩慢。
可以通過(guò)使用learn.recorder.plot_losses來(lái)繪制出驗(yàn)證和訓(xùn)練損失,可以看見(jiàn)他們?cè)诼南陆怠?br />
如果你看見(jiàn)這種情況,就證明你的學(xué)習(xí)速率太小了,所以你可以嘗試10倍,100倍的放大學(xué)習(xí)率然后再次進(jìn)行訓(xùn)練。**還有一個(gè)需要注意的是如果你的學(xué)習(xí)率太小了,那么你的訓(xùn)練損失會(huì)高于你的驗(yàn)證損失,你永遠(yuǎn)不會(huì)希望這樣的情況發(fā)生在你的訓(xùn)練模型中的。**這就意味著你沒(méi)訓(xùn)練夠,意味著你的學(xué)習(xí)率太低了或者你的epoch的數(shù)量太小了。所以如果你的訓(xùn)練模型發(fā)生這樣的情況,使用更高的學(xué)習(xí)率再多訓(xùn)練幾次。
Too few epochs
learn = cnn_learner(data, models.resnet34, metrics=error_rate)
learn.fit_one_cycle(1)
如果使用一個(gè)epoch,并且錯(cuò)誤率在7%,這是低于隨機(jī)預(yù)測(cè)的,但是看看訓(xùn)練損失和驗(yàn)證損失之間的差別,我們發(fā)現(xiàn)訓(xùn)練損失是遠(yuǎn)遠(yuǎn)高于驗(yàn)證損失的,所以太少的epoch和太小的learning rate的結(jié)果是相似的。所以你可以嘗試更多的epoch,如果結(jié)果還是一樣,那么你可以嘗試更高的學(xué)習(xí)率。如果嘗試一個(gè)更高的學(xué)習(xí)率,損失會(huì)達(dá)到10億,然后你再把學(xué)習(xí)率設(shè)為原來(lái)的值,再增加一個(gè)epoch,這就是平衡,也就是調(diào)參,99%的時(shí)候你只關(guān)心這些,只有1/20的情況下,默認(rèn)值是無(wú)效的。
Too many epochs
太多的epoch會(huì)造成過(guò)擬合。當(dāng)你訓(xùn)練你的模型時(shí)間太長(zhǎng),模型可能就會(huì)只識(shí)別特定的泰迪熊而不是一般的泰迪熊了。盡管你可能聽(tīng)過(guò)在深度學(xué)習(xí)中很難產(chǎn)生過(guò)擬合,所以現(xiàn)在為大家展示一個(gè)過(guò)擬合的案例,并且關(guān)閉一些其他選項(xiàng),我關(guān)閉了數(shù)據(jù)增強(qiáng),dropout,以及weight decay(權(quán)值衰減),我盡可能的讓模型過(guò)擬合。我以一個(gè)很小的學(xué)習(xí)率訓(xùn)練模型,并且訓(xùn)練模型很長(zhǎng)時(shí)間,我可能會(huì)得到一個(gè)過(guò)擬合的模型。
唯一能告訴你過(guò)擬合的是錯(cuò)誤率短暫的提升,然后開(kāi)始變得更差。你可能會(huì)聽(tīng)見(jiàn)很多人,甚至那些聲稱了解機(jī)器學(xué)習(xí)的人告訴你說(shuō)如果你的training loss 比validation loss低,那么就是過(guò)擬合,但是這其實(shí)并不是完全正確。
任何一個(gè)正確的訓(xùn)練模型的training loss都比validation loss低
這并不是過(guò)擬合的跡象,這并不意味著你做錯(cuò)了什么,這恰恰證明你做的是對(duì)的。你過(guò)擬合的標(biāo)志是錯(cuò)誤率開(kāi)始變得更糟,這才是你應(yīng)該關(guān)心的。你希望你的模型擁有更低的錯(cuò)誤率,所以只要你在訓(xùn)練的時(shí)候,你的模型的錯(cuò)誤在改善,那么你就沒(méi)有過(guò)擬合。
np.random.seed(42)
data = ImageDataBunch.from_folder(path, train=".", valid_pct=0.9, bs=26, ds_tfms=get_transforms(do_flip=False, max_rotate=0, max_zoom=1, max_lighting=0, max_warp=0),size=224, num_workers=4).normalize(imagenet_stats)
learn = cnn_learner(data, models.resnet50, metrics=error_rate, ps=0, wd=0)
learn.unfreeze()
learn.fit_one_cycle(40, slice(1e-6,1e-4))
結(jié)果如下:
epoch train_loss valid_loss error_rate time
0 1.281925 1.141897 0.694323 00:07
1 1.346654 1.129421 0.694323 00:03
2 1.340803 1.107458 0.681223 00:03
3 1.355779 1.085071 0.646288 00:03
4 1.295381 1.050753 0.589520 00:03
5 1.224308 1.000656 0.497817 00:03
6 1.159185 0.938931 0.397380 00:03
7 1.088768 0.867412 0.310044 00:03
8 1.008123 0.788017 0.231441 00:03
9 0.938289 0.708754 0.157205 00:03
10 0.864608 0.634222 0.122271 00:03
11 0.793969 0.566193 0.096070 00:03
12 0.733825 0.508754 0.082969 00:03
13 0.680985 0.458568 0.069869 00:03
14 0.632074 0.418085 0.061135 00:03
15 0.589376 0.385271 0.056769 00:03
16 0.551403 0.356482 0.056769 00:03
17 0.516843 0.330840 0.052402 00:03
18 0.485706 0.311566 0.052402 00:03
19 0.457809 0.295450 0.052402 00:03
20 0.432226 0.281761 0.052402 00:03
21 0.408979 0.269984 0.052402 00:03
22 0.387673 0.259906 0.048035 00:03
23 0.368162 0.251425 0.039301 00:03
24 0.350114 0.245693 0.034934 00:03
25 0.333477 0.238942 0.034934 00:03
26 0.318159 0.232099 0.030568 00:03
27 0.303887 0.226424 0.030568 00:03
28 0.290654 0.222446 0.030568 00:03
29 0.278258 0.218786 0.034934 00:03
30 0.266660 0.215658 0.030568 00:03
31 0.255738 0.214105 0.030568 00:03
32 0.245596 0.209824 0.030568 00:03
33 0.236173 0.205443 0.034934 00:03
34 0.227359 0.204399 0.030568 00:03
35 0.218893 0.202812 0.030568 00:03
36 0.210922 0.202212 0.039301 00:03
37 0.203402 0.201633 0.039301 00:03
38 0.196221 0.201402 0.039301 00:03
39 0.189409 0.201313 0.039301 00:03
綜上是在訓(xùn)練深度模型時(shí)候容易出錯(cuò)的四點(diǎn)
總結(jié)
以上是生活随笔為你收集整理的FastAI 2019课程学习笔记 lesson 2:自行获取数据并创建分类器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: NLP相关论文上新-2019
- 下一篇: 通过聚合数据API获取微信精选文章