Computational Network Toolkit (CNTK) 是微軟出品的開源深度學習工具包
用 CNTK 搞深度學習 (一) 入門
Computational Network Toolkit (CNTK) 是微軟出品的開源深度學習工具包。本文介紹CNTK的基本內容,如何寫CNTK的網絡定義語言,以及跑通一個簡單的例子。
根據微軟開發者的描述,CNTK的性能比Caffe,Theano, TensoFlow等主流工具都要強。它支持CPU和GPU模式,所以沒有GPU,或者神經網絡比較小的實驗,直接用CPU版的CNTK跑就行了。 其開源主頁在 https://github.com/Microsoft/CNTK 它把神經網絡描述成一個有向圖的結構,葉子節點代表輸入或者網絡參數,其他節點計算步驟。 它支持卷積神經網絡和遞歸神經網絡。 由於CNTK剛推出不久,大眾教程估計不多,而且bug估計也不少。我學習的時候,主要參考三個資料:
1 官方入門教程 https://github.com/Microsoft/CNTK/wiki/Tutorial 本文也主要以這里的教程為例
2 官方論壇 https://github.com/Microsoft/CNTK/issues
3 官方論文 http://research.microsoft.com/pubs/226641/CNTKBook-20160217..pdf 這個有150頁,我是當作字典來用,遇到問題的時候就在里面搜
安裝CNTK: https://github.com/Microsoft/CNTK/wiki/CNTK-Binary-Download-and-Configuration 去這個頁面找符合自己系統的版本。 我是Windows用戶,CNTK有編譯好的CPU和GPU版本。由於本人的顯卡不是英偉達的,所以無奈只能用CPU版湊合用用。已經編譯好的包最方便了,解壓,然后把目錄(類似%...%、CNTK-2016-02-08-Windows-64bit-CPU-Only\cntk\cntk)添加到PATH變量中就行了。 有條件的人也可以自己編譯源代碼,稍微麻煩一些,各種依賴關系,好處是源碼更新的比較快,CNTK一大特點就是目前各種小bug比較多,比如我現在用的編譯好的包還是兩個月前發布的,已經自己填了好多坑了。
安裝好CNTK之后,運行一個程序,就是一個簡單的命令行: CNTK configFile=your_config_file , 其中,your_config_file 是網絡的定義文件,大概長這樣:
command=Train:Test Train=[
action="train"
NDLNetworkBuilder = [
...
]
SGD = [
...
]
reader = [
...
]
]
Test=[ ... ]
運行的入口就是command命令,command后面接需要依次運行的模塊,用冒號分開。 每個模塊里面需要定義的事情比較類似,主要是定義輸入的格式,網絡結構,學習算法(目前只有SGD)和參數。 在定義網絡結構的時候,會指明哪些節點是優化目標,哪些是評價指標,以及哪些是輸出的點。
眾所周知,把神經網絡的隱藏層去掉之后,輸入直接連到輸出層,這樣就行成了一個logistics regression分類器。所以https://github.com/Microsoft/CNTK/wiki/Tutorial 這個教程就指導大家如何構建一個LR。 我這里稍微變一下,學習一下如何構建帶有一層隱藏層的neural network,如下圖:

