本門課程的基礎章節,詳細介紹了如何使用tf.keras進行模型的搭建以及大量的深度學習的理論知識。理論知識包括分類問題、回歸問題、損失函數、神經網絡、激活函數、dropout、批歸一化、深度神經網絡、Wide&Deep模型、密集特征、稀疏特征、超參數搜索等及其在圖像分類、房價預測上的實現。
課程代碼的tensorflow版本:
大部分代碼是tensorflow2.0的;
課程以tf.keras API為主,因為keras在1.3以后的版本就引入進來了,因而部分代碼可以在tf1.3+運行;
另外有少量tensorflow1.*版本代碼,這些版本的代碼並不能在2.0上運行,因為很多API都已經過時了。
理論部分:
tensorflow-keras簡介;
分類問題、回歸問題、損失函數;
神經網絡、激活函數、批歸一化、Dropout;
wide&deep模型;
超參數搜索。
實戰部分:
keras搭建分類模型;
keras回調函數;
keras搭建回歸模型;
keras搭建深度神經網絡;
keras實現wide&deep模型;
keras與scikit-learn實現超參數搜索。
tensorflow-keras簡介
keras是什么:
基於python的高級神經網絡API,它是一套API,而不是一個完整的庫;
Francois Chollet(現在在Google,tf.keras由他來實現)於2014-2015年編寫Keras;
keras只是神經網絡的API,它不是一個完整的庫,它如何去運行呢?他要設置后端,現在tensorflow支持三個后端,有了后端之后,keras才能去運行以Tensorflow、CNTK或者Theano為后端運行,keras必須有后端才可以運行,keras的后端是可以切換的,對於用戶來說他只是使用了keras的API,他並不會用到后端里邊的東西他不依賴於后端,對於用戶來說切換后端對於他使用keras沒有任何的影響,自從tensorflow支持了稱為keras后端之后,現在大家一般使用以tensorflow為后端的keras;
由於keras它的抽象化做的比較好,所以極方便於快速實驗,幫助用戶以最少的時間驗證自己的想法。
tensorflow-keras是什么:
是tensorflow內部對keras API規范的又給實現;
他和以tensorflow為后端的keras其實是兩碼事,因為這一套keras API規范的是直接是現在tensorflow上的,就是這套API和tensorflow結合更加的緊密;
實現在tf.keras空間下,所以說tensorflow keras和tf.keras是一個類似的概念。
tf-keras和keras聯系:
基於同一套API,都是keras定義的那一套API,因為是同一套API,所以keras程序可以通過改導入方式輕松轉為tf.keras程序,反之對於tf.keras的代碼要想改成keras的代碼可能不一定能夠成立,因為tf.keras有一些其他的特性的東西,因為tf.keras種的keras和tensorflow結合的更加緊密,如果之前用過keras的話,可以很輕松的轉到tensorflow-keras上來;
他們的規范是一樣的,他們的模型導出的規范也是一樣的,相同的JSON和HDF5模型序列化格式和語義。
tf-keras和keras區別:(就是tf-keras他和tensorflow的聯系更加的緊密,具體緊密在以下方面)
tf-keras全面支持eager mode,只是用keras.Sequential和keras.Model時沒影響,自定義Model內部運算邏輯的時候會有影響(Tf底層API可以使用keras的model.fit等抽象,更適用於研究人員嘗試自己的想法);
Tf.keras支持基於tf.data做為數據的輸入;
tf.keras支持TPU訓練;
tf.keras支持tf.distribution中的分布式策略;
其他特性(tf.keras可以與tensorflow中的estimator預估器相集成,tf.keras可以保存為SavedModel,保存為tensorflow中的SavedModel之后呢就可以利用tensorflow的那種跨平台的優勢可以把這個model部署到各種各樣的平台上去,這是tf.keras的一些優勢)。
是使用keras還是使用tf.keras,如何選擇?
如果想用到tf.keras中的任何一個特性,那么選用tf.keras;
如果后端互換性很重要,那么選用keras;
如果都不重要,那隨便。
分類與回歸問題
本節課要解決的兩個問題,分類問題與回歸問題。
分類問題預測的是類別,模型輸出是概率分布,三分類問題輸出例子:[0.2, 0.7, 0.1]。
回歸問題預測的是值,模型的輸出是一個實數值。
為什么需要目標函數?
參數是逐步調整的;
目標可以幫助衡量模型的好壞。
分類問題的目標函數:
需要衡量目標類別與當前預測的差距(三分類問題輸出例子[0.2, 0.7, 0.1],三分類真實類別2->one_hot->[0, 0, 1]);
one-hot編碼,把正整數變為向量表達(生成一個長度小於正整數的向量,只有正整數的位置處為1,其余位置都為0);
平法差損失1/nΣ1/2(y-Model(x))2;
交叉熵損失1/nΣyln(Model(x))。
回歸問題的目標函數(比分類問題簡單,因為輸出是一個值而非分布):
預測值與真實值的差距;
平方差損失;
絕對值損失。
有了目標函數之后,怎么求解模型?
模型的訓練就是調整參數,使得目標函數逐漸變小的過程,這就是目標函數的一個作用。
實戰:
keras搭建分類模型、keras回調函數、keras搭建回歸模型。
使用keras搭建分類模型
數據讀取與展示:
模型構建:
模型數據歸一化:
實戰回調函數
當訓練模型的時候,中間可能要做一些事情。
EearlyStopping是當你的模型訓練,它的loss不再下降的時候,可以提前把它給停掉。
看它的參數,最主要的是前三個,monitor是我要關注的是哪一個指標,一般情況下我們關注的是驗證集上的目標函數的值,min_delta是一個閾值,我這次訓練和上次訓練的目標函數值的差距是不是比這個閾值要低,如果比這個閾值高的話,就不用earlyStopping,如果比這個閾值低的話可能就要考慮把它提前停止掉,patience是前后兩次目標函數值的差距比mind_delta小的時候,我連續多少次發生這樣的情況,我就要把它先關閉掉。
ModelCheckpoint是所有參數的中間狀態,可以在訓練過程中每隔一段時間把point給保存下來。
TensorBoard是tensorflow中的一個非常重要的工具,一般是模型訓練完之后,才把模型訓練的指標隨着訓練迭代次數的推進而變化的一個趨勢圖才能打印出來,有了TensorBoard,我們在模型訓練過程中我們就可以做這樣的一個事情,而是它是一個非常自動化的一個工具,還非常的好用。
調模型花費的時間要比建模型的時間要多得多,這也就是TensorBoard出現的意義。
加上回調函數的訓練函數,訓練完模型之后,會發現指定的文件夾下生成輸出模型文件、train和validation文件夾下是TensorBoard的文件:
然后命令行tensorboard --logdir="callbacks",其中callbacks是當前文件夾下回調函數TensorBoard的文件夾,然后會自動創建一個本地的tensorBoard服務器,端口號6006,在瀏覽器中打開即可。
上邊是精確度,下邊是目標函數趨勢圖,紅線是訓練集的,藍線是驗證集的。
GRAPHS是定義的模型的結構。
PROFILE是記錄內存和CPU的使用量的,沒有記錄就沒有數據。
神經網絡講解
激活函數:
歸一化:
Min-max歸一化:x* = (x-min)/(max-min)
Z-score歸一化:x* = (x-μ)/σ
批歸一化:
把歸一化從輸入數據擴展到每層的激活值上,因為每一層的輸出都是下一行的輸入,所以把每層激活值都歸一化。
為什么歸一化有效?
未歸一化的theta1、theta2范圍是不一樣的,所以等高線(在該線上目標函數值相等)看起來是一個橢圓,在橢圓上計算梯度的時候,它指向的不一定是圓心,導致訓練軌跡曲折走一些彎路才能到圓心點。
歸一化的等高線是正圓,法線方向指向圓心,所以訓練速度會更快。
什么是dropout?
隨機把一些神經單元給棄用掉,令一些參數為0,每次訓練棄用的神經單元是不一樣的。
dropout的作用:
防止過擬合,模型參數太多,記住樣本,泛化性能差。任意的兩個節點並不能再組合的去學習一些東西了,而是說每個節點獨立的去學習數據中的規律,這樣就防止記住樣本的這種事情發生,防止過擬合。
然后開始新一輪的實戰:
keras實現深度神經網絡;keras更改激活函數;keras實現批歸一化;keras實現dropout。
實戰深度神經網絡
導致圖像前期不怎么變化的原因:
1.參數眾多,初期訓練不充分
2.梯度消失
梯度消失:
梯度下降就是給每個參數求解它的導數,然后讓這個參數在它的導數方向上做一定量的更新,這是梯度下降的思想。梯度消失就是,對於一個多層次的神經網絡來說,離目標函數比較遠的底層神經網路,它的梯度比較微小的現象就叫做梯度消失。
梯度消失一般發生在深度神經網路里,它發生的原因主要是鏈式法則,梯度在一層層的傳導的時候,由於它前邊的系數太多,有可能會導致梯度消失的問題存在。所以會導致剛開始訓練的時候圖像變化會比較平緩。
實戰批歸一化、激活函數、dropout
批歸一化緩解梯度消失:批歸一化使每一層的值更加的規整,從而使得導向更加精准,可以在一定程度上緩解梯度消失。
dropout:
一般只給最后幾層添加dropout,不給每一層都添加dropout,dropout是用來防止過擬合的。dropout實現方法在keras中和其他layer一樣,也把dropout也實現為一個layer,在layer后添加dropout layer就相當於給前邊一層做了dropout。
wide&deep模型
16年,用於分類和回歸。應用到了Google play中的應用推薦。原始論文:https://arxiv.org/pdf/1606.07792v1.pdf。
他把信息用稀疏特征和密集特征來表示,然后基於這兩種特征去構建模型
稀疏特征:
離散值特征(在眾多值中只取其中一個);
one-hot表示;
如,計算機專業={1,0,0}(專業有計算機、人文、其他);
叉乘={(計算機,數據結構),...};
叉乘之后,稀疏特征做叉乘獲取共現信息,實現記憶的效果。
稀疏特征的優缺點:
優點是廣泛用於工業界,缺點是需要人工設計所有特征、可能過擬合、泛化能力差。
密集特征:
向量表達,如計算機=[0.3, 0.2, 0.6];
典型的應用word2vec,與訓練好的將詞語轉化為向量的一個工具,可以把一個詞轉化為向量,通過向量之間的距離衡量詞語之間的距離,如男-女 = 國王-王后。
密集特征的優缺點:
優點是帶有語義信息,不同向量之間有相關性,兼容沒有出現過的特征組合,更少人工參與,缺點是過度泛化,推薦不怎么相關的產品。
wide模型和wide&deep模型:
wide模型的輸入是one-hot向量。wide&deep模型左邊是wide模型,右邊是deep模型,deep模型是把輸入先轉化為一個密集的向量表達,再經過一個多層的全連接神經網路,之后再連到輸出上去,下邊是稀疏特征、再上邊是密集特征(稀疏特征的一個密集向量的表達)、再往上是隱含層、輸出單元。相對於wide模型,wide&deep模型多了兩個層次。
deep模型和wide&deep模型:
所以說,wide&deep模型是把wide和deep模型組合起來的一個模型。
Google play中的應用推薦模型:
左邊是deep模型,右邊是wide模型。
實戰:
tf.keras中的子類API實現wide&deep模型;功能API(函數式API);多輸入與多輸出。
函數API實現wide&deep模型
采用回歸問題實現wide&deep模型,因為房價預測回歸問題中有8個特征,可以很輕松的把這8個特征划分成給wide模型用的、給deep模型用的。而對於圖像分類來說,這種划分沒有什么意義,因為圖像中的特征它們的價值都是一樣的,而對於房價預測中的特征它們的價值是不一樣的,所以房價預測問題更適合wide&deep模型的實現。
子類API實現wide&deep模型
wide&deep模型的多輸入與多輸出
真正的wide&deep模型中的,wide、deep模型的輸入往往是不一樣的。
多輸出主要針對多任務問題,比如除了預測當前的房價,還要預測1年后的房價,那么這就有了兩個預測任務,我們就需要給出兩個結果。
超參數搜索
為什么要超參數搜索?
神經網路有很多訓練過程中不變的參數(網絡結構參數:幾層,每層寬度,每層激活函數等;訓練參數:batch_size,學習率,學習率衰減算法等),手工去試耗費人力,所以需要超參數搜索找到最合適的超參數。
搜索策略:
網格搜索;
隨即搜索;
遺傳算法搜索;
啟發式搜索。
網格搜索:
定義n維方格,每個放個對應一組超參數,一組一組參數嘗試。
如圖,dropout設置四個值,learning rate設置四個值,相互組合形成16個值,然后把16個值放到不同的機器上並行執行,找到最好的組合方式,這就是網格搜索。
隨即搜索:
參數的生成方式為隨機,可探索的空間更大。
對於網格搜索,只能取固定的一些值,最優解可能存在於中間某個值,可能用網格搜索永遠都找不到最優值,所以隨即搜索產生,即隨機的參數值組合。
遺傳算法:
對自然界的模擬,A、初始化候選參數集合->訓練->得到模型指標作為生存概率,B、選擇->交叉->變異->產生下一代集合,C、重新到A。
啟發式搜索:
是研究熱點-AutoML中的一部分,使用循環神經網路來生成參數,使用強化學習來進行反饋,使用模型來訓練生成參數。
手動實現超參數搜索
還是選用房價預測的回歸問題來進行超參數搜索實驗,因為房價預測數據集比較小,對於超參數搜索這樣耗時的任務更易於展示。
由於這種手動實現,如果超參數過多,則循環層數變多,而且每組參數順序執行,沒法並行,效率低,所以可以借助一些庫來實現。
sklearn封裝keras模型,實現超參數搜索
RandomizedSearchCV實現超參數搜索
1.tf的model轉化為sklearn的model。
2.定義參數集合
3.RandomizedSearchCV搜索參數
先定義好一個tf.keras的model,然后調用一個函數去把tf.keras的model給封裝成一個sklearn的model。這個封裝函數在API中可以查到,在tf.keras下的wrapper下的scikit_learn下。
可以把tf.keras定義好的model轉化為sklearn支持的一個model。
參數build_fn是搭建好的tf.keras的model。