keras實戰項目——

keras實戰項目——

我們可以簡單的將深度神經網路的模塊,分成以下的三個部分,即深度神經網路上游的基於生成器的 輸入模塊,深度神經網路本身,以及深度神經網路下游基於批量梯度下降演算法的 凸優化模塊:

批量輸入模塊

各種深度學習零件搭建的深度神經網路

凸優化模塊

其中,搭建深度神經網路的零件又可以分成以下類別:

各種深度學習零件搭建的深度神經網路

需要強調一下,這些層與之前一樣,都 同時包括了正向傳播、反向傳播兩條通路。我們這裡只介紹比較好理解的正向傳播過程,基於其導數的反向過程同樣也是存在的,其代碼已經包括在 Tensorflow 的框架中對應的模塊里,可以直接使用。

接下來的部分,我們將首先介紹這些深度神經網路的零件,然後再分別介紹上游的批量輸入模塊,以及下游的凸優化模塊。

1.深度神經網路的基本零件

1.1 常用層:

1.1.1. Dense

Dense 層,就是我們上一篇文章里提到的 Linear 層,即 y=wx+b ,計算乘法以及加法。

1.1.2. Activation

Activation 層在我們上一篇文章中,同樣出現過,即 Tanh層以及Sigmoid層,他們都是 Activation 層的一種。當然 Activation 不止有這兩種形式,比如有:

這其中 relu 層可能是深度學習時代最重要的一種激發函數,在2011年首次被提出。由公式可見,relu 相比早期的 tanh 與 sigmoid函數, relu 有兩個重要的特點,其一是在較小處都是0(sigmoid,relu)或者-5(tanh),但是較大值relu函數沒有取值上限。其次是relu層在0除不可導,是一個非線性的函數:

即 y=x*(x>0)

對其求導,其結果是:

1.1.3. Dropout

Dropout 層,指的是在訓練過程中,每次更新參數時將會隨機斷開一定百分比(rate)的輸入神經元,這種方式可以用於防止過擬合。

1.1.4. Flatten

Flatten 層,指的是將高維的張量(Tensor, 如二維的矩陣、三維的3D矩陣等)變成一個一維張量(向量)。Flatten 層通常位於連接深度神經網路的 卷積層部分 以及 全連接層部分。

1.2 卷積層

提到卷積層,就必須講一下卷積神經網路。我們在第一講的最後部分提高深度學習模型預測的準確性部分,提了一句 「使用更複雜的深度學習網路,在圖片中挖出數以百萬計的特徵」。這種「更複雜的神經網路」,指的就是卷積神經網路。卷積神經網路相比之前基於 Dense 層建立的神經網路,有所區別之處在於,卷積神經網路可以使用更少的參數,對局部特徵有更好的理解。

1.2.1. Conv2D

我們這裡以2D 的卷積神經網路為例,來逐一介紹卷積神經網路中的重要函數。比如我們使用一個形狀如下的卷積核:

掃描這樣一個二維矩陣,比如一張圖片:

其過程與結果會是這樣:

當然,這裡很重要的一點,就是正如我們上一講提到的, Linear 函數的 w, b兩個參數都是變數,會在不斷的訓練中,不斷學習更新。卷積神經網路中,卷積核其實也是一個變數。這裡的

可能只是初始值,也可能是某一次迭代時選用的值。隨著模型的不斷訓練,將會不斷的更新成其他值,結果也將會是一個不規則的形狀。清楚了其原理,卷積神經網路還需要再理解幾個輸入參數:

Conv2D(filters, kernel_size, strides=(1, 1), padding=valid, ...)

其中:

filters 指的是輸出的卷積層的層數。如上面的動圖,只輸出了一個卷積層,filters = 1,而實際運用過程中,一次會輸出很多卷積層。

kernel_size 指的是卷積層的大小,是一個 二維數組,分別代表卷積層有幾行、幾列。

strides 指的是卷積核在輸入層掃描時,在 x,y 兩個方向,每間隔多長掃執行一次掃描。

padding 這裡指的是是否掃描邊緣。如果是 valid,則僅僅掃描已知的矩陣,即忽略邊緣。而如果是 same,則將根據情況在邊緣補上0,並且掃描邊緣,使得輸出的大小等於 input_size / strides。

1.2.2. Cropping2D

