共用方式為


BrainScript 網路產生器

自訂網路會在 CNTK 的自訂網路描述語言 「BrainScript」 中描述。若要定義自訂網路,請在訓練組態中包含名為 的 BrainScriptNetworkBuilder 區段。 您可以在 [ 基本概念 ] 頁面和對應的子頁面上找到網路描述語言的詳細描述。

使用 BrainScript 網路建立器有兩種形式,一種使用括弧 (...) ,另一種是使用大括弧的 {...} 簡短表單。 若要在外部檔案中描述您的網路,請指定類似以下的區塊:

BrainScriptNetworkBuilder = (new ComputationNetwork {
    include "yourNetwork.bs"
})

其中 yourNetwork.bs 包含使用 BrainScript 描述的網路。 yourNetwork.bs檔案會先在與組態檔相同的目錄中尋找,如果找不到,則位於 CNTK 可執行檔的目錄中。 這裡接受絕對和相對路徑名稱。 例如, bs/yourNetwork.bs 表示位於組態檔旁的檔案 bs (或 CNTK 可執行檔目錄內的目錄 bs) 。

注意:在 CNTK 1.6 之前,BrainScript 使用括弧 [...] ,而不是大括弧 {...} 。 仍接受方括弧,但已被取代。

或者,您可以直接在組態檔內定義網路內嵌。 如果您不打算跨多個組態共用相同的大腦腳本,這可以簡化設定。 使用此表單:

BrainScriptNetworkBuilder = {
    # insert network description here
}

所以 BrainScript 程式碼看起來會像這樣進入括弧? 若要瞭解,請直接跳到 BrainScript 基本概念

或者,請留在此頁面,並閱讀您一些較不常需要的詳細資料。

上述 {...} 表單實際上只是一個簡短的程式碼:

BrainScriptNetworkBuilder = (new ComputationNetwork {
    # insert network description here
})

最後,作為進階用途,表單 (...) 不限於使用 new 。 相反地,在括弧內允許評估為 物件的 ComputationNetwork BrainScript 運算式。 例如:

BrainScriptNetworkBuilder = ({
    include "myNetworks.bs"
    network = CreateMyNetworkOfType42()
}.network)

這是進階用法,有時也會發生在模型編輯的內容中。

下一步: BrainScript 基本概念

遺產 NDLNetworkBuilder

在舊版的 CNTK 中,網路產生器稱為 NDLNetworkBuilder 。 其定義語言是 BrainScript 的子集。 舊的剖析器較不具功能,但更適合使用。 還有其他小差異。

NDLNetworkBuilder 現在已被取代,但由於相似性,因此不難升級至 BrainScriptNetworkBuilder 。 以下是如何將網路描述 BrainScriptNetworkBuilder 轉換成 NDLNetworkBuilder 的指南。

NDLNetworkBuilder 更新至 BrainScriptNetworkBuilder

在大部分情況下,將 的現有網路定義 NDLNetworkBuilderBrainScriptNetworkBuilder 轉換成 很簡單。 主要變更是周圍的語法。 如果您未利用新的語言功能,核心網路描述本身主要是向上相容且可能完全相同或幾乎完全相同。

若要轉換您的描述,您必須切換網路產生器、調整 w.r.t. 外部語法,並可能稍微調整網路程式碼本身。

步驟 1: 切換網路建立器. NDLNetworkBuilder將 取代為 CNTK 組態檔中對應的 BrainScriptNetworkBuilder 區塊。 如果您的網路描述位於個別的檔案中:

# change from:
NDLNetworkBuilder = [
    ndlMacros = "shared.ndl"   # (if any)
    networkDescription = "yourNetwork.ndl"
]
# ...to:
BrainScriptNetworkBuilder = (new ComputationNetwork {
    include "shared.bs"        # (if any)
    include "yourNetwork.bs"
})

(副檔名的變更並非絕對必要,而是建議使用。)

如果您的網路描述位於 .cntk 組態檔本身:

# change from:
NDLNetworkBuilder = [
    # macros
    load = [
        SigmoidNetwork (x, W, b) = Sigmoid (Plus (Times (W, x), b))
    ]
    # network description
    run = [
        feat = Input (13)
        ...
        ce = CrossEntropyWithSoftmax (labels, z, tag="criterion")
    ]
]
# ...to:
BrainScriptNetworkBuilder = {
    # macros are just defined inline
    SigmoidNetwork (x, W, b) = Sigmoid (Plus (Times (W, x), b))  # or: Sigmoid (W * x + b)
    # network description
    feat = Input {13}
    ...
    ce = CrossEntropyWithSoftmax (labels, z, tag="criterion")
}

