1. 程式人生 > 其它 >適合開發者的深度學習:第一天就能使用的編碼神經網路工具

適合開發者的深度學習:第一天就能使用的編碼神經網路工具

當前的深度學習浪潮在五年前就開始了。深度學習是驅動汽車的技術,也可以在Atari遊戲中擊敗人類,甚至能夠診斷癌症。

深度學習是機器學習的一個分支。它被證明是一種可以在原始資料中找到模式(比如影象或聲音)的有效方法。如果說你想要在沒有特定程式設計的情況下對貓和狗進行分類,首先它會在圖片中找到物體物件的邊緣,然後從中構建了模式,接下來,它會檢測鼻子、尾巴和爪子。這使得神經網路能夠對貓和狗進行最終分類。

但是,對於結構化資料,有更好的機器學習演算法。例如,如果你有一個帶有消費者資料的excel表格,並且想要預測他們的下一個訂單,你可以使用更簡單的機器學習演算法。如下:

核心邏輯 假設有一個隨機調整齒輪的機器。這些齒輪層疊在一起,它們互相影響。在最開始的時候,這臺機器不工作。齒輪層是隨機調整的,它們都需要調整以給出正確的輸出。然後,工程師將檢查所有的齒輪,並且標記出是哪些齒輪造成了錯誤。從最後一層齒輪開始檢查,因為這是所有錯誤造成的結果層。一旦工程師知道是上一層造成的錯誤的話,他就會逆向工作。這樣他就能計算出每一個齒輪對誤差起得作用有多少。我們把這個過程稱為反向傳播演算法(back propagation)。

工程師會根據每個齒輪的錯誤進行調整,然後再次執行機器,直到機器給出正確的輸出。

訓練迴圈順序:作出預測→計算錯誤→調整預測→作出預測

神經網路以同樣的方式運作。它知道輸入和輸出並調整齒輪以找到兩者之間的相關性。給定一個輸入,它會調整齒輪來預測輸出。然後,它將預測值與實際值進行比較。

差異介於預測值和實際值之間。為了將錯誤最小化,神經網路對齒輪進行調優,直到預測值和實際值之間的差異儘可能地降低。

梯度下降(gradient descent)是將誤差最小化的最優方式。誤差是由誤差/成本函式計算的。

一個淺層的人工神經網路 許多人認為人工神經網路是我們大腦皮質的數字複製品。這不是真實的。這是Frank Rosenblatt的靈感來源,他是神經網路的發明者。

用一個或兩個小時時間操作神經網路模擬器來理解它。首先,我們將實現一個簡單的神經網路,以瞭解TFlearn中的語法(syntax)。在TFlearn中,最經典的101問題是OR operator。儘管神經網路更適合於其他型別的資料,但這個問題對於理解它是如何工作的是非常好的。

所有的深度學習專案都遵循同樣的核心邏輯:

  • 它從庫開始,然後匯入和清洗資料。不管是影象、音訊還是感官資料,所有輸入都被轉換成數字。這些長長的數字列表是我們神經網路的輸入。
  • 現在設計你的神經網路,選擇型別還有在你的網路中層數。
  • 然後讓它進入學習過程。它知道輸入和輸出值,並搜尋它們之間的相關性。
  • 最後一步是給你訓練的神經網路做一個預測。

以下是我們的神經網路的程式碼:

# 1. Import library of functions
import tflearn
# 2. Logical OR operator / the data
OR = [[0., 0.], [0., 1.], [1., 0.], [1., 1.]]
Y_truth = [[0.], [1.], [1.], [1.]]
# 3. Building our neural network/layers of functions 
neural_net = tflearn.input_data(shape=[None, 2])
neural_net = tflearn.fully_connected(neural_net, 1, activation='sigmoid')
neural_net = tflearn.regression(neural_net, optimizer='sgd', learning_rate=2, loss='mean_square')
# 4. Train the neural network / Epochs
model = tflearn.DNN(neural_net)
model.fit(OR, Y_truth, n_epoch=2000, snapshot_epoch=False)
# 5. Testing final prediction
print("Testing OR operator")
print("0 or 0:", model.predict([[0., 0.]]))
print("0 or 1:", model.predict([[0., 1.]]))
print("1 or 0:", model.predict([[1., 0.]]))
print("1 or 1:", model.predict([[1., 1.]]))

輸出:

Training Step: 2000 | total loss: 0.00072 | time: 0.002s
| SGD | epoch: 2000 | loss: 0.00072 -- iter: 4/4
Testing OR operator
0 or 0: [[ 0.04013482]]
0 or 1: [[ 0.97487926]]
1 or 0: [[ 0.97542077]]
1 or 1: [[ 0.99997282]]

