10.1 從生物到人工神經元(From Biological to Artificial Neurons)
人工神經網絡經歷了70年的跌宕起伏:深度學習與神經網絡:淺談人工神經網絡跌宕起伏七十年。
作者相信這次神經網絡浪潮是與眾不同的,理由如下:
- 現如今有海量數據用於訓練,並且ANNs在處理大規模復雜問題時頻繁由於其他ML技術。
- 硬件的性能有了明顯的提升,使得訓練ANNs的時間可以接受。
- 訓練算法有所改進。雖然與1990s相比只是輕微的不同,但卻得到了巨大提升。
- ANNs的一些理論上的缺陷,在實踐中情況要好得多。例如ANN的損失函數是非凸的,使用梯度下降訓練時有可能陷入局部最優解。但這一缺陷在實踐中很少見,即使出現,也與全局最優解很接近。
- ANNs似乎進入了“投資——進步”的良性循環。
10.1.1 生物神經元(Biological Neurons)
這需要回憶一下高中生物。https://en.wikipedia.org/wiki/Neuron
神經元通過細長的軸突(Axon)與其它神經元進行聯系。軸突的長度可能是細胞體的幾倍,也可能是成千上萬倍。
雖然單個神經元很簡單,但每個神經元都會與數以千計的神經元相聯系。數十億的神經元結合在一起形成巨大的網絡,就能進行高度復雜的計算。
10.1.2 邏輯運算神經元(Logical Computations with Neurons)
使用神經元進行或、與、非等運算。
10.1.3 感知機(The Perceptron)
感知機是最簡單的ANN架構,由Frank Rosenblatt於1957年發明。它基於被稱作linear threshold unit (LTU)的人工神經元。LTU首先計算輸入值的加權和($z = w_1x_1 + w_2x_2 + \cdots + w_nx_n = W^T \cdot X$),然后對$z$應用一個階梯函數(step function):
$h_W(x) = step(z) = step(W^T \cdot X)$。
圖10-4. LTU
感知機常用階梯函數:
\begin{align*}
\mbox{heaviside}(z) = \left\{\begin{matrix}
0 \quad \mbox{if} \quad z < 0 \\
1 \quad \mbox{if} \quad z \geq 0
\end{matrix}\right.
\end{align*}
\begin{align*}
\mbox{sgn}(z) = \left\{\begin{matrix}
-1 &\quad \mbox{if} \quad z < 0 \\
0 &\quad \mbox{if} \quad z = 0 \\
+1 &\quad \mbox{if} \quad z < 0
\end{matrix}\right.
\end{align*}
感知機學習規則:
$w_{i,j}^{\mbox{(next step)}} = w_{i,j} + \eta(y_j - \hat{y}_j)x_i$
(書中在括號里面寫的是$\hat{y}_j - y_j$,這是不對的,可參考https://en.wikipedia.org/wiki/Perceptron里面的算法步驟)
其中:
- $w_{i,j}$是第i個輸入神經元到第j個輸出神經元的權重。
- $x_i$是當前訓練樣本的第i個值。
- $\hat{y}_j$是當前訓練樣本預測值的第j個輸出。
- $y_j$是當前訓練樣本的第j個標簽。
- $\eta$是學習率
感知機的決策邊界是線性的,不能學習復雜模式,比如不能解決異或問題。但是可以通過多層感知機解決。
10.1.4 多層感知機和反向傳播
可以參考:反向傳播算法
圖10-8 常見激活函數及其導數
10.2 使用TensorFlow高級API訓練MLP
以下代碼訓練一個DNN用於分類,包括兩個隱層(一個有300神經元,一個有100神經元)和一個包含10個神經元的softmax輸出層。
import tensorflow as tf feature_columns = tf.contrib.learn.infer_real_valued_columns_from_input(X_train) dnn_clf = tf.contrib.learn.DNNClassifier(hidden_units=[300, 100], n_classes=10, feature_columns=feature_columns) dnn_clf.fit(x=X_train, y=y_train, batch_size=50, steps=40000)
如果使用MNIST數據集(需要進行歸一下,scale)進行訓練,可以達到98.1%的正確率。
>>> from sklearn.metrics import accuracy_score >>> y_pred = list(dnn_clf.predict(X_test)) >>> accuracy_score(y_test, y_pred) 0.98180000000000001
模型評估:
>>> dnn_clf.evaluate(X_test, y_test) {'accuracy': 0.98180002, 'global_step': 40000, 'loss': 0.073678359}
10.3 Training a DNN Using Plain TensorFlow
使用低級被python api訓練DNN,代碼位置。
10.4 超參數調整
神經網絡的靈活性也是其一大缺點:需要調整的超參數太多。無論使用任何網絡拓撲結構,都可以調整層數、每層神經元數、每層激活函數種類、權重初始化的邏輯,等等。
當然,可以使用網格搜索和交叉驗證來尋找合適的超參數。但是現在有太多的超參數,需要大量的時間在超參數空間中探索。最好的方法是使用隨機搜索,這在第二章也有介紹。還有一種選擇是使用類似Oscar的工具,其實現了復雜的算法幫助我們快速尋找合適的超參數。
下面將談一下一些超參數使用哪些值是合理的。
10.4.1 隱層數
對於很多問題,使用一個隱層就能得到不錯的結果。已經證明,對於只有一個隱層的MLP,只要提供足夠的神經元,就能對最復雜的函數建模。長期以來,這一事實使得研究者確信,不需要研究更深層的神經網絡。但他們忽視了深層網絡比淺層網絡具有更高的參數效率(parameter efficiency):前者可以使用更少的參數模擬復雜函數,這就可以更快速地訓練。
為了理解為什么會這樣,假設你要使用畫圖軟件繪制一個森林,但是復制/粘貼被禁用。這就要單獨地繪制每一棵樹,每一個分支,每一片樹葉。但如果可以使用復制粘貼,那將可以迅速完成整個森林。真實世界的數據同樣具有分層的結構,DNNs正好可以利用這一事實:低級隱層模擬低級結構(比如線性切分不同的形狀和方向),中間的隱層結合低級結構來模擬中級結構(比如方形,圓形),中級隱層和輸出層結合中級結構來模擬高級結構(比如人臉)。
總之,對於許多問題,都可以從一兩個隱層開始訓練。對付復雜問題,可以逐步增加隱層,直到過擬合。特別復雜的問題,比如圖片分類和語音識別,一般需要幾十層(或者上百層,但不是全連接,這將在第十三章介紹)。但是,一般不需要從頭開始訓練這種網絡:可以復用訓練好的任務相似的網絡,這可以節省大量的訓練時間和訓練數據(這將在第十一章介紹)。
10.4.2 每個隱層神經元數
很明顯,輸入層和輸出層的神經元數量由具體的分類任務決定。比如,MNIST任務需要$28 \times 28 = 784$個輸入神經元和10個輸出神經元。對於隱層,以往一個通常的做法是使其呈漏斗形,神經元數量逐層減少。其理論依據是,低級別的特征會被合並到高級別特征中。但是現如今,這一經驗不再是通常的選擇,你可以在每個隱層使用相同數量的神經元。和調整隱層數量相同,調整神經元數量時,也可以逐步增加知道過擬合。一般情況下,調整隱層數量比調整每層神經元數量更划算一些。
不幸的是,尋找合適數目的神經元,依然是a black art。一個簡單的做法是,使用比實際需要更多的隱層數和神經元數量,然后early stopping防止過擬合(還有其他的正則化技術,尤其是dropout,將在第十一章介紹)。這被稱為拉伸褲子(stretch pants)技術:與其浪費時間尋找恰好合適的尺寸,不如選擇更長的褲子,然后裁剪到合適尺寸(這是在Vincent Vanhoucke的深度學習課程中提到的,免費的哦)。
10.4.3 激活函數
大多數情況下隱層使用ReLU(或其變種)就可以了。它比別的激活函數更快,and Gradient Descent does not get stuck as much on plateaus,thanks to the fact that it does not saturate for large input values (as opposed to the logistic function or the hyperbolic tangent function, which saturate at 1)。(這句話沒看懂)
對於輸出層,softmax常用於分類問題,而回歸問題可以簡單地不使用激活函數。