2016 年 3 月

第 31 卷,第 3 期

本文章是由機器翻譯。

測試回合 - 類神經網路迴歸

James McCaffrey

James McCaffrey迴歸問題的目標是要預測數值變數 (通常稱為相依變數) 根據一或多個預測變數 (獨立變數),它可以是數值或類別值的值。例如,您可能想要預測的人,根據年齡、 性別 (男性或女性) 和年的教育年收入。

最簡單形式的迴歸稱為線性迴歸 (LR)。長程預測方程式可能看起來像這樣 ︰ 收入 = 17.53 + (5.11 * 年齡) + (-2.02 * 男性) + (-1.32 * 女性) + (6.09 * 教育)。雖然長程非常有用的一些問題,在許多情況下它不是有效。但是有其他常見的迴歸類型 — 多項式迴歸、 一般線性模型的迴歸和類神經網路迴歸 (NNR)。在論證上,最後的迴歸類型是最強大的迴歸的形式。

最常見的類神經網路 (NN) 類型是一個用來預測類別變數。比方說,您可能想要預測某個人的政治傾斜 (保守中, 度,盡量) 根據年齡、 收入和性別等因素。NN 分類有 n 個輸出節點,其中 n 是相依變數可以接受的值數目。N 個輸出節點的值總和為 1.0,並可以鬆散解譯為機率。因此,為了預測政治傾斜,NN 分類器會有三個輸出節點。如果輸出節點值 (0.24、 0.61、 0.15),NN 分類器預測 「 中等 」 中間節點發生的最大機率。

在 NN 迴歸,NN 會擁有包含相依的數值變數的預測的值的單一輸出節點。因此,預測年收入範例中,有三個輸入的節點 (一個用於年齡、 性別的其中一個其中男性 =-1 」 和 「 女 = + 1,而另一個用於教育的),和一個輸出節點 (年收入)。