定義網絡結構
CNTK用網絡描述語言(network description language, NDL)描述一個神經網絡。 簡單的說,我們要描述輸入的feature,輸入的label,一些參數,參數和輸入之間的計算關系,以及目標節點是什么。
NDLNetworkBuilder=[
run=ndlLR
ndlLR=[
# sample and label dimensions
SDim=$dimension$
LDim=1
features=Input(SDim, 1)
labels=Input(LDim, 1)
# parameters to learn
B0 = Parameter(4)
W0 = Parameter(4, SDim)
B = Parameter(LDim)
W = Parameter(LDim, 4)
# operations
t0 = Times(W0, features)
z0 = Plus(t0, B0)
s0 = Sigmoid(z0)
t = Times(W, s0)
z = Plus(t, B)
s = Sigmoid(z)
LR = Logistic(labels, s)
EP = SquareError(labels, s)
# root nodes
FeatureNodes=(features)
LabelNodes=(labels)
CriteriaNodes=(LR)
EvalNodes=(EP)
OutputNodes=(s,t,z,s0,W0)
]
]
features=Input(SDim, 1) labels=Input(LDim, 1) 和 B0 = Parameter(4) 等可以想象成是在定義變量。 輸入是列向量,CNTK里面的運算全是矩陣運算,所以就把輸入當做只有一列的矩陣。 t0 = Times(W0, features) 是做矩陣乘法,t0把輸入和權重相乘,z0 是在t0上面加了一個bias,
s0表示經過一個激活函數。 B0,W0,t0,z0,s0構成了隱層的操作,這里定義的隱層有4個節點。 t,z,s是輸出層的操作,s就是輸出節點的值。 框架定義好之后,還需要指定一些根節點,用來指定特殊的任務,例如 FeatureNodes=(features) 和LabelNodes=(labels)分別規定了輸入和輸出節點,CriteriaNodes 是訓練的
時候優化的目標,EvalNodes 是在做評測的時候輸出的參考值。OutputNodes 指定了需要輸出到文件的節點。
設置訓練算法
SGD = [
epochSize=0 # 每輪迭代使用的樣例數, =0 表示使用整個訓練集
minibatchSize=25 # 訓練25個樣本就更新一次參數
learningRatesPerMB=0.1 # learning rates per MB
maxEpochs=50 #迭代50次
]
目前只有SGD(以及在SGD上的各種變種),可以在里面設置各種參數。
設置輸入格式
reader = [
#customDelimiter = " "
readerType = "UCIFastReader"
file = "Train.txt"
miniBatchMode = "partial"
verbosity = 1
randomize = "none"
features=[
dim = $dimension$
start = 0
]
labels=[
start = $dimension$ # skip $dimension$ elements before reading the label (i.e. the first two dimensions so we have "x1 x2 y" basically)
dim = 1 # label has 1 dimension
labelType=regression
labelMappingFile = "SimpleMapping.txt"
]
]
這也是CNTK的一個特點(吐槽點), 指定用什么方式讀取數據文件。 readerType = "UCIFastReader" 指定用普通的扁平化表格的格式(一行一個樣例,同一行內用空格隔開不同的數值),還有別的格式類型,例如圖像格式,文本語料格式等。UCIFastReader 是將被棄用的,而且在目前最新的binary包中是有bug的 (所以說,有條件的同學盡量自己編譯最新的源碼)。 用官方教程里的設置直接跑回出bug,以上是我修改過的代碼。 輸入格式主要描述了feature是哪幾列,維度是多少,label是哪幾列, label的類型等等。
綜上,Train這個模塊就是定義了這幾件事情:輸入格式,網絡內容,訓練模式。 運行的時候也是這個步驟: 讀取數據-> SGD 訓練.
其他
除了Train之外的模塊的流程比較類似,它們不需要再定義網絡結構和訓練模式,但是輸入格式還是要指定的。 例如Test模塊的流程是: 讀取數據->計算網絡->得到預測值->評估. 評估針對的是在網絡結構中被定義為EvalNodes 的節點。 SquareError 只是其中的一種評估指標。如果想用別的誤差函數,可以去查字典http://research.microsoft.com/pubs/226641/CNTKBook-20160217..pdf
Test=[
action="test"
reader=[
readerType="UCIFastReader"
file="Test.txt"
features=[
dim=2
start=0
]
labels=[
start=$dimension$
dim=1
labelDim=2
]
]
]
Output模塊和Test的流程基本一樣,只不過最后一個不是評估,而是把屬於OutputNodes的值給輸出到文件。 Output模塊會指定一個輸出目錄 outputPath = "LR.txt" , 輸出的文件以“LR.txt”為前綴,再加上變量命作為文件名。例如"LR.txt.W0"。
# output the results
Output=[
action="write"
reader=[
readerType="UCIFastReader"
file="Test.txt"
features=[
dim=$dimension$
start=0
]
labels=[
start=2
dim=1
labelType=regression
]
]
outputPath = "LR.txt" # dump the output as text
]
dumpNodeInfo 用來輸出參數的值。這在調試中很有用,例如去看看網絡的參數是如何變化的:
dumpNodeInfo=[
action=dumpnode
printValues=true
]
####################################################################
B=LearnableParameter [1,1] NeedGradient=true
-6.67130613
####################################################################
EP=SquareError ( labels , s )
features=InputValue [ 2 x 1 {1,2} ]
labels=InputValue [ 1 x 1 {1,1} ]
LR=Logistic ( labels , s )
s=Sigmoid ( z )
t=Times ( W , features )
W=LearnableParameter [1,2] NeedGradient=true
1.23924482 1.59913719
####################################################################
z=Plus ( t , B )
全部的代碼如下。 train文件 https://github.com/Microsoft/CNTK/wiki/Tutorial/Train-3Classes.txt test 文件 https://github.com/Microsoft/CNTK/wiki/Tutorial/Test-3Classes.txt。 數據是2維的:

# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
# logistic regression cntk script -- Network Description Language
# which commands to run
command=Train:Output:dumpNodeInfo:Test
#required...
modelPath="Models/LR_reg.dnn" # where to write the model to
deviceId=-1 # CPU
dimension=2 # input data dimensions
# training config
Train=[
action="train"
traceLevel = 1
NDLNetworkBuilder=[
run=ndlLR
ndlLR=[
# sample and label dimensions
SDim=$dimension$
LDim=1
features=Input(SDim, 1)
labels=Input(LDim, 1)
# parameters to learn
B0 = Parameter(4)
W0 = Parameter(4, SDim)
B = Parameter(LDim)
W = Parameter(LDim, 4)
# operations
t0 = Times(W0, features)
z0 = Plus(t0, B0)
s0 = Sigmoid(z0)
t = Times(W, s0)
z = Plus(t, B)
s = Sigmoid(z)
LR = Logistic(labels, s)
EP = SquareError(labels, s)
# root nodes
FeatureNodes=(features)
LabelNodes=(labels)
CriteriaNodes=(LR)
EvalNodes=(EP)
OutputNodes=(s,t,z,s0,W0)
]
]
SGD = [
epochSize=0 # =0 means size of the training set
minibatchSize=25
learningRatesPerMB=0.1 # learning rates per MB
maxEpochs=50
]
# parameter values for the reader
reader = [
#customDelimiter = " "
readerType = "UCIFastReader"
file = "Train.txt"
miniBatchMode = "partial"
verbosity = 1
randomize = "none"
features=[
dim = $dimension$
start = 0
]
labels=[
start = $dimension$ # skip $dimension$ elements before reading the label (i.e. the first two dimensions so we have "x1 x2 y" basically)
dim = 1 # label has 1 dimension
labelType=regression
labelMappingFile = "SimpleMapping.txt"
]
]
]
# test
Test=[
action="test"
reader=[
readerType="UCIFastReader"
randomize = "none"
file="Test.txt"
features=[
dim=$dimension$
start=0
]
labels=[
start = $dimension$ # skip $dimension$ elements before reading the label (i.e. the first two dimensions so we have "x1 x2 y" basically)
dim = 1 # label has 1 dimension
labelType=regression
labelMappingFile = "SimpleMapping.txt"
]
]
]
# output the results
Output=[
action="write"
reader=[
readerType="UCIFastReader"
file="Test.txt"
randomize = "none"
features=[
dim=$dimension$
start=0
]
labels=[
start = $dimension$ # skip $dimension$ elements before reading the label (i.e. the first two dimensions so we have "x1 x2 y" basically)
dim = 1 # label has 1 dimension
labelType=regression
labelMappingFile = "SimpleMapping.txt"
]
]
outputPath = "LR.txt" # dump the output as text
]
dumpNodeInfo=[
action=dumpnode
printValues=false
]
后一篇:
用CNTK搞深度學習 (二) 訓練基於RNN的自然語言模型 ( language model )
http://www.cnblogs.com/sylvanas2012/p/5419477.html
原創博客,未經允許,請勿轉載。

