新手必讀!如何入手卷積神經網絡
卷積神經網絡可以算是深度神經網絡中很流行的網絡了。本文從基礎入手,介紹了卷積網絡的基本原理以及相關的其它技術,并利用卷積網絡做了一個簡單項目作為示例參考。想入手 CNN 的朋友不可錯過~
首先,我們先看看下面這張照片:
圖源:Pix2PixHD
這不是一張真實的照片,你可以新建一個窗口來打開它,放大看看,可以看到馬賽克。
實際上,這張照片是由 AI 生成的,是不是看起來很真實?
從 Alex Krizhevsky 及其朋友通過 ImageNet 公布這項技術至今,不過才七年。ImageNet 是一個大規模圖像識別競賽,每年都會舉辦,識別種類達 1000 多種,從阿拉斯加雪橇犬到廁紙應用盡有。之后,他們又創建了 AlexNet,獲得了 ImageNet 競賽冠軍,遠超第二名。
這項技術就是卷積神經網絡。它是深度神經網絡的一個分支,處理圖像的效果格外好。
圖源:ImageNet
上圖是幾年來贏得 ImageNet 挑戰賽的軟件產生的誤差率??梢园l現,2016 年誤差率降到了 5%,已經超越人類水平。
深度學習的引入與其說是改變規則,不如說是在打破規則。
卷積神經網絡架構
那么問題來了,卷積神經網絡到底是怎么運作的呢?
卷積神經網絡之所以優于其它深度神經網絡是由于它特殊的操作。相比一次只計算圖像中的單個像素,CNN 將多個像素的信息組合在一起(比如上圖中計算了 3*3 的像素),因此能夠理解時間模式。
另外,CNN 可以「看到」一組像素組合成一條直線或者曲線。由于深度神經網絡通常都是多層卷積的堆疊,通過上一層得到了直線或者曲線后,下一層不再組合像素,而是將線組合成形狀,一層一層進行下去,直到形成完整的圖片。
來自 Mynepalli 的深度卷積神經網絡圖
要想深入理解 CNN,你需要學習很多基礎知識,比如什么是核,什么是池化層。但是現在有很多優秀的開源項目,你可以直接在他們的基礎上進行研究并加以利用。
這就引入了另一門技術——遷移學習。
遷移學習
遷移學習使用訓練好的深度學習模型來學習特定的任務。
舉個栗子,比如你在火車調度公司工作,你們想在不增加勞動力的情況下,預測火車是否晚點。
你完全可以利用 ImageNet 上的卷積神經網絡模型,比如說 2015 年的冠軍 ResNet。用火車圖片重新訓練網絡,相信我,結果不會讓你失望的。
遷移學習主要有兩大優勢:
- 相比于從頭開始訓練,只需要少量圖片就可以得到很好的效果。ImageNet 競賽提供了一百萬張圖片用于訓練。使用遷移學習,你只需要 1000 甚至 100 張圖片就可以訓練出一個很好的模型,因為你的預訓練模型已經在一百萬張圖片上訓練過了。
- 較少的訓練時間就能實現良好的性能。為了得到和 ImageNet 模型同樣好的效果,你可能需要訓練數天,這還不包括模型效果不好時對其進行調整所需的時間。然而使用遷移學習,你可能只需要幾個小時甚至幾分鐘就可以完成特定任務的訓練,大大節省了時間。
圖像分類到圖像生成
有了遷移學習之后大家產生了許多有趣的想法。既然我們可以處理圖像、識別圖像中的信息,那我們為什么不自己生成圖像呢?
因吹斯汀!
生成對抗網絡由此應運而生。
朱俊彥等人提出的 CycleGAN
給定某些輸入,這項技術可以生成對應的圖片。
如上圖所示,CycleGAN 可以根據一幅畫生成對應的真實照片,也可以根據草圖生成背包的照片,甚至可以進行超分辨率重建。
超分辨率生成對抗網絡
很神奇,對嗎?
當然,你可以學習構建這些網絡。但如何開始呢?
卷積神經網絡教程
首先你要知道,入門很簡單,但掌握就不是那么容易了。
我們先從最基礎的開始。
圖源:Thomas Verbruggen on Unsplash
航拍仙人掌識別
這是 Kaggle 上的學習項目,你的任務是識別航拍圖像中是否有柱狀仙人掌。
是不是看起來非常簡單?
Kaggle 提供了 17500 張圖片,其中 4000 張未標注的作為測試集。如果你的模型能夠正確標注 4000 張圖片,就會得滿分 1 或者 100%。
我找了好久,終于找到下面這個非常適合新手入門的項目。
仙人掌
這張圖像與上面的類似。它大小為 32*32,其中包含或者不包含柱狀仙人掌。因為是航拍圖片所以包含各種不同角度。
所以你需要什么呢?
用 python 構建卷積神經網絡
是的,Python——深度學習領域最受歡迎的語言。至于深度學習框架,你有很多種選擇,可以自己逐一嘗試:
- Tensorflow,最受歡迎的深度學習框架,由谷歌工程師構建,并且擁有最多的貢獻者和粉絲。由于社群比較龐大,當你有問題時可以很容易找到解決方案。它們的高階 API keras,在入門者中很受歡迎。
- Pytorch,我最喜歡的深度學習框架。純 Python 實現,因此繼承了 Python 的各種優缺點。Python 開發者會很容易上手。它還有 FastAI 庫提供抽象,就像 Keras 之于 Tensorflow。
- MXNet,Apache 開發的深度學習框架。
- Theano,Tensorflow 的前身。
- CNTK,微軟開發的深度學習框架。
這篇教程中使用的就是我最喜歡的 Pytorch,并且使用 FastAI。
開始之前,你需要安裝 Python。瀏覽 Python 的官網,下載你需要的版本。需要確保的是一定要用 3.6+的版本,否則將不支持你需要用到的一些庫。
現在,打開你的命令行或者終端,安裝下面這些庫:
- pip install numpy
- pip install pandas
- pip install jupyter
Numpy 用于存儲輸入圖像,pandas 用于處理 CSV 文件,Jupyter notebook 用于編碼。
然后,去 Pytorch 官網下載需要的版本,并且如果你想加速訓練的話,要安裝 CUDA 版本的 Pytorch,并且版本至少是 1.0 以上。
上面這些搞定之后,安裝 torchvision 和 FastAI:
- pip install torchvision
- pip install fastai
運行 Jupyter notebook 命令,打開 Jupyter,它將打開一個瀏覽器窗口。
這樣所需環境就配置好了,我們開始吧。
準備數據
導入需要的代碼:
- import numpy as np
- import pandas as pd
- from pathlib import Path
- from fastai import *
- from fastai.vision import *
- import torch
- %matplotlib inline
Numpy 和 Pandas 基本是做什么任務都會需要的。FastAI 和 Torch 是你的深度學習庫。Matplotlib Inline 用于顯示圖表。
下面就可以從 Kaggle 競賽官網上下載數據了。
解壓 zip 文件,并放置于 Jupyter notebook 文件夾中。
假設你的 notebook 被命名為 Cacti。你的文件夾結構會是下面這樣:
Train 文件夾里包含所有的訓練圖片。
Test 文件夾是用于提交的測試圖片。
Train CSV 文檔里包含訓練數據的信息,將圖片名與列 has_cactus 映射,如果該列有 cactus,則值為 1,否則為 0。
Sample Submission CSV 中是提交所需的格式。文件名和 Test 文件夾中的圖片相對應。
- train_df = pd.read_csv("train.csv")
將 Train CSV 文檔加載到數據幀中。
- data_folder = Path(".")
- train_images = ImageList.from_df(train_df, path=data_folder, folder='train')
利用 ImageList from_df 方法創建加載生成器,以便將 train_df 數據幀和 train 文件夾中的圖像進行映射。
數據增強
這是一種根據現有數據創建更多數據的技術。一張貓的圖片水平翻轉之后仍然是貓的圖片。但通過這樣做,你可以把你的數據擴增至兩倍、四倍甚至 16 倍。
如果你數據量比較少,可以嘗試這種方法。
- transformations = get_transforms(do_flip=True, flip_vert=True, max_rotate=10.0, max_zoom=1.1, max_lighting=0.2, max_warp=0.2, p_affine=0.75, p_lighting=0.75)
FastAI 提供了 get_transform 函數來做這些事情。你可以水平翻轉、垂直翻轉、旋轉、放大、提高光度/亮度或者加仿射變換來增強數據。
你可以用我上邊提供的參數試一下圖片會變成什么樣?;蛘吣憧梢栽敿氶喿x官方文檔。
然后,對你的圖像序列做上述預處理。
- train_imgtrain_img = train_img.transform(transformations, size=128)
參數大小將用于放大或縮小輸入,以匹配你將使用的神經網絡。我所用的網絡是 DenseNet——ImageNet 2017 最佳論文獎的成果,它要輸入的圖像大小為 128*128。
準備訓練
讀取數據之后,就到了深度學習最關鍵的一步——訓練。這個過程也是深度學習中學習的由來。網絡從你的數據中學習并且依據學習到的結果調整自身參數,直到在數據上得到比較好的效果。
- test_df = pd.read_csv("sample_submission.csv")
- test_img = ImageList.from_df(test_df, path=data_folder, folder='test')
- train_imgtrain_img = train_img
- .split_by_rand_pct(0.01)
- .label_from_df()
- .add_test(test_img)
- .databunch(path='.', bs=64, device=torch.device('cuda:0'))
- .normalize(imagenet_stats)
在訓練這一步,你需要把訓練數據分出一小部分做驗證集。你不可以用這部分數據來訓練,因為它們只是用來做驗證的。當你的卷積神經網絡在驗證集上效果較好時,很有可能在測試集上也可以提交一個比較好的結果。
FastAI 提供了 split_by_rand_pct 函數,可以很方便地進行以上操作。
databunch 函數可以進行批處理。由于 GPU 內存限制,我的批大小為 64。如果你沒有 GPU,忽略 device 參數這一項。
之后,由于你使用的是預訓練網絡,用 normalize 函數來進行圖像歸一化。imagenet_stats 函數會根據 ImageNet 預訓練模型的訓練方式歸一化輸入圖像。
把測試數據也加入訓練數據列表里,可以使稍后預測更容易,免得再進行一次預處理。記住,這些圖像不能用于訓練,也不可以用來做驗證。這樣做只是為了確保訓練圖片和測試圖片采用了完全相同的預處理方式。
- learn = cnn_learner(train_img, models.densenet161, metrics=[error_rate, accuracy])
現在數據準備工作已經做完了?,F在,用 cnn_leaner 創建一個訓練器。如上所述,我是采用 DenseNet 作為預訓練網絡的,當然你也可以選擇 TorchVision 提供的其他網絡。
單周期技術
現在你可以開始訓練了。但是,包括卷積神經網絡在內,深度學習訓練的一大難題就是,如何選擇正確的學習率。學習率決定了進行梯度下降時更新參數減小誤差的幅度。
如上圖所示,大一些的學習率使訓練過程更快,但更容易錯過誤差邊界,甚至會跳出可控范圍,無法收斂。然而,當使用稍微小一點的學習率時,訓練過程會更慢,但不會發散。
所以,選擇合適的學習率非常重要。我們要找到的是足夠大卻又不會使訓練發散的恰當學習率。
但說起來容易做起來難。
所以,一個叫 Leslie Smith 的人提出了單周期策略。
簡單來說,就是先暴力查找幾個不同的學習率,然后選擇一個最接近最小誤差但還有進步空間的。代碼如下:
- learn.lr_find()
- learn.recorder.plot()
你會得到如下輸出:
誤差最小值在 10^-1 位置,所以我們可以使用略小于這個值的學習率,比如 3*10^-2。
- lr = 3e-02
- learn.fit_one_cycle(5, slice(lr))
訓練幾個 epoch(這里我選擇 5,不太大也不太小),然后看看結果。
等等,怎么回事?!
驗證集準確率達到了 100%!訓練過程實際上是非常高效的,只用了六分鐘時間。多么幸運!實際上,你可能需要數次迭代才能找到合適的算法。
我等不及要提交了!哈哈。下面讓我們預測并提交測試集結果吧。
- preds,_ = learn.get_preds(ds_type=DatasetType.Test) test_df.has_cactus = preds.numpy()[:, 0]
由于之前已經把測試圖片放入訓練圖片列表中了,因此不需要再對測試圖片做預處理。
- test_df.to_csv('submission.csv', index=False)
上面這行代碼會創建一個 CSV 文件,其中包含 4000 張測試圖像的名稱以及每張圖像是否包含仙人掌的 label。
當我嘗試提交時,我發現需要通過 Kaggle 核來提交 CSV,這是我之前沒有注意到的。
圖源:Kaggle
幸運的是,核的操作和 Jupyter notebook 非常相似。你完全可以把 notebook 里創建的東西復制粘貼過來,然后提交。
然后,Duang~完成了!
天吶!得分竟然為 0.9999,這已經非常好了。當然如果第一次嘗試就得到這么好的分數,應該還有進步的空間。
所以,我調整了網絡結構,又嘗試了一次。
得分為 1!我做到了!!所以你也可以,實際上并不是那么困難。
(另外,這個排名是 4 月 13 號的,我的排名現在很有可能已經下降了…)
我學到了什么
這個項目很簡單,你在解決任務的過程中也不會遇到什么奇怪的挑戰,所以這個項目非常適合入門。
并且由于已經有很多人得滿分了,我覺得主辦方應該另外創建一個用于提交的測試集,難度最好更高一點。
不管怎么樣,從這個項目開始基本沒有什么困難。你可以馬上嘗試并且獲得高分。
圖源:Mario Mrad on Unsplash
卷積神經網絡對各種不同的任務都很有效,不論是圖像識別還是圖像生成。現在分析圖像并不像以前那么難。當然,如果你嘗試的話也可以做到。
所以,選擇一個好的卷積神經網絡項目,準備好高質量的數據,開始吧!
原文鏈接:
https://medium.freecodecamp.org/everything-you-need-to-know-to-master-convolutional-neural-networks-ef98ca3c7655
【本文是51CTO專欄機構“機器之心”的原創譯文,微信公眾號“機器之心( id: almosthuman2014)”】