這裡 Cropping2D 就比較好理解了,就是特地選取輸入圖像的某一個固定的小部分。比如車載攝像頭檢測路面的馬路線時,攝像頭上半部分拍到的天空就可以被 Cropping2D函數直接切掉忽略不計。

1.2.3. ZeroPadding2D

1.2.1部分提到輸入參數時,提到 padding參數如果是same,掃描圖像邊緣時會補上0,確保輸出數量等於 input / strides。這裡 ZeroPadding2D 的作用,就是在圖像外層邊緣補上幾層0。如下圖,就是對原本 32x32x3 的圖片進行 ZeroPadding2D(padding=(2, 2)) 操作後的結果:

1.3. 池化層

1.3.1. MaxPooling2D

可能大家在上一部分會意識到一點,就是通過與一個相同的、大小為11x11的卷積核做卷積操作,每次移動步長為1,則相鄰的結果會非常接近,正是由於結果接近,有很多信息是冗餘的。

因此,MaxPooling 就是一種減少模型冗餘程度的方法。以 2x 2 MaxPooling 為例。圖中如果是一個 4x4 的輸入矩陣,則這個 4x4 的矩陣,會被分割成由兩行、兩列組成的 2x2 子矩陣,然後每個 2x2 子矩陣取一個最大值作為代表,由此得到一個兩行、兩列的結果:

1.3.2. AveragePooling2D

AveragePooling 與 MaxPooling 類似,不同的是一個取最大值,一個是平均值。如果上圖的 MaxPooling 換成 AveragePooling2D,結果會是:

1.4.正則化層

除了之前提到的 Dropout 策略,以及用 GlobalAveragePooling取代全連接層的策略,還有一種方法可以降低網路的過擬合,就是正則化,這裡著重介紹下 BatchNormalization。

1.4.1. BatchNormalization

BatchNormalization 確實適合降低過擬合,但他提出的本意,是為了加速神經網路訓練的收斂速度。比如我們進行最優值搜索時,我們不清楚最優值位於哪裡,可能是上千、上萬,也可能是個負數。這種不確定性,會造成搜索時間的浪費。

BatchNormalization就是一種將需要進行最優值搜索數據,轉換成標準正態分布,這樣optimizer就可以加速優化:

輸入:一批input 數據: B

期望輸出: β,γ

2.深度神經網路的上下游結構

深度神經網路的參數大小動輒幾十M、上百M,如何合理訓練這些參數是個大問題。這就需要在這個網路的上下游,合理處理這個問題。

海量參數背後的意義是,深度神經網路可以獲取海量的特徵。第一講中提到過,深度學習是脫胎於傳統機器學習的,兩者之間的區別,就是深度學習可以在圖像處理中,自動進行特徵工程,如我們第一講所言:

想讓計算機幫忙挖掘、標註這些更多的特徵,這就離不開 更優化的模型 了。事實上,這幾年深度學習領域的新進展,就是以這個想法為基礎產生的。我們可以使用更複雜的深度學習網路,在圖片中挖出數以百萬計的特徵。

這時候,問題也就來了。機器學習過程中,是需要一個輸入文件的。這個輸入文件的行、列,分別指代樣本名稱以及特徵名稱。如果是進行百萬張圖片的分類,每個圖片都有數以百萬計的特徵,我們將拿到一個 百萬樣本 x 百萬特徵 的巨型矩陣。傳統的機器學習方法拿到這個矩陣時,受限於計算機內存大小的限制,通常是無從下手的。也就是說,傳統機器學習方法,除了在多數情況下不會自動產生這麼多的特徵以外,模型的訓練也會是一個大問題。

深度學習演算法為了實現對這一量級數據的計算,做了以下演算法以及工程方面的創新:

將全部所有數據按照樣本拆分成若干批次,每個批次大小通常在十幾個到100多個樣本之間。(詳見下文 輸入模塊)

將產生的批次逐一參與訓練,更新參數。(詳見下文 凸優化模塊)

使用 GPU 等計算卡代替 CPU,加速並行計算速度。

這就有點《愚公移山》的意思了。我們可以把訓練深度神經網路的訓練任務,想像成是搬走一座大山。成語故事中,愚公的辦法是既然沒有辦法直接把山搬走,那就子子孫孫,每人每天搬幾筐土走,山就會越來越矮,總有一天可以搬完——這種任務分解方式就如同深度學習演算法的分批訓練方式。同時,隨著科技進步,可能搬著搬著就用翻斗車甚至是高達來代替背筐,就相當於是用 GPU 等高並行計算卡代替了 CPU。

