本文章是由機器翻譯。

測試回合

徑向基底函數網路訓練

James McCaffrey

下载代码示例

徑向基函數 (RBF) 網路是一個軟體系統,可以對資料進行分類和做出的預測。RBF 網路有一些表面的相似性到神經網路,但其實很不同。RBF 網路接受一個或多個數位輸入,並生成一個或多個數位輸出。由輸入的值,再加上一組參數稱為 RBF 郵編、 稱為 RBF 寬度一套、 稱為 RBF 砝碼一套稱為 RBF 偏見一套確定的輸出值。

為簡單起見的術語,RBF 權重和偏置值的組合,有時統稱為權重。在其中一詞權重通常使用的上下文使意思更清楚。更多的資訊,請參閱我的文章,"徑向基礎功能網路為程式師"在 10 月的 MSDN 雜誌問題 (msdn.microsoft.com/magazine/dn451445)。

當使用 RBF 網路進行分類和預測,面臨的挑戰是為郵編、 寬度、 重量和偏見找到一組值,以便計算產出最佳匹配一組已知的產出。這被稱為訓練 RBF 網路。雖然有研究者 RBF 網路在 1988 年推出以來,並不多解釋了如何實現 RBF 網路培訓的實際指導。這篇文章將介紹和描述完整演示 RBF 網路。

看一看在演示程式圖 1。該程式創建 RBF 模型所預測的鳶尾花 ("setosa","雜色"或"葵") 從花的萼片長度和寬度,和花瓣長度和寬度的四個數值的物種。該演示程式的資料來源包括知名 150 項基準集稱為費雪的虹膜資料的子集的 30 項。預處理過的 30 資料項目目。所以,值小於零均值較短比平均長度或寬度和大於零的值意味著長比平均長度或寬度正常了四個數值 x 值。Y 值為物種已編碼 (0,0,1),作為 (0,1,0) 或 (1,0,0) 為 setosa,雲芝和葵,分別。


圖 1 徑向基函數網路的演示程式

該演示將 30 項資料集拆分成 24 項集,用於培訓。也是為測試/評估生成的 RBF 模型設置定型六個專案。它具現化 RBF 網路有四個輸入節點 (一個用於輸入的資料的每個值),五個隱藏的處理節點和三個輸出節點 (一個用於每個輸出資料值)。確定隱藏節點的最佳數目是主要的試驗和錯誤的問題。五在演示中的選擇是任意的。

圖 1 你可以看到訓練 RBF 網路由三個階段組成。第一階段確定的郵編。可以郵編視為代表 x 值從訓練資料中選擇。RBF 網路需要一個質心隱藏的每個節點,因此該演示需要五個郵編。訓練演算法選擇 x 值從訓練資料項目目 [9],[19],[21] [20] 和 [4]。換句話說,第一次的質心是 (-0.362、-2.019、 0.074、 0.112)。

第二階段培訓確定寬度。你可以認為的寬度作為描述郵編之間的距離值。RBF 網路需要一個寬度為隱藏的每個節點。演示計算單一常見寬度為所有的五個隱藏節點的值 3.3318,而不是計算五起不同的寬度。

培訓的第三階段確定的 RBF 權重和偏置值。你可以認為的權重和偏置值作為數位常量。如果 RBF 網路有 NI 的輸入節點數、 NH 的隱藏節點數和沒有數位輸出節點,則該網路需要 (NH * 無) 重量值和無偏倚的值。所以,因為演示 RBF 網路有 4-5-3 的體系結構,它需要 5 * 3 = 15 重量再加上三個偏見,總共 18 權重和偏置值。該演示程式使用粒子群優化演算法 (PSO) 來確定 18 重量和偏見。

你訓練使用 24 項訓練資料集的演示 RBF 網路後,你將六項測試資料集送入網路。在此示例中,RBF 網路正確預測的五個六個測試專案,0.8333 分類準確性的物種。

本文假定您擁有先進的與 C# 的程式設計技巧和徑向基函數網路輸入過程輸出機制基本熟悉。我在我 10 月的專欄中討論了這一機制。太長,其整體在這篇文章,介紹該演示程式的原始程式碼是完整代碼下載就是可在 archive.msdn.microsoft.com/mag201312TestRun

程式的總體結構

