當前位置:
首頁 > 新聞 > 如何入手卷積神經網路

如何入手卷積神經網路

卷積神經網路可以算是深度神經網路中很流行的網路了。本文從基礎入手,介紹了卷積網路的基本原理以及相關的其它技術,並利用卷積網路做了一個簡單項目作為示例參考。想入手 CNN 的朋友不可錯過~

如何入手卷積神經網路

首先,我們先看看下面這張照片:

如何入手卷積神經網路

圖源:Pix2PixHD

這不是一張真實的照片,你可以新建一個窗口來打開它,放大看看,可以看到馬賽克。

實際上,這張照片是由 AI 生成的,是不是看起來很真實?

從 Alex Krizhevsky 及其朋友通過 ImageNet 公布這項技術至今,不過才七年。ImageNet 是一個大規模圖像識別競賽,每年都會舉辦,識別種類達 1000 多種,從阿拉斯加雪橇犬到廁紙應用盡有。之後,他們又創建了 AlexNet,獲得了 ImageNet 競賽冠軍,遠超第二名。

這項技術就是卷積神經網路。它是深度神經網路的一個分支,處理圖像的效果格外好。

如何入手卷積神經網路

圖源:ImageNet

上圖是幾年來贏得 ImageNet 挑戰賽的軟體產生的誤差率。可以發現,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——深度學習領域最受歡迎的語言。至於深度學習框架,你有很多種選擇,可以自己逐一嘗試:

  1. Tensorflow,最受歡迎的深度學習框架,由谷歌工程師構建,並且擁有最多的貢獻者和粉絲。由於社群比較龐大,當你有問題時可以很容易找到解決方案。它們的高階 API keras,在入門者中很受歡迎。
  2. Pytorch,我最喜歡的深度學習框架。純 Python 實現,因此繼承了 Python 的各種優缺點。Python 開發者會很容易上手。它還有 FastAI 庫提供抽象,就像 Keras 之於 Tensorflow。
  3. MXNet,Apache 開發的深度學習框架。
  4. Theano,Tensorflow 的前身。
  5. 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 函數來做這些事情。你可以水平翻轉、垂直翻轉、旋轉、放大、提高光度/亮度或者加仿射變換來增強數據。

你可以用我上邊提供的參數試一下圖片會變成什麼樣。或者你可以詳細閱讀官方文檔。

然後,對你的圖像序列做上述預處理。

train_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_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])

現在數據準備工作已經做完了。現在,用 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

卷積神經網路對各種不同的任務都很有效,不論是圖像識別還是圖像生成。現在分析圖像並不像以前那麼難。當然,如果你嘗試的話也可以做到。

所以,選擇一個好的卷積神經網路項目,準備好高質量的數據,開始吧!

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 機器之心 的精彩文章:

推理速度升5.1倍參數減少88%:谷歌提出新型卷積網路EfficientNet
結合符號主義和DL:DeepMind提出端到端神經網路架構PrediNet

TAG:機器之心 |