程式碼圖片版:

第一行:程式碼開始時是註釋,用來解釋程式碼。

第二行:包含TFlearn庫,這讓我們可以從谷歌的Tensorflow中使用深度學習功能。

第五到六行:表格中資料儲存在列表中,每個數字末尾的點將每個整數對映為浮點數。它使用十進位制值儲存數字,使計算精確。

第九行:初始化神經網路並指定輸入資料的維度或形狀。每一個OR operator都是成對的,因此它有一個“2”的形狀。它們中沒有預設值,並且代表了批處理大小。

第十行:輸出層。啟用函式將在一個間隔內的層上的輸出對映。在我們的例子中,我們使用了一個對映值在0到1之間的Sigmoid函式。閱讀更多關於第9行和第10行的內容,地址:http://tflearn.org/layers/core/。

第十一行:應用迴歸。優化器選擇哪種演算法來最小化成本函式。學習速率決定了修改神經網路的速度,而損失變數決定了如何計算錯誤。

第十四行:選擇使用哪個神經網路。它還用於指定儲存訓練日誌的位置。

第十五行:訓練你的神經網路和模型。選擇你的輸入資料(或)和真正的標籤(Y_truth)。Epochs會通過神經網路來決定所有資料執行的次數。如果你設定快照=True,那麼它會在每個階段之後驗證模型。

第十八到二十二行:用你的訓練模型做出預測。

閱讀更多關於第十四到二十二行的內容。地址:http://tflearn.org/models/dnn/

輸出標籤:第一個結果意味著組合[0.]&[0.]有4%的概率為真實的。訓練步驟顯示出你訓練了多少批次。

因為資料可以適應一個批處理,所以它和Epoch是一樣的。如果資料對於記憶體來說太大的話,你就需要把訓練分解成塊。損失衡量的是每個epoch的錯誤總和。

SGD代表隨機梯度下降和使成本函式最小化的方法。

Iter將顯示當前的資料索引和輸入項的總數。

你可以在幾乎所有TFlearn的神經網路中找到上述的邏輯和語法。瞭解程式碼的最佳方法是修改它並建立幾個錯誤。

損失曲線顯示每個訓練步驟的錯誤數量

使用Tensorboard時,你可以形象化每一個實驗,並建立一個直覺來判斷每個引數是如何改變訓練的。下面是一些你可以執行的示例的建議。我建議你花幾個小時來適應環境和TFlearn引數。

實驗

  • 增加訓練和epochs
  • 嘗試從文件中新增和更改一個引數到每個函式。例如,g = tflearn.fullyconnected(g, 1, activation=’sigmoid’)變成tflearn.fullyconnected(g, 1, activation=’sigmoid’, bias=False)
  • 在輸入資料中新增整數
  • 在輸入層中改變形狀
  • 在輸出層中更改啟用函式
  • 對梯度下降使用不同的方法
  • 改變神經網路計算成本的方式
  • 改變X和Y,而不是邏輯運算子
  • 將輸出資料更改為XOR邏輯運算子。例如,從[1.]到[0.]交換最後的Y_truth。你需要在你的網路中新增一個圖層讓它執行
  • 使它學得更快
  • 找到一種方法讓每一個學習步驟都超過0.1秒

開始 Python與Tensorflow結合是深度學習中最常見的堆疊。TFlearn是一個在Tensorflow上執行的高階框架。另一個常見的框架是Keras。它是一個更具有魯棒性的庫,但是我發現TFlearn語法更容易理解。它們都是在Tensorflow上執行的高階框架。

你可以在電腦的CPU上執行簡單的神經網路。但是大多數的實驗需要幾個小時甚至幾周的時間才能執行。這就是為什麼大多數人使用現代GPU進行深度學習的原因,通常是通過雲服務的途徑。

對於雲GPU來說,最簡單的解決方案是使用FloydHub。如果你有基本的命令列技能,那麼設定它不需要超過5分鐘。

使用FloydHub docs來安裝floyd-cli命令列工具。如果你在安裝時被困在任何地方,FloydHub會在他們的內部通話聊天中提供支援。

這有一個Floydhub的安裝視訊,並且使用了TFlearn、Jupyter Notebook和Tensorboard來執行。

視訊地址:https://www.youtube.com/watch?v=byLQ9kgjTdQ

讓我們使用TFlearn、Jupyter Notebook和Tensorboard來執行你的第一個神經網路。在安裝和登入到FloydHub之後,下載你需要的檔案。然後,到你的終端,輸入以下命令:

git clone https://github.com/emilwallner/Deep-Learning-101.git

開啟資料夾,並啟動FloydHub:

cd Deep-Learning-101
floyd init 101

在你的瀏覽器中,FloydHub將會開啟web面板,你將會被提示建立一個名為101的新的FloydHub專案。完成之後,返回到你的終端並執行相同的init命令。

floyd init 101

現在,你可以在FloydHub上執行你的神經網路了。通過floyd runcommand,你可以進入不同的設定。在我們的案例中,我們想要:

  • 在FloydHub上架置一個我已經上傳的公共資料集。在資料目錄型別(data directory type)——data emilwallner/datasets/cifar-10/1:data中可以找到。你可以通過在FloydHub上瀏覽它探索該資料集(以及許多其他公共資料集)
  • 使用雲GPU——GPU
  • 使用Tensorboard——Tensorboard
  • 在Jupyter Notebook模式下執行——mode jupyter

好了,讓我們來執行:

floyd run --data emilwallner/datasets/cifar-10/1:data --gpu --tensorboard --mode jupyter

一旦它在你的瀏覽器中啟動了Jupyter,那麼點選名為start-here.ipnyb的檔案。start-here.ipnyb是一個簡單的神經網路,可以瞭解在TFlearn中的語法。它學習OR operator的邏輯,稍後會做出詳細解釋。

在選單行中,單擊Kernel > Restart & Run All。如果你看到了這個資訊,那麼就證明它是有效的,你就可以繼續操作。

然後,到你的FloydHub專案中去尋找Tensorboard的連結。

一個深度神經網路 深度學習是一種有多個隱藏層的神經網路。關於卷積神經網路的工作,已經有了很多詳細的教程。

教程地址:

  • https://www.youtube.com/watch?v=FmpDIaiMIeA&t=1202s
  • http://cs231n.github.io/convolutional-networks/
  • https://www.youtube.com/watch?v=LxfUGhug-iQ

所以,我們將集中討論你可以應用到大多數神經網路的高階概念。

注意:視覺化並不是一個深度神經網路,它需要一個以上的隱藏層

你需要訓練神經網路來預測它沒有經過訓練的資料,它需要一種概括的能力。這是學習(learning)和遺忘(forgetting)之間的平衡。

你想讓它學會把訊號從噪音中分離出來,但也要忘記在訓練資料中發現的訊號。如果神經網路學習得不充分,那就不合適了。相反的是過度擬合。

正則化是通過忘記訓練特定的訊號來減少過度擬合的過程。為了直觀地理解這些概念,我們將使用CIFAR-10資料集。它是一個在10個不同的類別中有6萬張圖片的資料集,比如汽車、卡車和鳥類等等。它的目標是在10個類別中預測新影象所屬於哪一個類別。

CIFAR中的樣本圖片

通常情況下,我們必須刮掉資料,清洗它,並對影象應用過濾器。但是為了縮小它的範圍,我們只關注神經網路。你可以在安裝部分的Jupyter Notebbok上執行所有示例。

地址:https://github.com/emilwallner/Deep-Learning-101

輸入層獲取一個已被對映到數字的影象。輸出層將影象分為10個類別。隱藏層是由卷積、匯聚和連線的層組成的。

選擇圖層的數量 讓我們將一個與三組圖層的神經網路進行比較。每個集合包括一個卷積、池和連線的層。

前兩個實驗被稱為experiment-0-few-layers.ipynb和experiment-0-three-layer-sets.ipynb。

# Convolutional network building
network = input_data(shape=[None, 32, 32, 3],
 data_preprocessing=img_prep,
 data_augmentation=img_aug)
# One set of layers
network = conv_2d(network, 32, 3, activation='relu')
network = max_pool_2d(network, 2)
network = fully_connected(network, 512, activation='relu')
network = fully_connected(network, 10, activation='softmax')
network = regression(network, optimizer='adam',
 loss='categorical_crossentropy',
 learning_rate=0.001)

你可以通過點選Kernel > Restart & Run All選單欄來執行這些Nootebook。然後看一下Tensorboard的訓練日誌。你會發現,有很多層的準確率要高於15%。沒有很多的層是不合適的,這證明了它沒有進行足夠的學習。

你可以在前面下載的資料夾中執行相同的示例,以及所有即將進行的實驗。

repo中的experiment_0.ipynb

看一看精確性和準確性/有效性(Accuracy和Accuracy/Validation)。在深度學習中,將資料集一分為二是最好的實踐。一種是訓練神經網路,另一種是驗證神經網路。這樣你就可以知道神經網路對新資料的預測或者它的泛化能力有多好。

