1. 程式人生 > >PyBrain官方Tutorial翻譯(一)

PyBrain官方Tutorial翻譯(一)

1.介紹

PyBrain的主旨是將不同的資料處理演算法封裝到模組(Module)裡。最小的模組包括一個依賴可自由調節引數的向前實現,一般通過一些機器學習演算法。

模組有輸入緩衝、輸出緩衝和相應的應用在錯誤反向傳播演算法中的錯誤緩衝。

模組整合在網路(Network)類別的物件上,由連線(Connection)物件連線起來。他們自身也可能包括一系列可調節的引數,例如權重等。

注意一個網路本身也是一個模組,方便建立分層網路。除了提供構建最常見的網路結構的快捷鍵之外,原則上只要是有向非迴圈圖,系統允許整合幾乎任意的連線系統。

網路的自由引數通過訓練(Trainer)進行調整,例如通過資料集(Dataset)去學習最優引數。但在強化學習實驗中,會使用包含優化任務的模擬環境而非資料集。

2.   用模組和連線構建網路

本章將會指導你使用PyBrain最基本的結構元素:向前反饋網路(FeedForwardNetwork)和迴圈網路(RecurrentNetwork),和對應的模組物件和連線物件。我們已經知道如何用buildNetwork快捷鍵建立網路—但因為這項技術的種種限制,我們現在探查如何從最底層(ground up)建立網路。

2.1. Feed Forward Networks

我們會從簡單的例子開始建立一個多層感知器。

首先我們建立一個新的FeedForwardNetwork物件:

>>> frompybrain.structureimport
FeedForwardNetwork
>>> n= FeedForwardNetwork()

然後,我們構建輸入層、隱藏層和輸出層:

>>> frompybrain.structureimport LinearLayer, SigmoidLayer
>>> inLayer= LinearLayer(2)
>>> hiddenLayer= SigmoidLayer(3)
>>> outLayer= LinearLayer(1)

要想知道所有不同類別的層,可以檢視modules包。 在使用它們之前,我們需要把它們加入網路:

>>> n.addInputModule(inLayer)
>>> n.addModule(hiddenLayer)
>>> n.addOutputModule(outLayer)

我們可以新增若干層的輸入和輸出模組。但是要明確告知哪些模組是輸入,哪些是輸出,便於向前傳遞輸入和向後傳遞錯誤。

還需要具體指定它們如何連線。這裡我們使用最常見的連線型別,即層與層之間的完全連線,將每一層的每一個神經元與其他(鄰近)層的每一個神經元連線。在FullConnection類別裡得到了實現:

>>> frompybrain.structureimport FullConnection
>>> in_to_hidden= FullConnection(inLayer, hiddenLayer)
>>> hidden_to_out= FullConnection(hiddenLayer, outLayer)

和模組一樣,我們要具體指定的將它們加入網路中:

>>> n.addConnection(in_to_hidden)
>>> n.addConnection(hidden_to_out)

所有的元素都在適當的位置了,現在只差最後一步就可以讓我們的MLP跑起來了,叫做.sortModules()方法:

>>> n.sortModules()

這個招呼實現了網路最終使用前,一些必要的內部初始化:例如,模組按照拓撲排序等。

1.2.       Examining a Network

我們可以直接打印出網路來檢查它們的結構:

>>> print n
FeedForwardNetwork-6
Modules:
 [<LinearLayer 'LinearLayer-3'>, <SigmoidLayer 'SigmoidLayer-7'>, <LinearLayer 'LinearLayer-8'>]
Connections:
 [<FullConnection 'FullConnection-4': 'LinearLayer-3' -> 'SigmoidLayer-7'>, <FullConnection 'FullConnection-5': 'SigmoidLayer-7' -> 'LinearLayer-8'>]

注意輸出在你們的電腦上可能會有所不同。

一種使用這個網路的方法是使用一個被轉換的輸入,招呼它本身的‘activate()’方法:

>>> n.activate([1,2])
array([-0.11302355])

再次注意,在你的電腦上可能結果會有所不同,因為連線權重的初始化是隨機的。可以檢查.params領域的連線,來檢視這些引數。

我們可以直接取得連線的可訓練引數(權重),或者一次性讀取所有網路權重:

>>> in_to_hidden.params
array([ 1.37751406,  1.39320901, -0.24052686, -0.67970042, -0.5999425 , -1.27774679])
>>> hidden_to_out.params
array([-0.32156782,  1.09338421,  0.48784924])

網路封裝模組也有這些引數。可以如下檢測到:

>>> n.params
array([ 1.37751406,  1.39320901, -0.24052686, -0.67970042, -0.5999425 ,
     -1.27774679, -0.32156782,  1.09338421,  0.48784924])

可見最後三個網路引數等於第二層連線的引數值。

1.3.       Naming your Networks structure

在某些情況下,需要給網路不同部分起具體的名字。結構化元件源起Named類別,所以可以通過它們的.name屬性來命名,否則會自動生成一個新名字。

從屬類別可以在初始化的時候,通過傳遞.name自變數來命名:

>>> LinearLayer(2)
<LinearLayer 'LinearLayer-11'>
>>> LinearLayer(2, name="foo")
<LinearLayer 'foo'>

使用自己命名的網路,列印結果會更加簡潔和可讀。並且保證每次執行程式,都會按照相同的名稱來顯示。

1.4.       Using Recurrent Networks

要允許迴圈性,網路必須可以“及時向後看”。由於這樣,RecurrentNetwork類別和FeedForwardNetwork有實質上的區別,即儲存了完全的歷史記錄。很佔記憶空間,但是學習演算法所必需的。

建立一個迴圈性網路,基本和之前一樣,選擇適當的類別即可:

>>> frompybrain.structureimport RecurrentNetwork
>>> n= RecurrentNetwork()

我們很快可以建立一個和上面例子一樣的網路:

>>> n.addInputModule(LinearLayer(2, name='in'))
>>> n.addModule(SigmoidLayer(3, name='hidden'))
>>> n.addOutputModule(LinearLayer(1, name='out'))
>>> n.addConnection(FullConnection(n['in'], n['hidden'], name='c1'))
>>> n.addConnection(FullConnection(n['hidden'], n['out'], name='c2'))

RecurrentNetwork類別多一個.addRecurrentConnection(), 每次可以回看一個timestep。我們可以在隱藏層之間多加一層:

>>> n.addRecurrentConnection(FullConnection(n['hidden'], n['hidden'], name='c3'))

如果現在我們啟用網路,會每次得到不同的輸出:

>>> n.sortModules()
>>> n.activate((2,2))
array([-0.1959887])
>>> n.activate((2,2))
array([-0.19623716])
>>> n.activate((2,2))
array([-0.19675801])

當然,我們可以清空網路歷史,通過召喚reset方法來實現:

>>> n.reset()
>>> n.activate((2,2))
array([-0.1959887])
>>> n.activate((2,2))
array([-0.19623716])
>>> n.activate((2,2))
array([-0.19675801])

在召喚.rest()之後,我們將得到和物件建立時一樣的輸出結果。