1. 程式人生 > >CNTK 搞深度學習-1

CNTK 搞深度學習-1

激活 result dll desc mman caf element 有用 成了

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

CNTK 搞深度學習-1