看一下示範程式中為適合用來了解 NN 迴歸的是,並在這篇文章所朝的方向,請參閱 [圖 1。而不是解決實際問題,以保持為 NN 迴歸的概念盡可能清楚示範的目標是建立 NN 模型來預測的正弦函數值。萬一三角知識有點荒廢了,會顯示圖形的正弦函數 [圖 2。Sin 函式接受為正的無限大負無限大方向從單一實際輸入的值,並傳回介於-1.0 和 +1.0。Sin 函式會傳回 0 時,x = 0.0,x = pi (~ 3.14),x = 2 * pi、 x = 3 * pi 等等。Sin 函式是非常困難模型功能。

類神經網路迴歸示範
[圖 1 類神經網路迴歸示範

Sin (x) 函式
[圖 2 sin (x) 函式

示範一開始會以程式設計方式產生要用於培訓 NN 模型 80 資料項目。80 訓練項目有隨機的輸入值介於 0 到 6.4 x (稍微超過 2 * pi) 和對應的 y 值,也就是 sin (x)。

示範建立 1-12-1 NN,也就是具有一個輸入節點 (x) NN 12 隱藏處理節點 (有效地定義預測方程式) 和一個輸出節點 (x 預測正弦)。當使用附屬公司,總是實驗涉及;透過反覆嘗試偵測到的隱藏節點數目。

NN 分類器有兩個啟動函式,一個用於隱藏的節點,一個用於輸出節點。分類器的輸出節點啟動函式幾乎都是 softmax 函式,因為 softmax 產生總和為 1.0 的值。分類器的隱藏的節點啟動函式通常是羅吉斯 sigmoid 函數或雙曲正切函數 (縮寫雙曲正切)。但是在 NN 迴歸,隱藏的節點啟動函式,但沒有輸出節點啟動函式。示範 NN 隱藏的節點啟動使用 tanh 函式。

NN 輸出取決於其輸入的值和一組稱為加權和偏差的常數。由於偏差其實只是特殊類型的權數,「 加權 」 一詞是有時會用來參考兩者。使用類神經網路 i 輸入節點、 j 隱藏節點和 k 總共有輸出節點 (我 * j) j + (j * k) + k 加權和偏差。因此 1-12-1 示範 NN 具有 (1 * 12) + 12 + (12 * 1) + 1 = 37 加權和偏差。

決定的加權和偏差值的程序稱為 「 定型模型 」。其概念是,嘗試不同值的加權和偏差判斷計算的輸出值的 NN 密切相符的訓練資料的已知正確的輸出值。

有數種不同的演算法可以用來定型 NN。到目前為止最常見的方法是使用後端傳播演算法。反向傳播是反覆的程序,其中的值的加權和偏差緩慢變更,使 NN 通常會計算更精確的輸出值。

兩個必要的參數 (的反覆項目與學習速率的最大數目) 和一個選用參數 (動量頻率),則會使用反向傳播。MaxEpochs 參數設定的演算法反覆運算次數限制。LearnRate 參數控制多少加權和偏差值可以變更每個反覆項目中。趨勢電子報參數加速訓練,並可協助避免後端傳播演算法阻塞不佳的解決方案。示範設定的值為 10000 maxEpochs、 learnRate 為 0.005,值和的值為 0.001 趨勢電子報。透過反覆嘗試已判斷這些值。

使用後端傳播演算法 NN 訓練,當有可用的三種類型。在批次來支援傳播、 訓練的所有項目會先檢查,然後所有的加權和偏差值會調整。在隨機反向傳播 (也稱為線上反向傳播) 會檢查每個訓練項目之後,所有的加權和偏差值會調整。迷你批次中傳播,所有加權和偏差值會在檢查的訓練項目指定的分數之後進行都調整。示範程式使用的是最常見的變體隨機反向傳播。

示範程式會在每 1000 訓練 epoch 顯示錯誤的量值。請注意,跳位元的錯誤值。之後完成訓練課程,示範顯示 37 加權和偏差定義 NN 模型的值。NN 加權和偏差的值沒有任何明顯的解譯,但請務必檢查來檢查不正確的結果,例如,當一個加權極大的值,且所有其他的加權是接近零的值。

示範程式結束時,會評估 NN 模型。NN 預測值的 sin (x) 的 x = pi,pi / 2 和 3 * pi / 2 是只要 0.02 正確的值。預測的值 sin(6 * pi) 太遠是從正確的值。這是預期的結果,因為 NN 定型只是用來預測 sin (x) 的 x 值介於 0 到 2 之間的值,但是 * pi。

本文假設您有最少的中繼層級的程式設計技巧,但不會假設您了解太多類神經網路迴歸。使用 C# 程式碼示範程式,但您不應該有重構程式碼以另一種語言,例如 Visual Basic 或 Perl 很多麻煩。示範程式會呈現在本文中,將整個太長,而隨附的程式碼下載中提供完整的來源。所有一般錯誤檢查已移除從示範以保留小的程式碼和重要概念盡可能清楚的大小。

示範程式結構

若要建立示範程式,我啟動 Visual Studio,並選取 [從檔案 [C# 主控台應用程式範本 |新 |專案功能表動作。我使用 Visual Studio 2015,但示範有沒有顯著的.NET 相依性,以便能使用任何版本的 Visual Studio。我命名為 NeuralRegression 的專案。

範本程式碼載入 [編輯器] 視窗之後,請在 [方案總管] 視窗中已選取檔案 Program.cs,以滑鼠右鍵按一下它,並重新命名了稍微更具描述性的 NeuralRegressionProgram.cs。我可以自動重新命名為我的類別程式的 Visual Studio。在編輯器的程式碼頂端,我刪除未使用的命名空間的所有參考留下只是最上層系統命名空間的參考。

示範程式,以節省空間,一些次要的編輯的整體結構所示 [圖 3。所有控制陳述式都是 Main 方法中。所有的類神經網路迴歸功能都包含在程式定義的類別,名為 NeuralNetwork。

[圖 3 類神經網路迴歸程式結構

using System;
namespace NeuralRegression
{
  class NeuralRegressionProgram
  {
    static void Main(string[] args)
    {
      Console.WriteLine("Begin NN regression demo");
      Console.WriteLine("Goal is to predict sin(x)");
      // Create training data
      // Create neural network
      // Train neural network
      // Evaluate neural network
      Console.WriteLine("End demo");
      Console.ReadLine();
    }
    public static void ShowVector(double[] vector,
      int decimals, int lineLen, bool newLine) { . . }
    public static void ShowMatrix(double[][] matrix,
      int numRows, int decimals, bool indices) { . . }
  }
  public class NeuralNetwork
  {
    private int numInput; // Number input nodes
    private int numHidden;
    private int numOutput;
    private double[] inputs; // Input nodes
    private double[] hiddens;
    private double[] outputs;
    private double[][] ihWeights; // Input-hidden
    private double[] hBiases;
    private double[][] hoWeights; // Hidden-output
    private double[] oBiases;
    private Random rnd;
    public NeuralNetwork(int numInput, int numHidden,
      int numOutput, int seed) { . . }
    // Misc. private helper methods
    public void SetWeights(double[] weights) { . . }
    public double[] GetWeights() { . . }
    public double[] ComputeOutputs(double[] xValues) { . . }
    public double[] Train(double[][] trainData,
      int maxEpochs, double learnRate,
      double momentum) { . . }
  } // class NeuralNetwork
} // ns

在 Main 方法中,這些陳述式來建立定型資料 ︰

int numItems = 80;
double[][] trainData = new double[numItems][];
Random rnd = new Random(1);
for (int i = 0; i < numItems; ++i) {
  double x = 6.4 * rnd.NextDouble();
  double sx = Math.Sin(x);
  trainData[i] = new double[] { x, sx };
}

一般的規則與類神經網路更多的訓練資料處理時有更好。建立模型的正弦函數值介於 0 和 2 x * pi,我需要至少 80 的項目,以取得正確的結果。選擇的種子值為 1 的隨機數字的物件是任意的。訓練資料會儲存在陣列的陣列樣式矩陣。在實際案例中,您可能會從文字檔讀取培訓資料。

這些陳述式來建立類神經網路 ︰

int numInput = 1;
int numHidden = 12;
int numOutput = 1;
int rndSeed = 0;
NeuralNetwork nn = new NeuralNetwork(numInput,
  numHidden, numOutput, rndSeed);

因為目標正弦函數接受單一值,是只有一個輸入的節點。最類神經網路迴歸問題,您會擁有數個輸入預測獨立變數的每個節點。最類神經網路迴歸問題中只有單一輸出節點,但可以預測兩個或多個數值。

NN 需要隨機物件來初始化加權值,並將訓練項目處理的順序。示範 NeuralNetwork 建構函式會接受內部隨機物件的種子值。使用 0 值,是任意的。

這些陳述式被訓練類神經網路 ︰

int maxEpochs = 10000;
double learnRate = 0.005;
double momentum  = 0.001;
double[] weights = nn.Train(trainData, maxEpochs,
  learnRate, momentum);
ShowVector(weights, 4, 8, true);

NN 是極為敏感的訓練參數值。即使很小的變更可能會產生完全不同的結果。

示範程式會評估所產生之 NN 模型的品質預測 sin (x) 的三個標準值。陳述式,以一些次要的編輯是 ︰

double[] y = nn.ComputeOutputs(new double[] { Math.PI });
Console.WriteLine("Predicted =  " + y[0]);
y = nn.ComputeOutputs(new double[] { Math.PI / 2 });
Console.WriteLine("Predicted =  " + y[0]);
y = nn.ComputeOutputs(new double[] { 3 * Math.PI / 2.0 });
Console.WriteLine("Predicted = " + y[0]);

請注意,示範 NN 會儲存其輸出陣列中的輸出節點,即使只是此範例中的單一輸出值。傳回陣列,可讓您預測多個值,而不會變更原始碼。

示範結束時,會預測也超出範圍的訓練資料的 x 值的 sin (x) ︰

y = nn.ComputeOutputs(new double[] { 6 * Math.PI });
Console.WriteLine("Predicted =  " + y[0]);
Console.WriteLine("End demo");

在大部分的 NN 分類案例中,您可以呼叫方法會計算分類精確度,也就是正確的預測分割總數的預測數目。這可能是因為類別的輸出值是正確或不正確。但當使用 NN 迴歸,沒有標準方法來定義精確度。如果您想要計算某種程度的精確度,它將會問題相關。例如,預測 sin (x) 您可以任意定義正確預測為 0.01 的正確值內的其中一個。

輸出值的計算

大部分的設計分類 NN,另一個用於迴歸之間的主要差異都會計算輸出與培訓模型的方法。類別 NeuralNetwork 方法的定義以 ComputeOutputs 開始 ︰

public double[] ComputeOutputs(double[] xValues)
{
  double[] hSums = new double[numHidden];
  double[] oSums = new double[numOutput];
...

方法會接受保留預測獨立變數的值的陣列。本機變數 hSums 和 oSums 是臨時保存初步 (之前啟用) 值的隱藏和輸出節點的陣列。接下來,獨立變數的值複製到類神經網路的輸入節點 ︰

for (int i = 0; i < numInput; ++i)
  this.inputs[i] = xValues[i];

然後初步隱藏的節點會計算的值乘以每個輸入值,其對應隱藏輸入的加權,並累積 ︰

for (int j = 0; j < numHidden; ++j)
  for (int i = 0; i < numInput; ++i)
    hSums[j] += this.inputs[i] * this.ihWeights[i][j];

接下來,新增隱藏的節點的偏差值 ︰

for (int j = 0; j < numHidden; ++j)
  hSums[j] += this.hBiases[j];

隱藏節點的值取決於將隱藏的節點啟用函數套用至每個初步的總和 ︰

for (int j = 0; j < numHidden; ++j)
  this.hiddens[j] = HyperTan(hSums[j]);

接下來,會計算輸入節點的初步值乘以每個隱藏的節點值以其對應的隱藏-到-輸出權數,並累積 ︰

for (int k = 0; k < numOutput; ++k)
  for (int j = 0; j < numHidden; ++j)
    oSums[k] += hiddens[j] * hoWeights[j][k];

然後新增隱藏的節點的偏差值 ︰

for (int k = 0; k < numOutput; ++k)
  oSums[k] += oBiases[k];

到目前為止,迴歸網路的輸出節點值的計算是完全相同的分類器網路的輸出節點值的計算。但是,在分類器,最後輸出節點的值會計算方式將 softmax 啟用函數套用至每個累計總和。迴歸網路啟動的函式會套用。因此,ComputeOutputs 結束時,會直接複製 oSums 值的方法可用來輸出節點的陣列 ︰

...
  Array.Copy(oSums, this.outputs, outputs.Length);
  double[] retResult = new double[numOutput]; // Could define a GetOutputs
  Array.Copy(this.outputs, retResult, retResult.Length);
  return retResult;
}

為了方便起見,輸出節點中的值也會複製到本機傳回陣列,他們可以輕鬆地存取而不呼叫 GetOutputs 某種類型的方法。

訓練使用後端傳播演算法 NN 分類器,會使用兩個啟動函式的微積分衍生項目。隱藏節點的程式碼看起來像 ︰

for (int j = 0; j < numHidden; ++j) {
  double sum = 0.0; // sums of output signals
  for (int k = 0; k < numOutput; ++k)
    sum += oSignals[k] * hoWeights[j][k];
  double derivative = (1 + hiddens[j]) * (1 - hiddens[j]);
  hSignals[j] = sum * derivative;
}

名為衍生的本機變數的值是 tanh 函式微積分衍生項目,以及來自相當複雜的理論。包含輸出節點啟動函式的結果計算 NN 分類器是 ︰

for (int k = 0; k < numOutput; ++k) {
  double derivative = (1 - outputs[k]) * outputs[k];
  oSignals[k] = (tValues[k] - outputs[k]) * derivative;
}

在這裡,本機變數的衍生物件的值是 softmax 函數微積分衍生項目。不過,由於 NN 迴歸不使用啟用函式的輸出節點,程式碼是 ︰

for (int k = 0; k < numOutput; ++k) {
  double derivative = 1.0;
  oSignals[k] = (tValues[k] - outputs[k]) * derivative;
}

當然,乘以 1.0 沒有任何作用,您無法直接丟掉衍生詞彙。另一個方式來思考這是該在 NN 迴歸,輸出節點啟動函式是識別函式 f (x) = x。Identity 函數微積分衍生項目,是常數 1.0。

總結

示範程式碼和本文中的說明應該足以讓您立即啟動及執行,如果您想要探索一或多個數值的預測變數使用類神經網路迴歸。如果您有是類別預測變數,您必須編碼變數。類別預測變數可以採用兩個可能的值,例如性別 (男性,女性),您會編碼為-1 和 + 1 另一個值。

對於類別預測變數可以採取三個或多個可能的值,您會使用所謂 1-of-(N-1) 編碼方式。比方說,如果預測工具變數是可接受的四個可能的值 (紅色、 藍色、 綠色、 黃色),按一下其中一個紅色的色彩會編碼為 (1,0,0) 的藍色 (0、 1、 0) 為綠色,為 (0,0,1) 和黃色] 做為-1,-1 (-1)。


Dr。James McCaffreyRedmond,華盛頓中的 Microsoft Research 的運作方式他曾在包括 Internet Explorer 和 Bing 的數個 Microsoft 產品。Dr.McCaffrey 可以到達jammc@microsoft.com

感謝下列 Microsoft 技術專家檢閱這份文件 ︰ Gaz Iqbal 和 Umesh Madan