於是,我們這裡將主要提到的上游輸入模塊,以及下游凸優化模塊,實際上就是在說如何使用愚公移山的策略,用 少量多次 的方法,去「搬」深度神經網路背後大規模計算量這座大山。

2.2. 輸入模塊

這一部分實際是在說,當我們有成千上萬的圖片,存在硬碟中時,如何實現一個函數,每調用一次,就會讀取指定張數的圖片(以n=32為例),將其轉化成矩陣,返回輸出。

有 Python 基礎的人可能意識到了,這裡可能是使用了 Python 的 生成器 特性。其具體作用如廖雪峰博客所言:

創建一個包含100萬個元素的 list,不僅佔用很大的存儲空間,如果我們僅僅需要訪問前面幾個元素,那後面絕大多數元素佔用的空間都白白浪費了。 所以,如果 list 元素可以按照某種演算法推算出來,那我們是否可以在循環的過程中不斷推算出後續的元素呢?這樣就不必創建完整的list,從而節省大量的空間。在Python中,這種一邊循環一邊計算的機制,稱為生成器:generator。

其關鍵的寫法,是把傳統函數的 return 換成 yield:

next(generator)

即可一次返回 32 張圖像以及對應的標註信息。

當然,keras 同樣提供了這一模塊,ImageDataGenerator,並且還是加強版,可以對圖片進行 增強處理(data argument)(如旋轉、反轉、白化、截取等)。圖片的增強處理在樣本數量不多時增加樣本量——因為如果圖中是一隻貓,旋轉、反轉、顏色調整之後,這張圖片可能會不太相同,但它仍然是一隻貓。

datagen = ImageDataGenerator( featurewise_center=False, samplewise_center=False, featurewise_std_normalization=False, samplewise_std_normalization=False, zca_whitening=False, width_shift_range=0.1, height_shift_range=0.1, horizontal_flip=True, vertical_flip=False)# compute quantities required for featurewise normalizationdatagen.fit(X_train)

2.3 凸優化模塊

這一部分談的是,如何使用基於批量梯度下降演算法的凸優化模塊,優化模型參數。

前面提到,深度學習的「梯度下降」計算,可以理解成搬走一座大山,而「批量梯度下降」,則是一群人拿著土筐,一點一點把山上的土給搬下山。那麼這一點具體應該如何實現呢?其實在第二講,我們就實現了一個隨機批量梯度下降(Stochastic gradient descent, SGD),這裡再回顧一下:

當然,SGD 其實並不是一個很好的方法,有很多改進版本,可以用下面這張gif圖概況:

Keras 里,可以直接使用 SGD, Adagrad, Adadelta, RMSProp 以及 Adam 等模塊。其實在優化過程中,直接使用 Adam 默認參數,基本就可以得到最優的結果:

from keras.optimizers import Adamadam = Adam()model.compile(loss=categorical_crossentropy, optimizer=adam, metrics=[accuracy])

3.實戰項目——CIFAR-10 圖像分類

最後我們用一個keras 中的示例,首先做一些前期準備:

核心部分,用各種零件搭建深度神經網路:

datagen = ImageDataGenerator( featurewise_center=False, samplewise_center=False, featurewise_std_normalization=False, samplewise_std_normalization=False, zca_whitening=False, rotation_range=0, width_shift_range=0.1, height_shift_range=0.1, horizontal_flip=True, vertical_flip=False)datagen.fit(X_train)

核心部分,用各種零件搭建深度神經網路:

下游部分,使用凸優化模塊:

adam = Adam(lr=0.0001)model.compile(loss=categorical_crossentropy, optimizer=adam, metrics=[accuracy])

最後,開始訓練模型,並且評估模型準確性:

>>>>閱讀全文


推薦閱讀:

「南寧IT圈」每日推送-20180515
學完這門課程,搖身一變成為Salesforce超級英雄!
美國人也不老實,美國刷「假好評」以及防水軍鬥爭
Tech in 2017: Hack Reality
讓我們一起來聊一聊F8里的黑科技

TAG:計算機視覺 | 科技 |