步驟 2: 移除 loadrun 區塊。 使用 BrainScriptNetworkBuilder 時,會合並宏/函式定義和主要程式碼。 loadrun 區塊必須直接移除。 例如下列程式碼:

load = ndlMnistMacros
run = DNN
ndlMnistMacros = [
    featDim = 784
    ...
    labels = InputValue(labelDim)
]
DNN = [
    hiddenDim = 200
    ...
    outputNodes = (ol)
]

只會變成:

featDim = 784
...
labels = InputValue(labelDim)
hiddenDim = 200
...
outputNodes = (ol)

您可能已使用 run 變數來選取其中一個具有外部變數的多個組態,例如:

NDLNetworkBuilder = [
    run = $whichModel$   # outside parameter selects model, must be either "model1" or "model2"
    model1 = [ ... (MODEL 1 DEFINITION) ]
    model2 = [ ... (MODEL 1 DEFINITION) ]
]

此模式大部分是必要的,因為 NDL 沒有條件運算式。 在 BrainScript 中,現在會使用 if 運算式來撰寫:

BrainScriptNetworkBuilder = (new ComputationNetwork
    if      "$whichModel$" == "model1" then { ... (MODEL 1 DEFINITION) }
    else if "$whichModel$" == "model2" then { ... (MODEL 2 DEFINITION) }
    else Fail ("Invalid model selector value '$whichModel$'")
)

不過,選取的模型通常非常類似,因此最好是合併其描述,而改為只針對其不同之處使用內部的條件。 以下是用來在單向與雙向 LSTM 之間選擇參數的範例:

encoderFunction =
    if useBidirectionalEncoder
    then BS.RNNs.RecurrentBirectionalLSTMPStack
    else BS.RNNs.RecurrentLSTMPStack
encoder = encoderFunction (encoderDims, inputEmbedded, inputDim=inputEmbeddingDim)

步驟 3: 調整您的網路描述. 關於網路描述 (公式本身) ,BrainScript 大致上與 NDL 相容。 以下是主要差異:

  • 宏 (函式的傳回值) 不再是其中定義的最後一個變數,而是整個變數集。 您必須在結尾明確選取輸出值。 例如:

      # NDL:  
      f(x) = [  
          x2 = Times (x, x)  
          y = Plus (x2, Constant (1))  
      ]  # <-- return value defaults to last entry, i.e. y  
      # BrainScript:
      f(x) = {
          x2 = x*x  
          y = x2 + 1  
      }.y  # <-- return value y must be explicitly dereferenced
    

    如果沒有這項變更,函式傳回值會是整個記錄,而您得到的一般錯誤是 ComputationNode ,預期找到 的位置 ComputationNetwork

  • BrainScript 不允許具有可變參數數目的函式。 這主要對函 Parameter() 式很重要:向量參數無法再撰寫為 Parameter(N) ,現在必須明確寫入為張量 ParameterTensor{N} 或 1 欄矩陣 Parameter(N, 1) 。 如果沒有這項變更,您會收到與位置參數數目不符的錯誤。 此標記法也適用于 NDL,因此您可以先進行這項變更,並在轉換之前先使用 NDL 進行測試。 這也是將舊版名稱 LearnableParameter() 的任何用法重新命名為 ParameterTensor{} 的好機會。

    在 BrainScript 中,函式也很重要 RowStack() ,其會採用單一參數作為輸入陣列。 輸入必須以冒號分隔 (:) 而不是逗號,例如 RowStack (a:b:c) ,而不是 RowStack (a, b, c)

  • 某些預設值已更新,主要是 的選擇性 imageLayout 參數 Convolution() 、共用作業和 ImageInput() 。 針對 NDL,這些預設 legacy 為 ,而現在預設值是 cudnn 與 cuDNN 卷積基本類型相容的預設值。 (所有 NDL 程式碼範例都會明確指定此參數為 cudnn already.)

  • BrainScript 的剖析器更嚴格:

    • 識別碼現在會區分大小寫。 內建函式會使用 PascalCase (,例如 RectifiedLinear()) ,而內建變數和參數名稱則使用 camelCase (,例如 modelPathcriterionNodes) ,如同選項字串 (init="fixedValue"tag="criterion") 。 請注意,對於選擇性參數的名稱,不一定會攔截不正確的拼字錯誤。 相反地,只會忽略一些拼字錯誤的選擇性參數。 例如「特殊節點」定義。 它們的正確拼字現在如下:

        featureNodes    = ...
        labelNodes      = ...
        criterionNodes  = ...
        evaluationNodes = ...
        outputNodes     = ...
      
    • 不再允許縮寫的替代名稱,例如 Const() 應該是 Constant() ,應該是 tag="evaluation"tag="eval" 而且 evalNodes 現在是 evaluationNodes

    • 修正了一些拼字錯誤的名稱: criteria 現在 criterion (同樣 criterionNodes) , defaultHiddenActivity 現在是 defaultHiddenActivation

    • = 式定義不再是選擇性的符號。

    • 雖然允許對區塊使用方括弧 ([ ... ]) ,但它已被取代。 使用大括弧 ({ ... }) 。

    • 選項標籤必須以字串括住,例如 init="uniform" ,而不是 init=uniform 。 如果沒有引號,BrainScript 將會失敗,並顯示錯誤訊息,指出符號 uniform 未知。

    • (和 ParameterTensor{}) 建立參數 Input{} 的 BrainScript 基本類型應該針對其引數使用大括弧 (,例如 f = Input{42}) 。 這是不會強制執行但建議繼續進行的慣例。

    仍然接受 NDLNetworkBuilder 這個更受限的語法,因此建議您先進行這些語法變更,並使用 NDL進行測試,然後再實際變更為 BrainScript。

