機器學習 Studio 的 Net# 類神經網路規格語言指南(傳統版)
適用於:機器學習 Studio (傳統) Azure 機器學習
重要
Machine Learning 工作室 (傳統) 的支援將於 2024 年 8 月 31 日結束。 建議您在該日期之前轉換成 Azure Machine Learning。
自 2021 年 12 月 1 日起,您將無法建立新的 Machine Learning 工作室 (傳統) 資源。 在 2024 年 8 月 31 日之前,您可以繼續使用現有的 Machine Learning 工作室 (傳統) 資源。
ML 工作室 (傳統) 文件即將淘汰,未來將不再更新。
Net# 是由 Microsoft 所開發的語言,可用來定義複雜的神經網路架構,例如深度神經網路或任意維度的卷積。 您可以使用複雜的結構來改善對影像、視訊或音訊等數據的學習。
您可以在 機器學習 Studio 中的所有類神經網路模組中使用 Net# 架構規格(傳統):
本文說明使用 Net# 開發自定義神經網路所需的基本概念和語法:
- 類神經網路需求以及如何定義主要元件
- Net# 規格語言的語法和關鍵字
- 使用 Net 建立的自定義神經網路範例#
類神經網路基本概念
類神經網路結構包含以圖層方式組織的節點,以及節點之間的加權連接(或邊緣)。 連線是方向的,而且每個連線都有來源節點和目的地節點。
每個可定型層 (隱藏或輸出層) 都有一或多個 連線組合。 線上組合包含來源層,以及來自該來源層的連接規格。 指定套件組合共用來源和目的地層中的所有連線。 在 Net# 中,連線套件組合會被視為屬於套件組合的目的地層。
Net# 支援各種連線組合,可讓您自定義輸入對應至隱藏層的方式,並對應至輸出。
默認或標準套件組合是 完整套件組合,來源層中的每個節點都會連線到目的地層中的每個節點。
此外,Net# 支援下列四種進階連線配套:
篩選的套件組合。 您可以使用來源層次節點和目的地層次節點的位置來定義述詞。 每當述詞為 True 時,就會連接節點。
卷積套件組合。 您可以在來源層中定義節點的小鄰區。 目的地層中的每個節點都會連接到來源層中的一個節點鄰區。
共用套件組合 和 回應正規化套件組合。 這些類似於卷積套件組合,使用者會在來源層中定義節點的小型鄰區。 差異在於,這些套件組合中邊緣的權數無法定型。 相反地,預先定義的函式會套用至來源節點值,以判斷目的地節點值。
支援的自訂
您在 機器學習 Studio 中建立的類神經網路模型架構(傳統版)可以使用 Net#廣泛自定義。 您可以:
- 建立隱藏層,並控制每個圖層中的節點數目。
- 指定如何彼此連接圖層。
- 定義特殊的連線結構,例如卷積和權數共享組合。
- 指定不同的啟用函式。
如需規格語言語法的詳細資訊,請參閱 結構規格。
如需定義一些常見機器學習工作的類神經網路範例,從simplex到複雜,請參閱 範例。
一般需求
- 必須只有一個輸出層、至少一個輸入層,以及零個或多個隱藏層。
- 每個圖層都有固定數目的節點,在概念上排列在任意維度的矩形陣列中。
- 輸入層沒有相關聯的定型參數,並代表實例數據進入網路的點。
- 可訓練的圖層(隱藏層和輸出層)具有相關聯的定型參數,稱為權數和偏差。
- 來源和目的地節點必須位於不同的圖層中。
- 連接必須是無迴圈的;換句話說,無法有連線鏈結回到初始來源節點。
- 輸出層不能是連接配套的來源層。
結構規格
類神經網路結構規格是由三個區段所組成: 常數宣告、 圖層宣告、 連接宣告。 另外還有選擇性 的共用宣告 區段。 區段可以依任何順序指定。
常數宣告
常數宣告是選擇性的。 它提供方法來定義類神經網路定義中其他地方所使用的值。 宣告語句包含標識符,後面接著等號和值表達式。
例如,下列語句會定義常數 x
:
Const X = 28;
若要同時定義兩個或多個常數,請以大括弧括住標識碼名稱和值,並使用分號分隔它們。 例如:
Const { X = 28; Y = 4; }
每個指派表達式的右側可以是整數、實數、布爾值(True 或 False),或是數學表達式。 例如:
Const { X = 17 * 2; Y = true; }
圖層宣告
需要圖層宣告。 它會定義圖層的大小和來源,包括其連接組合和屬性。 宣告語句的開頭是圖層的名稱(輸入、隱藏或輸出),後面接著圖層的維度(正整數的元組)。 例如:
input Data auto;
hidden Hidden[5,20] from Data all;
output Result[2] from Hidden all;
- 維度的乘積是圖層中的節點數目。 在此範例中,有兩個維度 [5,20],這表示圖層中有 100 個節點。
- 圖層可以依任何順序宣告,但有一個例外:如果定義了一個以上的輸入層,則宣告它們的順序必須符合輸入數據中的特徵順序。
若要指定自動判斷圖層中的節點數目,請使用 auto
關鍵詞。 關鍵詞 auto
有不同的效果,視圖層而定:
- 在輸入層宣告中,節點數目是輸入數據中的特徵數目。
- 在隱藏層宣告中,節點數目是由隱藏節點數目的參數值所指定的數位。
- 在輸出層宣告中,兩個類別分類的節點數目為 2,回歸為 1,等於多類別分類的輸出節點數目。
例如,下列網路定義允許自動判斷所有圖層的大小:
input Data auto;
hidden Hidden auto from Data all;
output Result auto from Hidden all;
可定型圖層的圖層宣告(隱藏或輸出層)可以選擇性地包含輸出函式(也稱為啟用函式),其預設為 分類模型的 sigmoid ,以及 回歸模型的線性 。 即使您使用預設值,您也可以視需要明確陳述啟用函式。
支援下列輸出函式:
- 乙狀結腸
- linear
- softmax
- rlinear
- 廣場
- sqrt
- srlinear
- abs
- tanh
- brlinear
例如,下列宣告使用 softmax 函式:
output Result [100] softmax from Hidden all;
連接宣告
定義可定型層之後,您必須在已定義的層次之間宣告連接。 連接套件組合宣告會以 關鍵詞 from
開頭,後面接著套件組合的來源層名稱,以及要建立的連接套件組合類型。
目前支援五種連線套件組合:
- 關鍵詞所指出的完整 套件組合
all
- 篩選的 套件組合,以 關鍵詞
where
表示,後面接著述詞表達式 - 以 關鍵詞
convolve
表示的捲積組合,後面接著卷積屬性 - 集區組合 ,以關鍵詞 最大集 區或 平均集區表示
- 回應正規化 配套,以關鍵詞 回應規範表示
完整套件組合
完整連線組合包含來源層中每個節點與目的地層中每個節點的連接。 這是預設的網路連線類型。
篩選的套件組合
篩選的連接套件組合規格包含述詞,以語法表示,非常類似於 C# Lambda 表達式。 下列範例會定義兩個篩選套件組合:
input Pixels [10, 20];
hidden ByRow[10, 12] from Pixels where (s,d) => s[0] == d[0];
hidden ByCol[5, 20] from Pixels where (s,d) => abs(s[1] - d[1]) <= 1;
在 的述
ByRow
詞中,是一個參數,s
代表輸入層節點矩形陣列中的索引,Pixels
而d
是代表隱藏層ByRow
節點陣列之索引的參數。 和d
的類型s
都是長度為2的整數元組。 就概念上講,s
範圍涵蓋所有具有0 <= s[0] < 10
和0 <= s[1] < 20
的整陣列,以及所有整陣列的範圍,以及d
和0 <= d[0] < 10
0 <= d[1] < 12
。在述詞表達式的右側,有一個條件。 在此範例中,針對的每個值
s
,d
而且條件為 True,來源層節點到目的地層節點都有邊緣。 因此,此篩選表示式表示套件組合包含從 所s
定義的節點連線到 所定義的d
節點,在所有 s[0] 等於 d[0] 的情況下。
您可以選擇性地為篩選的套件組合指定一組權數。 Weights 屬性的值必須是浮點值的 Tuple,其長度符合套件組合所定義的連接數目。 根據預設,會隨機產生權數。
加權值會依目的地節點索引分組。 也就是說,如果第一個目的地節點連接到 K 來源節點,則 Weights Tuple 的第一K
個元素是來源索引順序中第一個目的地節點的權數。 這也適用於其餘目的地節點。
您可以直接將權數指定為常數值。 例如,如果您先前已了解權數,您可以使用下列語法將它們指定為常數:
const Weights_1 = [0.0188045055, 0.130500451, ...]
卷積套件組合
當定型數據具有同質結構時,常會使用卷積連接來學習數據的高階特徵。 例如,在影像、音訊或視訊數據中,空間或時態維度可能相當一致。
卷積組合採用矩形核心,這些核心會滑過維度。 基本上,每個核心都會定義一組套用在本機街區的權數,稱為 核心應用程式。 每個核心應用程式都會對應至來源層中的節點,這稱為 中央節點。 核心的權數會在許多連線之間共用。 在卷積套件組合中,每個核心都是矩形,而且所有核心應用程式的大小都相同。
捲積套件組合支援下列屬性:
InputShape 會針對這個卷積組合的目的,定義來源層的維度。 值必須是正整數的元組。 整數的乘積必須等於來源層中的節點數目,否則不需要符合為來源層宣告的維度。 此 Tuple 的長度會 成為卷積套件組合的 arity 值。 通常 arity 是指函式可以接受的自變數或操作數數目。
若要定義核心的形狀和位置,請使用 KernelShape、Stride、Padding、LowerPad 和 UpperPad 屬性:
KernelShape:(必要) 定義卷積套件組合每個核心的維度。 值必須是正整數的元組,其長度等於配套的arity。 此 Tuple 的每個元件不得大於 InputShape 的對應元件。
Stride:(選擇性) 定義卷積的滑動步驟大小(每個維度的一個步驟大小),也就是中央節點之間的距離。 值必須是正整數的元組,其長度為套件組合的arity。 此 Tuple 的每個元件不得大於 KernelShape 的對應元件。 預設值是所有元件等於一的 Tuple。
共用:(選擇性) 定義卷積每個維度的權數共用。 此值可以是單一布爾值或布爾值的 Tuple,其長度為套件組合的 arity。 單一布爾值會擴充為長度正確的 Tuple,且所有元件都等於指定值。 預設值是包含所有 True 值的 Tuple。
MapCount:(選擇性) 定義卷積套件組合的功能對應數目。 此值可以是單一正整數或正整數的元組,其長度為配套的arity。 單一整數值會擴充為長度正確的 Tuple,其中第一個元件等於指定值,而其餘元件則等於一個。 預設值為一。 特徵對應總數是 Tuple 元件的乘積。 此元件總數的分解,決定特徵對應值在目的地節點中的分組方式。
權數:(選擇性) 定義套件組合的初始權數。 此值必須是浮點值的 Tuple,其長度為核心數目,也就是每個核心權數的次數,如本文稍後所定義。 默認權數會隨機產生。
有兩組屬性可控制填補,屬性互斥:
填補:(選擇性) 決定輸入是否應該使用 預設填補配置來填補。 此值可以是單一布爾值,或者它可以是布爾值的 Tuple,其長度為套件組合的 arity。
單一布爾值會擴充為長度正確的 Tuple,且所有元件都等於指定值。
如果維度的值為 True,則來源會在該維度中以零值單元格填補,以支援其他核心應用程式,使該維度中第一個和最後一個核心的中心節點是來源層中該維度中的第一個和最後一個節點。 因此,會自動決定每個維度中的「虛擬」節點數目,以將核心完全
(InputShape[d] - 1) / Stride[d] + 1
放入填補的來源層。如果維度的值是 False,則會定義核心,以便排除在每一端的節點數目相同(最多 1 個)。 此屬性的預設值是所有元件都等於 False 的 Tuple。
UpperPad 和 LowerPad:(選擇性) 對要使用的填補量提供更大的控制權。 重要:只有在未定義上述 Padding 屬性時,才能定義這些屬性。 這些值應該是整數值元組,其長度為套件組合的arity。 指定這些屬性時,會將「虛擬」節點新增至輸入層每個維度的下端和上端。 每個維度中新增至下端和上端的節點數目分別由LowerPad和 UpperPad[i] 決定。
若要確保核心只對應到「實際」節點,而不是「虛擬」節點,必須符合下列條件:
LowerPad 的每個元件必須嚴格小於
KernelShape[d]/2
。UpperPad 的每個元件不得大於
KernelShape[d]/2
。這些屬性的預設值是 Tuple,所有元件都等於 0。
Padding = true 設定允許所需的填補,以將核心的「中心」保留在「實際」輸入內。 這會變更計算輸出大小的數學運算。 一般而言,輸出大小 D 會計算為
D = (I - K) / S + 1
,其中I
是輸入大小、K
是核心大小、S
是步幅,而且/
是整數除法(四捨五入為零)。 如果您設定 UpperPad = [1, 1],則輸入大小I
實際上為 29,因此D = (29 - 5) / 2 + 1 = 13
。 不過,當 Padding = true 時,基本上I
會受到 顛簸K - 1
;因此D = ((28 + 4) - 5) / 2 + 1 = 27 / 2 + 1 = 13 + 1 = 14
。 藉由指定 UpperPad 和 LowerPad 的值,您得到的填補控制權會比您只設定 Padding = true 還要多。
如需卷積網路及其應用程式的詳細資訊,請參閱下列文章:
- http://d2l.ai/chapter_convolutional-neural-networks/lenet.html
- https://research.microsoft.com/pubs/68920/icdar03.pdf
共用套件組合
共用套件組合會套用類似於卷積連線的幾何,但它會使用預先定義的函式來來源節點值來衍生目的地節點值。 因此,共用套件組合沒有可訓練的狀態(權數或偏差)。 共用套件組合支持共用、MapCount 和權數以外的所有卷積屬性。
一般而言,相鄰共享單位所摘要的核心不會重疊。 如果 Stride[d] 等於每個維度中的 KernelShape[d],則取得的圖層是傳統本機共用層,這通常用於捲積神經網路。 每個目的地節點都會計算來源層中核心活動的最大或平均值。
下列範例說明共用套件組合:
hidden P1 [5, 12, 12]
from C1 max pool {
InputShape = [ 5, 24, 24];
KernelShape = [ 1, 2, 2];
Stride = [ 1, 2, 2];
}
- 套件組合的arity為3:也就是Tuple
InputShape
、KernelShape
和Stride
的長度。 - 來源層中的節點數目為
5 * 24 * 24 = 2880
。 - 這是傳統的本機共用層,因為 KernelShape 和 Stride 相等。
- 目的地層中的節點數目為
5 * 12 * 12 = 1440
。
如需共用層的詳細資訊,請參閱下列文章:
- https://www.cs.toronto.edu/~hinton/absps/imagenet.pdf (第3.4節)
- https://cs.nyu.edu/~koray/publis/lecun-iscas-10.pdf
- https://cs.nyu.edu/~koray/publis/jarrett-iccv-09.pdf
回應正規化套件組合
回應正規化是一種本機正規化配置,最初由 Geoffrey Hinton 等人在具有深度卷積神經網路的 ImageNet 分類論文中引進。
回應正規化可用來協助神經網路中的一般化。 當一個神經元在非常高的啟用層級引發時,局部回應正規化層會抑制周圍神經元的啟用層級。 這是使用三個參數 (, β
和 k
) 和卷積結構 (α
或鄰里形狀) 來完成。 目的層 y 中的每個神經元都會對應至來源層中的神經元 x 。 y 的啟用層級是由下列公式所指定,其中 f
是神經元的啟用層級,而 Nx
是核心(或包含 x 附近神經元的集合),如下列卷積結構所定義:
回應正規化配套支持共用、MapCount 和權數以外的所有卷積屬性。
如果核心包含與 x 相同對應中的神經元,則正規化配置稱為 相同的對應正規化。 若要定義相同的地圖正規化,InputShape 中的第一個座標必須具有值 1。
如果核心包含與 x 相同空間位置的神經元,但神經元位於其他對應中,則會跨對應正規化呼叫正規化配置。 這種類型的回應正規化實作一種橫向抑制形式,靈感來自真實神經元中發現的型別,為不同地圖上計算的神經元輸出之間的大激活水準創造競爭。 若要跨地圖正規化定義,第一個座標必須是大於一個且不大於地圖數目的整數,而座標的其餘部分必須具有值 1。
由於回應正規化套件組合會將預先定義的函式套用至來源節點值,以判斷目的地節點值,因此它們沒有可定型的狀態(權數或偏差)。
注意
目的地層中的節點會對應至核心中央節點的神經元。 例如,如果 KernelShape[d]
為奇數,則 KernelShape[d]/2
對應至中央核心節點。 如果 KernelShape[d]
為 ,則中央節點位於 KernelShape[d]/2 - 1
。 因此,如果 Padding[d]
為 False,則第一個和最後一個 KernelShape[d]/2
節點在目的地層中沒有對應的節點。 若要避免這種情況,請將Padding定義為 [true、true、...、true]。
除了稍早所述的四個屬性之外,回應正規化套件組合也支援下列屬性:
- Alpha:(必要) 指定與上一個公式中對應的
α
浮點值。 - Beta:(必要) 指定與上一個公式中對應的
β
浮點值。 - Offset:(選擇性) 指定與上一個公式中對應的
k
浮點值。 預設為 1。
下列範例會使用下列屬性來定義回應正規化套件組合:
hidden RN1 [5, 10, 10]
from P1 response norm {
InputShape = [ 5, 12, 12];
KernelShape = [ 1, 3, 3];
Alpha = 0.001;
Beta = 0.75;
}
- 來源圖層包含五個地圖,每個地圖維度為12x12,總計1440個節點。
- KernelShape 的值表示這是相同的地圖正規化圖層,其中鄰里是 3x3 矩形。
- Padding 的預設值為 False,因此目的層在每個維度中只有 10 個節點。 若要在對應至來源層中每個節點的目的地層中包含一個節點,請新增 Padding = [true、true、true];並將 RN1 的大小變更為 [5, 12, 12]。
共用宣告
Net# 選擇性地支援使用共享權數定義多個套件組合。 如果兩個組合的結構相同,則可以共用任何兩個套件組合的權數。 下列語法會定義具有共享權數的套件組合:
share-declaration:
share { layer-list }
share { bundle-list }
share { bias-list }
layer-list:
layer-name , layer-name
layer-list , layer-name
bundle-list:
bundle-spec , bundle-spec
bundle-list , bundle-spec
bundle-spec:
layer-name => layer-name
bias-list:
bias-spec , bias-spec
bias-list , bias-spec
bias-spec:
1 => layer-name
layer-name:
identifier
例如,下列共用宣告會指定圖層名稱,指出應該共享權數和偏差:
Const {
InputSize = 37;
HiddenSize = 50;
}
input {
Data1 [InputSize];
Data2 [InputSize];
}
hidden {
H1 [HiddenSize] from Data1 all;
H2 [HiddenSize] from Data2 all;
}
output Result [2] {
from H1 all;
from H2 all;
}
share { H1, H2 } // share both weights and biases
- 輸入功能會分割成兩個相等大小的輸入層。
- 隱藏層接著會計算兩個輸入層的較高層級特徵。
- 共用宣告會 指定 H1 和 H2 必須以與各自輸入相同的方式計算。
或者,這可以使用兩個不同的共用宣告來指定,如下所示:
share { Data1 => H1, Data2 => H2 } // share weights
<!-- -->
share { 1 => H1, 1 => H2 } // share biases
只有當圖層包含單一套件組合時,才可以使用簡短格式。 一般而言,只有在相關結構相同時,才能進行共用,這表示它們的大小相同、卷積幾何相同等等。
Net# 使用方式的範例
本節提供一些範例,說明如何使用 Net# 來新增隱藏層、定義隱藏層與其他圖層互動的方式,以及建置卷積網路。
定義簡單的自定義類神經網路:「Hello World」 範例
這個簡單的範例示範如何建立具有單一隱藏層的類神經網路模型。
input Data auto;
hidden H [200] from Data all;
output Out [10] sigmoid from H all;
此範例說明一些基本命令,如下所示:
- 第一行會定義輸入層(名為
Data
)。 當您使用auto
關鍵詞時,類神經網路會自動在輸入範例中包含所有功能數據行。 - 第二行會建立隱藏層。 名稱
H
會指派給具有 200 個節點的隱藏層。 此層已完全連接到輸入層。 - 第三行會定義輸出層(名為
Out
),其中包含10個輸出節點。 如果神經網路用於分類,則每個類別都有一個輸出節點。 關鍵詞 sigmoid 表示輸出函式會套用至輸出層。
定義多個隱藏層:計算機視覺範例
下列範例示範如何使用多個自定義隱藏層來定義稍微複雜一點的類神經網路。
// Define the input layers
input Pixels [10, 20];
input MetaData [7];
// Define the first two hidden layers, using data only from the Pixels input
hidden ByRow [10, 12] from Pixels where (s,d) => s[0] == d[0];
hidden ByCol [5, 20] from Pixels where (s,d) => abs(s[1] - d[1]) <= 1;
// Define the third hidden layer, which uses as source the hidden layers ByRow and ByCol
hidden Gather [100]
{
from ByRow all;
from ByCol all;
}
// Define the output layer and its sources
output Result [10]
{
from Gather all;
from MetaData all;
}
此範例說明類神經網路規格語言的數個功能:
- 結構有兩個輸入層和
Pixels
MetaData
。 - 此
Pixels
層是兩個連接配套的來源層,具有目的地層和ByRow
ByCol
。 - 層
Gather
和Result
是多個連線組合中的目的地層。 - 輸出層是兩個連接組合中的目的地層
Result
;一個是第二層隱藏Gather
層做為目的地層,另一個則是輸入層MetaData
做為目的地層。 - 隱藏層
ByRow
和ByCol
,使用述詞表達式來指定篩選的連線能力。 更精確地說,位於ByRow
[x, y] 的節點會連接到中Pixels
第一個索引座標等於節點第一個座標 x 的節點。 同樣地,位於 [x, y] 的ByCol
節點會連接到 中Pixels
具有第二個索引座標之一節點的第二個座標 y 中的節點。
定義多類別分類的捲積網路:數位辨識範例
下列網路的定義是設計來辨識數位,並說明自定義類神經網路的一些進階技術。
input Image [29, 29];
hidden Conv1 [5, 13, 13] from Image convolve
{
InputShape = [29, 29];
KernelShape = [ 5, 5];
Stride = [ 2, 2];
MapCount = 5;
}
hidden Conv2 [50, 5, 5]
from Conv1 convolve
{
InputShape = [ 5, 13, 13];
KernelShape = [ 1, 5, 5];
Stride = [ 1, 2, 2];
Sharing = [false, true, true];
MapCount = 10;
}
hidden Hid3 [100] from Conv2 all;
output Digit [10] from Hid3 all;
結構具有單一輸入層
Image
關鍵詞
convolve
表示名為Conv1
和Conv2
的圖層是捲積層。 每一個圖層宣告後面都會接著卷積屬性的清單。網路有第三個隱藏層,
Hid3
它完全連接到第二個隱藏層。Conv2
輸出層
Digit
只會連接到第三個隱藏層Hid3
。 關鍵字all
表示輸出層已完全連線到Hid3
。卷積的arity為三:元組
InputShape
、、KernelShape
Stride
和Sharing
的長度。每個核心權數為
1 + KernelShape\[0] * KernelShape\[1] * KernelShape\[2] = 1 + 1 * 5 * 5 = 26
。 或26 * 50 = 1300
。您可以計算每個隱藏層中的節點,如下所示:
NodeCount\[0] = (5 - 1) / 1 + 1 = 5
NodeCount\[1] = (13 - 5) / 2 + 1 = 5
NodeCount\[2] = (13 - 5) / 2 + 1 = 5
您可以使用圖層 [50, 5, 5, 5] 的宣告維度來計算節點總數,如下所示:
MapCount * NodeCount\[0] * NodeCount\[1] * NodeCount\[2] = 10 * 5 * 5 * 5
因為
Sharing[d]
只有 False,d == 0
因此核心數目為MapCount * NodeCount\[0] = 10 * 5 = 50
。
通知
自定義類神經網路架構的 Net# 語言是由 Shon Katzenberger (Architect, 機器學習) 和 Alexey Kamenev (軟體工程師,Microsoft Research) 所 Microsoft開發。 它會在內部用於機器學習專案和應用程式,範圍從影像偵測到文字分析。 如需詳細資訊,請參閱 機器學習 Studio 中的類神經網路 - Net 簡介#