正如我們所看到的,訓練資料的精確性高於驗證資料集的準確性。神經網路包括背景噪音和阻礙它預測新影象的細節。為了解決這個問題,你可以懲罰複變函式,並在神經網路中引入噪聲。為了防止這一現象的發生,常用的正則化技術是dropout層,並對複變函式進行懲罰。

Dropout層 我們可以將dropout正則化與民主(democracy)的價值進行比較。它們沒有很多強大的神經元來決定最終的結果,而是分配了權力。

神經網路被迫學習幾種獨立的表達方式。當它做出最終的預測時,它有幾個不同的模式可供學習。這有一個有著dropout層的神經網路的例子。

network = input_data(shape=[None, 32, 32, 3],
 data_preprocessing=img_prep,
 data_augmentation=img_aug)
network = conv_2d(network, 32, 3, activation='relu')
network = max_pool_2d(network, 2)
network = conv_2d(network, 64, 3, activation='relu')
network = conv_2d(network, 64, 3, activation='relu')
network = max_pool_2d(network, 2)
network = fully_connected(network, 512, activation='relu')
#The dropout layer
network = dropout(network, 0.5)
network = fully_connected(network, 10, activation='softmax')
network = regression(network, optimizer='adam',
 loss='categorical_crossentropy',
 learning_rate=0.001)

在這個比較中,除了一個有dropout層而另一個沒有之外,它們的神經網路是一樣的。

在神經網路的每一層,神經元相互依賴。有些神經元比其他神經元更有影響力。而dropout層會隨機地對不同的神經元進行不同的測試。這樣,每個神經元都必須對最終的輸出做出不同的貢獻。

第二種防止過度擬合的方法是在每一層上應用L1或L2正則化函式。

L1和L2正則化 假設你想描述一匹馬。如果描述得太詳細,你就排除了太多數樣子的馬。但是,如果說得太籠統的話,你可能會把其他動物也包括在內。L1和L2正則化可以幫助網路進行區分。

network = input_data(shape=[None, 32, 32, 3],
 data_preprocessing=img_prep,
 data_augmentation=img_aug)
network = conv_2d(network, 32, 3, activation='relu', regularizer='L2')
network = max_pool_2d(network, 2)
network = conv_2d(network, 64, 3, activation='relu', regularizer='L2')
network = conv_2d(network, 64, 3, activation='relu', regularizer='L2')
network = max_pool_2d(network, 2)
network = fully_connected(network, 512, activation='relu', regularizer='L2')
network = fully_connected(network, 10, activation='softmax')
network = regression(network, optimizer='adam',
 loss='categorical_crossentropy',
 learning_rate=0.001)

如果我們像之前的實驗一樣做一個類似的比較,我們會得到一個相似的結果。

具有正則化函式的神經網路在沒有它們的情況下表現得更出色。正則化函式L2懲罰的功能過於複雜。它度量每個函式對最終輸出的貢獻。然後它會懲罰有大系數的那些。

批量大小 另一個核心超引數是批處理大小,它是每個訓練步驟所使用的資料量。下面是大批量和小批量大小的比較。

#Large batch size
model.fit(X, Y, 
 n_epoch=50, 
 shuffle=True, 
 validation_set=(X_test, Y_test), 
 show_metric=True, 
 batch_size=2000, 
 run_id='cifar_large_batch_size')

正如我們在結果中看到的,一個大批處理需要更少的週期,但是有更精確的訓練步驟。相比之下,較小的批處理更隨機,但需要更多的訓練步驟。

此外,雖然大量的批處理需要更少的學習步驟。但是,你需要更多的記憶體和時間來計算每一步。

學習速率 最後一個實驗是對一個具有小、中、大學習速率的網路進行比較。

#Large learning rate
network = regression(network, 
 optimizer='adam',
 loss='categorical_crossentropy',
 learning_rate=0.01)

學習速率通常被認為是最重要的引數之一。它調節瞭如何在每個學習步驟中調整預測的變化。如果學習速率過高或過低,它可能不會收斂,就像上面的大的學習速率一樣。

設計神經網路並沒有固定的方法,很多都和實驗有關。如果你能夠訪問大量計算能力,你可以建立程式來設計和優化超級引數。當你完成了你的工作後,你應該spin down你的雲GPU例項。做法是在FloydHub web儀表盤中點選取消。

接下來可以做些什麼? 在TFlearn的官方示例repo中,你可以切身體會一些表現最好的卷積神經網路。嘗試複製一些方法,並改進CIFAR-10資料集的驗證。

repo地址:https://github.com/tflearn/tflearn/tree/master/examples/images。