Theano - 簡單訓練示例



Theano 在訓練神經網路方面非常有用,在神經網路中,我們必須重複計算成本和梯度以達到最佳狀態。在大型資料集上,這會變得計算密集。由於 Theano 對我們之前看到的計算圖進行了內部最佳化,因此它可以有效地完成此操作。

問題陳述

我們現在將學習如何使用 Theano 庫來訓練一個網路。我們將以一個簡單的案例為例,從一個具有四個特徵的資料集開始。在對每個特徵應用一定的權重(重要性)後,我們計算這些特徵的總和。

訓練的目標是修改分配給每個特徵的權重,以便總和達到目標值 100。

sum = f1 * w1 + f2 * w2 + f3 * w3 + f4 * w4

其中f1f2、... 是特徵值,w1w2、... 是權重。

為了更好地理解問題陳述,讓我量化一下這個例子。我們將假設每個特徵的初始值為 1.0,並將 w1 等於0.1w2 等於0.25w3 等於0.15w4 等於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()

請注意,在上述語句中,xW 是向量,而不是簡單的標量變數。我們現在使用以下表達式計算誤差(成本):

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]

您現在可以在網路中使用這些值來部署模型。

廣告