Introduction
此系列講解如何用 torch 實作 neural network 。
本系列不講解如何安裝 torch 及 lua 的基本語法,假設讀者都已具備這些基礎知識。
以 torch 實作 neural network 時,最常用的套件為 nn,而在 nn
中,建構 neural network 最基本的單位為 nn.Module 。 nn.Module
是一個抽象類別,所有建構 neural network 本身有關的 module ,都是從 nn.Module
所繼承而來。
舉個例子,如果要實作以下運算:
假設 為 2 維的 input ,而 為 3 維的output, 分別為 weight 和 bias ,此兩參數皆以隨機值進行初始化。
使用 torch 實作此運算的方法如下:
首先,載入 nn 套件:
1
|
|
建立一個 Linear Module:
1
|
|
其中, nn.Linear 即是用來進行 這類的線性運算所用的模組,它繼承了 nn.Module
。 而 2 和 3 分別代表了 和 的維度。 當它被建構出來時, weight 和 bias 的值會以隨機值來初始化。
以上程式中,建立一個命名為 l1
的 module ,如果要取得它的 weight 和 bias ,可以用 l1.weight
和 l1.bias
取得,方法如下:
1 2 |
|
執行結果如下:
1 2 3 4 5 6 7 8 9 |
|
其中, size 3x2 的 tensor 為 weight, size 3 的 tensor 為 bias。
用此 module 可以執行運算,令 x 為一個二維向量 ,輸入此 module ,進行 forward propagation ,也就是說,執行 的運算, 並輸出結果為 ,實作如下:
1 2 3 |
|
輸出結果 y
為一個三維向量,如下:
1 2 3 4 |
|
nn.Module & nn.Linear
這邊要更進一步介紹 nn.Module
和 nn.Linear
的內容是什麼。由於 torch 的程式碼相當簡潔易懂,可以直接看程式碼來了解它的功能是什麼。
nn.Module
程式碼: https://github.com/torch/nn/blob/master/Module.lua
nn.Linear
程式碼: https://github.com/torch/nn/blob/master/Linear.lua
首先,介紹 nn.Module
,先看 init()
的部分:
1 2 3 4 5 |
|
Module
中最基本的成員有 output
和 gradInput
。
output
為此 Module
的 forward propagation 結果,而 gradInput
為 backward propagation 的運算結果。
這些變量一開始都會被初始化為 空的 tensor 。
註:本文先不講解 backward propagation 與 gradInput
的部分,交由之後的教學文章來解釋。
在 Module:forward
的部分,是用來進行 forward propagation的,如下:
1 2 3 4 5 6 7 |
|
先看 forward 的部分, Module 沒有運算的實作,僅單純輸出 output
值。如果呼叫了 forward propagation ,則從 Module:updateOutput
就直接輸出了 output
。
而 nn.Linear
則實作了 forward propagation。
所謂的 Linear,即是指 的線性運算。
再來看 nn.Linear
的程式碼,先看 init()
的部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
在第1行, nn.Linear
繼承了 nn.Module
。
在第3行開始可以看到,建構 Linear 所需的參數有 inputSize
, outputSize
和 bias
。 bias
不一定要給,如果沒有給,則預設值會讓它是隨機的。除非 bias=false
,則此 Linear Module 就不會有 bias
。
從6~10行中,它比 nn.Module
多了 weigt
和 bias
這兩個變量,而 reset()
則是將它們初始化。
如果要建立一個 Linear Module,則要給定 inputSize
和 outputSize
,也就是 和 的維度。
假設 是二維, 是三維,建立一個命名為 l2
的 Linear 模組:
1
|
|
用以下方法印出 l2 的 weight
, bias
和 output
:
1 2 3 |
|
輸出結果如下:
1 2 3 4 5 6 7 8 9 10 11 |
|
其中,weight
和 bias
會被初始化隨機成 size 3x2 和 size 3 的 double tensor ,而最後一行顯示出 output
還是空的(with no dimension)。
如果想知道各個 variable 的 size ,還有個方式,就是直接用 print 的方式把它印出來,作法如下:
1
|
|
執行結果如下:
1 2 3 4 5 6 7 8 9 10 |
|
要讓 output
有值,就要進行 forward propagation 。而 Linear:updateOutput
則是實作了 Module:updateOutput
中, forward propagation 運算的實際內容,程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
以上可以分為兩部分來看,首先是當 input:dim() ==1
時,也就是 input
的維度為 1 ,也就是一次只輸入單筆資料的時候。第一步,會先調整 output
的 size
為適當的大小,再將 bias
複製到 output
,再讓 input
和 weight
進行矩陣相乘,並和 output
相加,再輸出結果。
從數學公式上來看,輸入值 是一維的向量,進行的運算如下:
此時, 放前面,而 放後面。
例如當輸入值向量 時,則矩陣運算的結果為:
實作以上算式,呼叫 l2:forward
,輸入 torch.Tensor{0,1}
並印出結果:
1
|
|
結果如下:
1 2 3 4 |
|
這時已經進行過了 forward 運算,而 output
有值了,所以可以印出它的值,方法如下:
1
|
|
output
的值也是如下:
1 2 3 4 |
|
而當 input:dim() ==2
時,也就是 input
的維度為 2 ,也就是一次輸入多筆資料。這時需要先把 weight
進行轉置,再和 input
,並和 bias
相加,並將結果加到 output
並輸出。
一次輸入多筆資料的目的是為了加速運算,因為用矩陣對矩陣的相乘的方式就可以來加速。這樣同時輸入的一批資料,就稱為 batch 。
從公式上來看,輸入值 是二維的矩陣,則進行以下矩陣運算:
此時, 放前面,而 進行轉置後放後面。
而 是將 轉置以後,再複製其橫排所形成的矩陣,以便和前面的矩陣相乘結果來相加。
例如當輸入資料有兩筆向量 和 時,則可以組成以下矩陣 (2x2) :
則矩陣運算的過程如下:
輸出結果為一個 2x3 的矩陣,每一個橫排為一個三維向量,代表著每一筆資料經過線性運算的結果。
實作以上算式,呼叫 l2:forward
,輸入由 {0,1}
和 {2,1}
這兩筆資料組成的 batch, 並印出結果:
1 2 3 4 5 |
|
結果如下:
1 2 3 |
|
也可印出 output
的值:
1
|
|
結果如下:
1 2 3 |
|
Materials
本次教學的完整程式碼於此:
https://github.com/ckmarkoh/torch_nn_tutorials/blob/master/1_nn_module_and_linear.ipynb