步驟 4: 從 「write」 和 「test」 區段中移除 NDLNetworkBuilder 。 請檢閱節的「寫入」和「測試」區段 NDLNetworkBuilder ,並加以移除。 我們的一些股票 NDL 範例有無關 NDLNetworkBuilder 的區段。 它們不會使用,而且不應該存在。 如果您的設定是以下列其中一個範例為基礎,您可能也會有這類區段。 它們過去會被忽略,但透過 BrainScript 更新,在這些區段中定義新的網路現在具有意義 (模型編輯) ,因此應該不再忽略它們,因此應該移除。

NDLNetworkBuilder 參考 (已被取代)

已被取代 NDLNetworkBuilder 的語法為:

NDLNetworkBuilder = [
    networkDescription = "yourNetwork.ndl"
]

區塊 NDLNetworkBuilder 具有下列參數:

  • networkDescription:網路描述檔案的檔案路徑。 在已被 NDLNetworkBuilder 取代之後,使用副檔名 .ndl 是自訂的 。 networkDescription如果沒有指定參數,則會假設網路描述會內嵌在相同的 NDLNetworkBuilder 子區塊中,並使用 run 下列參數指定。 請注意,只能透過 networkDescription 參數指定一個檔案路徑。 若要載入多個宏檔案,請使用 ndlMacros 參數。

  • run:將執行的 NDL 區塊。 如果透過 networkDescription 參數指定外部 NDL 檔案,參數 run 會識別該檔案中的區塊。 此參數會覆寫檔案中可能已經存在的任何 run 參數。 networkDescription如果未指定任何檔案, run 參數會識別目前組態檔中的區塊。

  • load:要載入的 NDL 腳本區塊。 您可以透過 「:」 分隔清單來指定多個區塊。 參數指定的 load 區塊通常會包含宏以供 區塊使用 run 。 與 參數類似 run ,如果參數指定 networkDescription 檔案,參數 load 會識別外部 NDL 檔案中的區塊,並覆寫檔案中可能已經存在的任何 load 參數。 networkDescription如果未指定任何檔案, load 則識別目前組態檔中的 區塊。

  • ndlMacros:可載入 NDL 宏的檔案路徑。 此參數通常用來載入所有 NDL 腳本可以使用的預設 NDL 宏集。 您可以藉由指定此參數 ndlMacros 的檔案路徑 「+」 分隔清單,來載入多個 NDL 檔案,每個檔案都指定不同的宏集。 若要與其他命令區塊共用宏,例如 NDL 的模型編輯語言 (MEL) 區塊,您應該在組態檔的根層級定義它。

  • randomSeedOffset:初始化可學習參數時的非負隨機種子位移值。 預設值是 0。 這可讓使用者使用不同的隨機初始化來執行實驗。