若要創建該演示程式,我發起Visual Studio2012年和創建 C# 主控台應用程式命名為 RadialNetworkTrain。演示沒有任何重大的.NET 相關性,所以任何版本的Visual Studio工作。載入的範本代碼後,則在解決方案資源管理器中,我更具描述性的 RadialTrainProgram.cs 和Visual Studio將自動重命名重命名 Program.cs 檔的視窗相關聯類程式。在原始程式碼的頂部,刪除所有不必要的引用的.NET 命名空間,離開只是對 System 命名空間的引用。

整體的程式結構,與刪除一些 WriteLine 語句和一些少量的編輯,提交在圖 2。除了程式類,房子的主要方法、 演示了一個 RadialNetwork 類,封裝 RBF 網路建立和培訓、 顆粒類的定義與 RBF 訓練演算法,用於確定權重和偏置值,使用粒子物件和一個傭工類,包含實用程式顯示的方法。

圖 2 總體 RBF 網路演示的程式結構

using System;
namespace RadialNetworkTrain
{
  class RadialTrainProgram
  {
    static void Main(string[] args)
    {
      Console.WriteLine("Begin radial basis function (RBF) network training demo");
      double[][] allData = new double[30][];
      allData[0] = new double[] { -0.784, 1.255, -1.332, -1.306, 0, 0, 1 };
      allData[1] = new double[] { -0.995, -0.109, -1.332, -1.306, 0, 0, 1 };
      // Etc.
allData[28] = new double[] { 0.904, -1.473, 1.047, 0.756, 1, 0, 0 };
      allData[29] = new double[] { 1.431, 1.528, 1.209, 1.659, 1, 0, 0 };
      Console.WriteLine("First four and last line of normalized, encoded input data:");
      Helpers.ShowMatrix(allData, 4, 3, true, true);
      double[][] trainData = null;
      double[][] testData = null;
      int seed = 8; // Gives a good demo
      GetTrainTest(allData, seed, out trainData, out testData);
      Helpers.ShowMatrix(trainData, trainData.Length, 3, true, false);
      Helpers.ShowMatrix(testData, testData.Length, 3, true, false);
      int numInput = 4;
      int numHidden = 5;
      int numOutput = 3;
      RadialNetwork rn = new RadialNetwork(numInput, numHidden, numOutput);
      Console.WriteLine("Beginning RBF training");
      int maxIterations = 100; // Max for PSO
      double[] bestWeights = rn.Train(trainData, maxIterations);
      Console.WriteLine("Evaluating RBF accuracy on the test data");
      rn.SetWeights(bestWeights);
      double acc = rn.Accuracy(testData);
      Console.WriteLine("Classification accuracy = " + acc.ToString("F4"));
      Console.WriteLine("End RBF network training demo");
    }
    static void GetTrainTest(double[][] allData, int seed,
      out double[][] trainData, out double[][] testData) { .
.
}
  }
  public class RadialNetwork
  {
    private static Random rnd = null;
    private int numInput;
    private int numHidden;
    private int numOutput;
    private double[] inputs;
    private double[][] centroids;
    private double[] widths;
    private double[][] hoWeights;
    private double[] oBiases;
    private double[] outputs;
    public RadialNetwork(int numInput, int numHidden, int numOutput) { .
.
}
    private static double[][] MakeMatrix(int rows, int cols) { .
.
}
    public void SetWeights(double[] weights) { .
.
}
    public double[] GetWeights() { .
.
}
    private double MeanSquaredError(double[][] trainData,
      double[] weights) { .
.
}
    public double Accuracy(double[][] testData) { .
.
}
    private static int MaxIndex(double[] vector) { .
.
}
    public double[] ComputeOutputs(double[] xValues) { .
.
}
    private static double[] Softmax(double[] rawOutputs) { .
.
}
    public double[] Train(double[][] trainData, int maxIterations) { .
.
}
    private void DoCentroids(double[][] trainData) { .
.
}
    private static double AvgAbsDist(double[] v1, double[] v2,
      int numTerms) { .
.
}
    private int[] DistinctIndices(int n, int range) { .
.
}
    private void DoWidths(double[][] centroids) { .
.
}
    private double[] DoWeights(double[][] trainData, int maxIterations) { .
.
}
    private static double EuclideanDist(double[] v1, double[] v2,
      int numTerms) { .
.
}
    private static void Shuffle(int[] sequence) { .
.
}
  }
  public class Particle
  {
    // Implementation here
  }
  public class Helpers
  {
    // Implementation here
  }
}

