
Theano - 簡單訓練示例
Theano 在訓練神經網路方面非常有用,在神經網路中,我們必須重複計算成本和梯度以達到最佳狀態。在大型資料集上,這會變得計算密集。由於 Theano 對我們之前看到的計算圖進行了內部最佳化,因此它可以有效地完成此操作。
問題陳述
我們現在將學習如何使用 Theano 庫來訓練一個網路。我們將以一個簡單的案例為例,從一個具有四個特徵的資料集開始。在對每個特徵應用一定的權重(重要性)後,我們計算這些特徵的總和。
訓練的目標是修改分配給每個特徵的權重,以便總和達到目標值 100。
sum = f1 * w1 + f2 * w2 + f3 * w3 + f4 * w4
其中f1、f2、... 是特徵值,w1、w2、... 是權重。
為了更好地理解問題陳述,讓我量化一下這個例子。我們將假設每個特徵的初始值為 1.0,並將 w1 等於0.1、w2 等於0.25、w3 等於0.15 和 w4 等於0.3。分配權重值沒有明確的邏輯,這只是我們的直覺。因此,初始總和如下所示:
sum = 1.0 * 0.1 + 1.0 * 0.25 + 1.0 * 0.15 + 1.0 * 0.3
總和為0.8。現在,我們將繼續修改權重分配,以便此總和接近 100。當前0.8 的結果值與我們期望的 100 的目標值相差甚遠。在機器學習術語中,我們將成本定義為目標值減去當前輸出值的差值,通常將其平方以放大誤差。我們透過計算梯度並更新權重向量來在每次迭代中減少此成本。
讓我們看看如何在 Theano 中實現整個邏輯。
宣告變數
我們首先宣告我們的輸入向量 x 如下所示:
x = tensor.fvector('x')
其中x 是一個包含浮點值的單維陣列。
我們定義一個標量目標變數,如下所示:
target = tensor.fscalar('target')
接下來,我們建立一個權重張量W,其初始值如上所述:
W = theano.shared(numpy.asarray([0.1, 0.25, 0.15, 0.3]), 'W')
定義 Theano 表示式
我們現在使用以下表達式計算輸出:
y = (x * W).sum()
請注意,在上述語句中,x 和W 是向量,而不是簡單的標量變數。我們現在使用以下表達式計算誤差(成本):
cost = tensor.sqr(target - y)
成本是目標值與當前輸出值的差值的平方。
為了計算梯度(它告訴我們距離目標有多遠),我們使用內建的grad 方法,如下所示:
gradients = tensor.grad(cost, [W])
我們現在透過使用0.1 的學習率更新權重向量,如下所示:
W_updated = W - (0.1 * gradients[0])
接下來,我們需要使用上述值更新我們的權重向量。我們在以下語句中執行此操作:
updates = [(W, W_updated)]
定義/呼叫 Theano 函式
最後,我們在 Theano 中定義一個函式來計算總和。
f = function([x, target], y, updates=updates)
為了呼叫上述函式若干次,我們建立了一個for 迴圈,如下所示:
for i in range(10): output = f([1.0, 1.0, 1.0, 1.0], 100.0)
如前所述,函式的輸入是一個向量,其中包含四個特徵的初始值 - 我們將每個特徵的值分配為1.0,沒有任何具體原因。您可以根據自己的選擇分配不同的值,並檢查函式是否最終收斂。我們將在每次迭代中列印權重向量和相應輸出的值。它在下面的程式碼中顯示:
print ("iteration: ", i) print ("Modified Weights: ", W.get_value()) print ("Output: ", output)
完整程式清單
為了方便您快速參考,此處重新列出了完整的程式清單:
from theano import * import numpy x = tensor.fvector('x') target = tensor.fscalar('target') W = theano.shared(numpy.asarray([0.1, 0.25, 0.15, 0.3]), 'W') print ("Weights: ", W.get_value()) y = (x * W).sum() cost = tensor.sqr(target - y) gradients = tensor.grad(cost, [W]) W_updated = W - (0.1 * gradients[0]) updates = [(W, W_updated)] f = function([x, target], y, updates=updates) for i in range(10): output = f([1.0, 1.0, 1.0, 1.0], 100.0) print ("iteration: ", i) print ("Modified Weights: ", W.get_value()) print ("Output: ", output)
執行程式時,您將看到以下輸出:
Weights: [0.1 0.25 0.15 0.3 ] iteration: 0 Modified Weights: [19.94 20.09 19.99 20.14] Output: 0.8 iteration: 1 Modified Weights: [23.908 24.058 23.958 24.108] Output: 80.16000000000001 iteration: 2 Modified Weights: [24.7016 24.8516 24.7516 24.9016] Output: 96.03200000000001 iteration: 3 Modified Weights: [24.86032 25.01032 24.91032 25.06032] Output: 99.2064 iteration: 4 Modified Weights: [24.892064 25.042064 24.942064 25.092064] Output: 99.84128 iteration: 5 Modified Weights: [24.8984128 25.0484128 24.9484128 25.0984128] Output: 99.968256 iteration: 6 Modified Weights: [24.89968256 25.04968256 24.94968256 25.09968256] Output: 99.9936512 iteration: 7 Modified Weights: [24.89993651 25.04993651 24.94993651 25.09993651] Output: 99.99873024 iteration: 8 Modified Weights: [24.8999873 25.0499873 24.9499873 25.0999873] Output: 99.99974604799999 iteration: 9 Modified Weights: [24.89999746 25.04999746 24.94999746 25.09999746] Output: 99.99994920960002
觀察到在四次迭代後,輸出為99.96,在五次迭代後,輸出為99.99,這接近我們期望的100.0 目標。
根據所需的精度,您可以安全地得出結論,網路在 4 到 5 次迭代中得到訓練。訓練完成後,查詢權重向量,在 5 次迭代後,它取以下值:
iteration: 5 Modified Weights: [24.8984128 25.0484128 24.9484128 25.0984128]
您現在可以在網路中使用這些值來部署模型。