類 RadialNetwork 不是很複雜的程式結構建議,因為大多數的類方法是傭工。 方法列車執行調用的傭工,DoCentroids,DoWidths 和 DoWeights 的三個階段的培訓過程。 AvgAbsDist 和 DistinctIndices 的私有方法是傭工為 DoCentroids。 方法 DoWeights 在每次反覆運算粒子群優化演算法通過按不同的順序使用洗牌過程培訓資料項目目的私有方法。

演示的心臟是相當簡單的。 第一,歸一化和編碼資料設置:

double[][] allData = new double[30][];
allData[0] = new double[] { -0.784, 1.255, -1.332, -1.306, 0, 0, 1 };
allData[1] = new double[] { -0.995, -0.109, -1.332, -1.306, 0, 0, 1 };
// Etc.
allData[28] = new double[] { 0.904, -1.473, 1.047, 0.756, 1, 0, 0 };
allData[29] = new double[] { 1.431, 1.528, 1.209, 1.659, 1, 0, 0 };

這裡的資料是硬編碼為簡單起見。 在大多數情況下您的資料將存儲在一個文字檔或 SQL 表。 下一步,資料被分割成培訓和測試子集:

double[][] trainData = null;
double[][] testData = null;
int seed = 8;
GetTrainTest(allData, seed, out trainData, out testData);

Rbf 神經網路進行具現化:

int numInput = 4;
int numHidden = 5;
int numOutput = 3;
RadialNetwork rn = new RadialNetwork(numInput,
   numHidden, numOutput);

如在上一節中所述,必須由試驗和錯誤基本上確定最佳的隱藏的處理節點數。 培訓網路:

int maxIterations = 100;
double[] bestWeights = rn.Train(trainData, maxIterations);

並且,最後,計算生成的模型:

rn.SetWeights(bestWeights);
double acc = rn.Accuracy(testData);
Console.WriteLine("Classification accuracy = " +
  acc.ToString("F4"));

BestWeights 陣列保存的 RBF 權重和偏置值所確定的培訓方法。方法 SetWeights 載入這些權重和偏置值。你不需要有郵編和顯式載入,因為由火車方法設置這些值的寬度。

徑向基函數網路輸入-過程-輸出

若要瞭解 RBF 網路培訓過程,您需要瞭解 RBF 網路輸入-­進程輸出機制。中的關係圖圖 3 顯示如何演示 RBF 網路計算的輸出測試的資料項目目 [1] = (0.498,0.709 提高,0.452 0.482) 後經過了網路。輸入的 x 值傳遞到隱藏的每個節點。每個隱藏的節點計算其本地輸出使用其自己的質心和寬度。


圖 3 徑向基函數網路架構

例如,在最頂端隱藏的節點的質心是 (-0.362、-2.019、 0.074、 0.112) 和它的寬度是 3.3318。隱藏的每個節點的本地輸出然後用於通過加權的求和的投入,再加上偏置值計算確定初步的輸出值。例如,如果 hOutput [0] 表示隱藏節點 0 的本地輸出,然後在最頂層輸出節點的初步輸出是 (hOutput [0] * w[0][0]) + (hOutput [1] * w[1][0]) + (hOutput [2] * w[2][0]) + (hOutput [3] * w[3][0]) + (hOutput [4] * w[4][0]) + 偏見 [0] =-12.7999。

三個初步輸出值的計算後,他們會被轉換成使用 softmax 函數的最後輸出值。這個想法是要修改初步輸出值,所以,最終的輸出值將所有介於 0.0 和 1.0,並總和為 1.0。這樣,可以寬鬆地解釋為概率的輸出值。

圖 3,最後產出是 0.0237 0.6865 0.2897)。因為中間節點具有最高的價值,它被解釋為 1,其他兩個值被解釋為 0,給推斷出的輸出的 (0,1,0)。記得的測試資料是 (0.482 0.709 提高、 0.452、 0.498、 0.000 1.000,0.000),那裡的第一次四個值是投入和最後三個值有目標值,所以,RBF 網路使得正確預測的物種 (Iris 雲芝在這種情況下)。現在的問題是:RBF 網路郵編、 寬度、 重量和偏見的值是從哪裡來的?

確定 RBF 網路郵編

RadialNetwork 類的火車方法是基本上做所有的實際工作的三個説明器方法的包裝:

public double[] Train(double[][] trainData, int maxIterations)
{
  DoCentroids(trainData);
  DoWidths(this.centroids);
  double[] bestWeights = DoWeights(trainData, maxIterations);
  return bestWeights;
}

方法 DoCentroids 確定代表輸入的 x 值。 有很多可能性在這裡。 一種常用方法是使用一個 k-均值或 k 進行劃分的聚類演算法,以反覆運算方式分配和重新分配資料項目目,所以類似資料項目目組合在一起。 當完成後,每個群集將有代表性的資料成員。 您可以使用這些作為 RBF 郵編。

另一種辦法是從隨機選定的訓練資料項目目中提取 x 值。 這是簡單的但是有壞郵編可能被選中的機會的風險。

該演示程式使用稱之為一個羽量級聚類建議由這個偽代碼的方法:

initialize maxDistance
intialize bestIndices
loop
  select numHidden random indices into train data
  compute an estimated distance between selected data items
  if estimated distance > maxDistance then
    set maxDistance = curr distance
    set bestIndices = curr indices
  end if
end loop
fetch the x-values in train data at bestIndices
store x-values into RBF centroids

這個想法是最能說明的示例。 假設訓練資料包括 24 項中所示的圖 1。 進一步假設,第一次通過加工迴圈隨機選定的四個指數是 [0],[1],[2] 和 [3]。 這些對應:

0: ( 1.537, -0.382,  1.317,  0.756)
  1: (-0.468,  2.346, -1.170, -1.048)
  2: ( 1.115,  0.164,  0.560,  0.370)
  3: ( 1.220,  0.436,  0.452,  0.241)

這些都是候選人郵編。 這個想法是讓代表的 x 值,這意味著你不想靠近在一起的值。 所以,你計算某種程度的這些候選人郵編之間的距離。 在這裡,有很多可能的辦法。 演示估計通過計算連續的兩名候選人,而不是計算所有可能對之間的平均距離之間的平均距離候選人郵編對所有可能的組合之間的平均距離。 對於此示例,它計算候選人 [0] 和 [1] 之間的距離之間 [1] 和 [2],和之間 [2] 和 [3]。

計算距離的常用方法是總和的使用歐幾裡德距離,是總和的平方根的平方差之和的值。 (附註:演示 RBF 網路使用高斯的內核,使用歐氏距離來計算隱藏的節點本地輸出值)。然而,該演示程式使用曼哈頓距離,哪裡的距離之差的絕對值平均變的體。 因此,候選人 [0] 和 [1] 之間的距離是:

d = abs(1.537 - (-0.468)) + .
.
.
+ abs(0.756 - (-1.048)) / 4
  = 2.256

生成一組候選郵編和計算估計的平均距離為的候選集重複指定的次數和組具有的最大的估計平均距離的候選人被選為 RBF 質心集的過程。

請注意確定 RBF 網路郵編可被視為一種無監督的訓練技術因為目標值 (例如 0、 1、 0) 在訓練資料中的不需要或使用。 這意味著可以快速確定郵編。 另外,RBF 網路寬度、 權重和偏置值可以 — — 在理論上至少 — — 更快的大致等效的神經網路權值和偏差值比計算。 這給 rbf 神經網路的潛在優勢 (但您會看到,還有更多的故事)。

在確定 RBF 網路郵編的過程中,確定候選人指數是有趣的子問題。 該演示程式使用聰明的演算法稱為水庫採樣。 想法是來接的第一次可能 n 指數,然後用剩餘可能指數概率上替換初始指數:

private int[] DistinctIndices(int n, int range)
{
  // Reservoir sampling.
assumes rnd exists
  int[] result = new int[n];
  for (int i = 0; i < n; ++i)
    result[i] = i;
  for (int t = n; t < range; ++t) {
    int m = rnd.Next(0, t + 1);
    if (m < n) result[m] = t;
  }
  return result;
}

雖然該方法是短的它是微妙。 替代辦法包括使用強力攻擊方式隨機指數在生成,然後檢查以查看是否存在任何重複項。

確定 RBF 網路寬度

RBF 網路輸入過程輸出機制為隱藏的每個節點需要一個寬度值。 有很多可能性確定的寬度值。 最簡單的方法和使用的演示程式,是計算一個共同的寬度,所有隱藏的處理節點可以使用。 在這一領域的研究往往是朦朧和結論有時是相互矛盾。 該演示程式作為郵編對所有可能的組合之間的歐幾裡德距離平均計算常見的寬度。 在偽代碼:

sumOfDists = 0.0
for each pair of centroids
  accumulate Euclidean distance between curr pair
end loop
return accumulated sumOfDists / number of pairs

根據我的經驗,RBF 網路的成效是對用於隱藏的節點寬度的值非常敏感。 研究表明一個太小的寬度往往以過度適合培訓資料,導致貧困分類精度。 太大,寬度往往不足合適的資料,這也導致貧窮的分類。 如果您通過手動設置的 RBF 網路寬度值試驗演示代碼,你可以看到這種效果在行動中。

使用郵編之間的平均距離,davg 常見的隱藏的節點寬度值,研究表明使用 (2 * davg),或 (davg / sqrt(2 * numHidden)),和許多其他值。 而不是使用一個共同的寬度,有很多可能性計算隱藏的每個節點的不同寬度值。 在我看來,高靈敏度的寬度值,相關缺乏令人信服的關於如何向最佳計算寬度值,主要的缺點是基於 RBF 網路的研究成果和 RBF 網路相比,神經網路和支援向量機等替代。

確定 RBF 網路權重和偏見

在確定郵編和寬度之後, 訓練 RBF 網路的最後一步確定重量和偏見的值。 從理論上講,RBF 網路權值,您可以輕鬆地計算和快速因為籠統地說,有 n 個未知值 n 方程。 因此,標準數值技術可,在理論上,用於為權重值的解決。

不幸的是,在實踐中,使用標準技術運行到許多實際問題。 例如,許多標準技術研究方程組求解涉及矩陣求逆的使用。 矩陣求逆可以失敗原因有許多。

而不是使用確定性但可能脆性的數值技術來為 RBF 網路權重完全解決,該演示程式使用粒子群優化演算法估計的最佳值。 PSO 是魚的元啟發式基於協調的組的行為,如成群的鳥或學校。 在 PSO,粒子有一個位置,它表示一個潛在的解決方案 (在這種情況下的重量值的最佳集)。 每個粒子都有一個確定粒子的下一位置的速度。

在 PSO,創建一套的粒子。 在每個類比的時間刻度線,每個粒子移動到一個新位置基於粒子的當前的位置和速度、 微粒,最著名的歷史地位和任何微粒的最著名的歷史地位。 這裡是 PSO 在高級別的偽代碼:

set number of particles
set maxIterations
initialize all particles to random positions
loop maxIterations times
  for each particle
    update curr particle's velocity
    use new velocity to compute new position
    compute error for new position
    check if new particle best position
    check if new best position for all particles
  end for
end loop
return best position found by any particle

PSO 是一個迷人的話題在它自己的權利。你可以瞭解更多關於它通過閱讀我 2011 年 8 月的文章,"粒子群優化演算法"(msdn.microsoft.com/magazine/hh335067)。PSO 要求的幾個自由參數規格­eters,包括控制粒子的當前位置的相對影響的重量常量的最佳的歷史地位和最佳全球的歷史地位。PSO 還需要指定粒子的數量、 反覆運算和 (可選),一種用於早期演算法退出錯誤閾值的最大數目。您可以嘗試使用演示代碼這些因素。

除了 PSO 和傳統數值技術,有很多替代品用於查找 RBF 網路權重,包括簡單的梯度下降和實數型遺傳演算法。雖然已經研究理論的 RBF 網路相當拓­實現漸進,不同的訓練技術的對比效果上有相對較少的令人信服的研究結果。

總結

這裡提出的解釋和演示的程式碼應該調查 RBF 網路給你堅實的基礎。雖然 RBF 網路是知名的在研究界,他們好像在相比,神經網路分類器、 樸素貝葉斯分類器和邏輯回歸等替代的軟體發展人員社區中經常使用。一個可能的原因可能是稀缺的實際執行情況的例子。另一個可能原因是基本 RBF 網路因素,尤其是那些相關的 RBF 網路寬度計算的不確定性。在我看來,是沒有扎實的研究證據來回答 RBF 網路是否更有效、 不太有效,或大約相等於替代機器學習技術的問題。

Dr。James McCaffre 為微軟在華盛頓州雷德蒙德的研究工作 他曾在幾個 Microsoft 產品,包括互聯網資源管理器和 Bing。他可以在達成 jammc@microsoft.com

衷心感谢以下技术专家对本文的审阅:KirkOlynyk (Microsoft 研究)