この記事は機械翻訳されたものです。

テストの実行

プログラマ用のニュートラル ネットワークのバックプロパゲーション (機械翻訳)

James McCaffrey

コード サンプルのダウンロード

James McCaffrey人工ニューラル ネットワークは固定数の数値入力を受け付け、数値出力の固定数を生成するメタ-関数として考えることができます。 ほとんどの状況では、各非表示ニューロン完全入力ニューロンと出力ニューロンに接続されて、非表示ニューロンの層ニューラル ネットワークをしています。 個々 のそれぞれの非表示と関連付けられている各個々 の出力ニューロンとニューロンの重みの値と 1 つのいわゆるバイアス値のセットです。 重量と偏見の入力値の与えられた出力値を決定します。

ニューラル ネットワークの予測は新しいデータを行うことができますので、既存のデータのセットをモデルに使用されると、主な課題は、既存のデータに最適な出力を生成する重みとバイアスの値のセットを見つけることです。 最適なニューラル ネットワークの重みとバイアスの推定方法の最も一般的なバックプロパゲーションと呼ばれます。 誤差逆伝搬の根底にある複雑な数学を記述する多くの優秀な参照がありますが、非常にほとんどのガイド逆伝搬アルゴリズムをプログラムする方法を明確に説明するプログラマのために利用可能 します。 逆伝播を実装する方法について説明します。 C# 言語を使用するが、ここで他の言語に紹介コードをリファクタリングする問題はありません。

どこに向かっているを参照してくださいする最良の方法でデモ プログラムのスクリーン ショットを見てみることです図 1。 3 つの入力ニューロンは、4 つのニューロンを非表示のレイヤーを持つニューラル ネットワークのデモ プログラムを作成し、2 つのニューロンの出力します。 単一の隠れ層をもつニューラル ネットワークは、2 つの活性化関数必要があります。 多くの状況では、しかし、2 つの活性化関数は同じ通常、シグモイド関数です。 しかし、異なる活性化関数使用活性化関数と逆伝播の関係を説明するためのこのデモでは、:シグモイド関数の入力隠された計算のため、tanh (ハイパーボリック タンジェント) 関数の出力が非表示の計算。

Back-Propagation Algorithm in Action
図 1 逆伝搬アルゴリズムの動作

3-4-2 を完全に接続されて A ニューラル ネットワークが必要です 3 ※ 4 + 4 ※ 2 = 20 重量値と 4++ 2 = 26 の重量と偏見の合計 6 バイアス値。 これらの重量と偏見は、多かれ少なかれ、任意の値に初期化されます。 3 つのダミーの入力値は、1.0、2.0 および 3.0 に設定されます。 初期重量、バイアスおよび入力値では、最初の出力値に {0.7225,-0.8779} をニューラル ネットワークによって計算されます。 デモ プログラム任意 2 つ正しい出力値を前提としていますは、{-0.8500、0.7500}。 逆伝搬アルゴリズムの目標は、重量と至近 {1.0、2.0、3.0} 入力用の正しい値に出力を生成する偏見の新しいセットを見つけることです。

バックプロパゲーション無料 2 つのパラメーターが必要です。 通常バックプロパゲーション文学では、ギリシャ文字の eta を与え、学習率は最終的な見積もりにアルゴリズムをどのように高速収束を制御します。 ギリシャ文字のアルファを通常与え、勢い、アルゴリズムが振動して決して収束最終的な見積もりに状況を避けるため逆伝搬アルゴリズムに役立ちます。 デモ プログラムは 0.90 0.04 に勢いを学習率を設定します。 通常これらの値は、試行錯誤で発見されます。

ニューラル ネットワークの重みとバイアスの最高のセットを見つけることは、ネットワークのトレーニングと呼ばれます。 バックプロパゲーションとトレーニングは、反復的なプロセスです。 各イテレーションでは、bp は、理論的目標値に近づいている出力値を生成ニューラル ネットワークの重みとバイアスの値の新しいセットを計算します。 デモ プログラムの最初のトレーニングの反復後, 逆伝搬アルゴリズム {-0.8932,-0.8006} の新規出力を生成する新しい重みとバイアスの値が見つかりました。 最初の新しい出力値-0.8932 の-0.8500 の最初のターゲットの出力値に近い方の多くだった。 -0.8006 の 2 番目の新しい出力値は、まだ遠いをターゲット値で 0.7500 からだった。

トレーニング プロセスは、さまざまな方法で終了できます。 出力の値とターゲット値の絶対差の合計をなるまでデモ プログラム トレーニング反復 < = 0.01 またはトレーニングに達する 1,000 イテレーション。 デモでは、トレーニングの六つのイテレーション後逆伝搬ニューラル ネットワークのセットの出力を生成する重みとバイアスの値が見つかりました {-0.8423, 0.7481} いたに非常に近い、{-0.8500, 0.7500} 希望のターゲット値。

この資料では、エキスパート レベルのプログラミング スキルがあるし、ニューラル ネットワークの非常に基本的な理解があることを想定しています。 (ニューラル ネットワークの基礎については、2012 年 5 月の私の記事、「ダイビングにニューラル ネットワーク」を参照してください msdn.microsoft.com/magazine/hh975375.)コードに示されているデモ プログラムを図 1 アルゴリズムのキーの部分を説明するのに集中しますので、この記事では、提示するビットが長すぎます。 デモ プログラムの完全なソース コードで入手可能です archive.msdn.microsoft.com/mag201210TestRun

ニューラル ネットワークのクラスを定義します。

逆伝播を使用するニューラル ネットワーク符号化は素敵なオブジェクト指向アプローチに適しています。 デモ プログラムを使用するクラスの定義に記載されている図 2

図 2 ニューラル ネットワーク クラス

class NeuralNetwork
{
  private int numInput;
  private int numHidden;
  private int numOutput;
  // 15 input, output, weight, bias, and other arrays here
  public NeuralNetwork(int numInput, 
    int numHidden, int numOutput) {...}
  public void UpdateWeights(double[] tValues, 
    double eta, double alpha) {...}
  public void SetWeights(double[] weights) {...}
  public double[] GetWeights() {...}
  public double[] ComputeOutputs(double[] xValues) {...}
  private static double SigmoidFunction(double x)
  {
    if (x < -45.0) return 0.0;
    else if (x > 45.0) return 1.0;
    else return 1.0 / (1.0 + Math.Exp(-x));
  }
  private static double HyperTanFunction(double x)
  {
    if (x < -10.0) return -1.0;
    else if (x > 10.0) return 1.0;
    else return Math.Tanh(x);
  }
}

メンバー フィールド、numInput、numHidden、numOutput、ニューラル ネットワークの特性を定義します。 単純なコンス トラクターに加えて、クラスはパブリックにアクセスできる 4 つのメソッドと 2 つのヘルパー メソッドです。 メソッド UpdateWeights には逆伝搬アルゴリズムのすべてのロジックが含まれています。 メソッド SetWeights の重量と偏見の配列し、それらの値の sequen をコピー­スにアレイ メンバー。 メソッド GetWeights を実行する逆オペラ­重量と偏見を単一の配列にコピーして、配列を返す情報。 メソッド ComputeOutputs は、現在の入力、重量とバイアスの値を使用して、ニューラル ネットワークの出力値を決定します。

SigmoidFunction メソッドは、入力隠された活性化関数として使用されます。 これは、実際の値 (c# では double 型) を受け取り、0.0 ~ 1.0 の値を返します。 HyperTanFunction メソッドも実際の値を受け付けますが、-1.0 ~ +1.0 の値を返します。 C# 言語は、組み込みのハイパーボリック タンジェント関数、Math.Tanh がネイティブ tanh 関数がない言語を使用している場合は、ゼロから 1 つをコード必要があります。

アレイの設定

正常にニューラル ネットワーク誤差逆伝播アルゴリズムをプログラミングするのには、キーの重みとバイアスの値を格納、別の種類の入力と出力値の格納のアルゴリズムは、以前のイテレーションからの値を格納、スクラッチの計算を格納に使用されているアレイを完全に理解することです。 大規模なダイアグラムで図 3 逆伝播をプログラムする方法を理解する知っている必要なすべての情報が含まれています。 あなたの最初の反応に図 3 の線に沿って何かをする可能性がある"それを忘れて — これはあまりにも複雑です"。そこにハングアップします。 Bp は簡単ではありませんが、図を理解したら逆伝搬の任意のプログラミング言語を使用して実装することができます。

The Back-Propagation Algorithm
図 3 逆伝搬アルゴリズム

図 3 プライマリ入力があり、またいくつかのローカルの入力と、ダイアグラムの内部で発生する出力値が、図の端の出力します。 ニューラル ネットワークと名前と意味のすべてのこれらの入力と出力を明確保つ必要性を符号化の難しさを過小評価しないでください。 私の経験に基づいて、図のように、1 つの図 3 絶対に不可欠です。

概説したニューラル ネットワークの定義で使用される 15 の配列の最初の 5 図 2 隠し入力レイヤーを扱うし、は。

public class NeuralNetwork
{
  // Declare numInput, numHidden, numOutput
  private double[] inputs;
  private double[][] ihWeights;
  private double[] ihSums;
  private double[] ihBiases;
  private double[] ihOutputs;
...

入力、という最初の配列は、数値の入力値を保持します。 これらの値は、通常、テキスト ファイルなどのいくつかの正規化されたデータ ソースから直接来る。 教師のコンス トラクターには、入力としてインスタンスを作成します。

this.inputs = new double[numInput];

配列 ihWeights (ウェイト隠し入力) は、仮想の 2 次元配列としての配列の実装です。 入力ニューロンの最初のインデックスを示す、2 番目のインデックスは、非表示ニューロンを示します。 配列としてのコンス トラクターでインスタンス化します。

this.ihWeights = Helpers.MakeMatrix(numInput, numHidden);

ここでは、ヘルパー ユーティリティ クラスの簡略化ニューラル ネットワークのクラスの静的メソッドです。

public static double[][] MakeMatrix(int rows, int cols)
{
  double[][] result = new double[rows][];
  for (int i = 0; i < rows; ++i)
    result[i] = new double[cols];
  return result;
}

配列 ihSums は、中間の計算で ComputeOutputs メソッドを保持するために使用されるスクラッチの配列です。 配列としてインスタンス化されるローカル非表示ニューロンの入力となる値を保持します。

this.ihSums = new double[numHidden];

配列 ihBiases は、非表示ニューロンのバイアスの値を保持します。 ニューラル ネットワークの重みの値は、ローカルの入力値を乗算することによって適用される定数です。 バイアス値は次の層へのローカルの入力になります、ローカル出力値を生成する、中間の合計に追加されます。 配列 ihBiases としてインスタンス化します。

this.ihBiases = new double[numHidden];

配列 ihOutputs は (これは出力層への入力になる) 非表示層のニューロンから放出される値を保持します。

教師のクラス内の次の 4 つのアレイ出力が非表示のレイヤーに関連する値を保持します。

private double[][] hoWeights;
private double[] hoSums;
private double[] hoBiases;
private double[] outputs;

これら 4 つの配列としてのコンス トラクターでインスタンス化されます。

this.hoWeights = Helpers.MakeMatrix(numHidden, numOutput);
this.hoSums = new double[numOutput];
this.hoBiases = new double[numOutput];
this.outputs = new double[numOutput];

ニューラル ネットワークのクラスは、逆伝搬アルゴリズムに直接関連している六つの配列があります。 最初の 2 つの配列は、グラデーションのため出力層と非表示ニューロンと呼ばれる値を保持します。 グラデーションが直接どのくらい遠くまでオフに説明する値は、どの方向に (正または負) ローカル出力ターゲット出力を基準。 グラデーションの値は、現在の体重と新しいより良い重みとバイアスを生成するためにバイアス値に追加されます、デルタ値の計算に使用されます。 各非表示層のニューロンと各出力層のニューロンの 1 つのグラデーションの値です。 配列として宣言します。

private double[] oGrads; // Output gradients
private double[] hGrads; // Hidden gradients

配列としてのコンス トラクターでインスタンス化されます。

this.oGrads = new double[numOutput];
this.hGrads = new double[numHidden];

教師のクラスの最終的な 4 つのアレイ (グラデーション) デルタ トレーニング ループの以前のイテレーションからを保持します。 誤差逆伝搬の非収束を防ぐために勢いのメカニズムを使用する場合これらの以前のデルタは必要があります。 私は勢いが不可欠、検討しますが、勢いを実装しないする場合これらの配列を省略できます。 として宣言されています。

private double[][] ihPrevWeightsDelta;  // For momentum
private double[] ihPrevBiasesDelta;
private double[][] hoPrevWeightsDelta;
private double[] hoPrevBiasesDelta;

これらの配列としてインスタンス化されます。

ihPrevWeightsDelta = Helpers.MakeMatrix(numInput, numHidden);
ihPrevBiasesDelta = new double[numHidden];
hoPrevWeightsDelta = Helpers.MakeMatrix(numHidden, numOutput);
hoPrevBiasesDelta = new double[numOutput];

出力のコンピューティング

各ループ内で反復に示すトレーニング図 1 2 つの部分があります。 最初の部分では、出力が、重量と偏見の現在のプライマリ入力を使用して計算されます。 2 番目の部分では、bp の重みとバイアスを変更に使用されます。 ダイアグラムで図 3 研修プロセスの両方の部分を示しています。

左から右、入力 x 0 作業、x 1 と x 2 1.0、2.0、3.0 の値が割り当てられます。 これらのプライマリの入力値は、入力層ニューロンに行くに変更せずに出力されます。 特定の範囲内にある値を正規化するなど、彼らの入力入力層ニューロンは変更できますがほとんどの場合このような処理を外部で行われます。 このため、ニューラル ネットワーク図しばしば長方形または正方形のボックス入力ニューロンの非表示層と出力層のニューロンがある同じ意味のニューロンを処理ではない指定します。 さらに、この用語に影響します。 いくつかのケースで示すニューラル ネットワーク図3三層のネットワークと呼ばれるだろうが、入力レイヤーの処理を実行しないので、示すニューラル ネットワークは、2 層のネットワークと呼ばれます。

次に、非表示層のニューロンの各ローカル入力とローカル出力を計算します。 たとえば、インデックス [3]、一番下の非表示ニューロンのスクラッチの合計として計算します (1.0)(0.4)+(2.0)(0.8)+(3.0)(1.2) = 5.6。 スクラッチの合計は、関連付けられた入力隠された重量回 3 つの入力の合計の製品です。 上記各矢印の値の重みです。 次に、ローカル生成する入力値 5.6 + (-6) のバイアス値、-6、スクラッチの合計に追加されます-1.40 =。 [入力隠された活性化関数ニューロンのローカル出力値を生成するこの中間の入力値に適用されます。 ローカル出力は 1 ですので、この場合、活性化関数シグモイド関数です/(1 + exp(-(-1.40))) = 0.20。

出力層のニューロンは、同様に彼らの入力と出力を計算します。 たとえば、 図 3、一番下の出力層ニューロン インデックス [1] とそのスクラッチの合計として計算します (0.86)(1.4)+(0.17)(1.6)+(0.98)(1.8)+(0.20)(2.0) = 3.73。 関連のバイアスはローカルの入力を与えるために追加されます。3.73 + (-5.0) = -1.37. プライマリ出力を与えるために活性化関数が適用されます。tanh(-1.37) = 増減:-2.09%。 ComputeOutputs のコードを調べると、丁度説明したように、メソッドが出力を計算することがわかります。

バックプロパゲーション

一度それらの数学の結果は何を知っている誤差逆伝搬の理論の背後にある数学はかなり複雑ですが、bp の実装はあまりにも困難ではないです。 逆伝播を開始右から左に示す図での作業で図 3。 最初のステップは、各出力層のニューロンの勾配の値を計算するためにです。 リコール勾配マグニチュードと方向のエラーに関して情報がある値です。 出力層のニューロンのグラデーションは異なる非表示層のニューロンのグラデーションから計算されます。

出力層ニューロンの勾配はマイナス評価計算の出力値に出力層の活性化関数の微分積分微分時間の計算の出力値 (必要な) のターゲット値と等しいです。 たとえば、勾配値の最下位の出力層のニューロンの図 3、インデックス [1] では、として計算されます。

(0.75 – (-0.88)) * (1 – (-0.88)) * (1 + (-0.88)) = 0.37   

0.75 に目的の値です。 増減: +0.18% 前方へのパスの計算からの計算の出力値です。 この例では出力層の活性化関数 tanh 関数であることを思い出してください。 Tanh(x) の微積分の誘導体である (1 - tanh(x)) ※ (1 + tanh(x))。 数学解析は少しトリッキーですが、最終的には、出力層ニューロンのグラデーションの計算をここで説明数式によって与えられます。

非表示層のニューロンの勾配は回、関連付けられている出力隠し重みのプライマリ出力の積の合計回ニューロンの出力をローカルで評価する非表示の層の活性化関数の微積分の誘導体に等しいです。 たとえば、 図 3、インデックス [3] 最下位中間層ニューロンのグラデーションです。

(0.20)(1 – 0.20) * [ (-0.76)(1.9) + (0.37)(2.0) ] = -0.03

シグモイド関数 g(x) を呼び出す場合は、それ g(x) シグモイド関数の微積分の誘導体であることが判明 ※ (1 - g(x))。 この例が隠し入力活性化関数にシグモイド関数を使用することを思い出してください。 ここでは 0.20 ニューロンからローカル出力です。 増減:-0.30% と 0.37 出力層のニューロンのグラデーションをありは 1.9 と 2.0 2 つの出力層のグラデーションと関連付けられている出力が非表示の重みです。

重量とバイアスのデルタの計算

すべてのグラデーション出力層と非表示層のグラデーションが計算された後、次のステップで誤差逆伝搬アルゴリズム デルタ値それぞれの重みとバイアスの値を計算する勾配の値を使用します。 右から左へを計算する必要があります、グラデーションとは異なり、任意の順序でデルタ値を計算できます。 デルタ値の重みやバイアス eta 倍の重量または重量またはバイアスに関連付けられた入力値のバイアスのグラデーションを関連付けです。 たとえば、非表示ニューロン [3] に入力隠された重量入力ニューロン [2] からのデルタ値です。

デルタ i h 重量 [2] [3] = eta ※ 隠されたグラデーション [3] ※ 入力 [2]
= 0.90 * (-0.11) * 3.0
= -0.297

0.90 Eta は、どのように高速逆伝搬学習制御です。 Eta の値が大きいデルタは良い答えをオーバー シュートのリスクのより大きな変化を生成します。 -0.11% 値です非表示ニューロン [3] のグラデーション。 3.0 の値は、入力ニューロン [2] の入力値です。 ダイアグラムでの面で図 3、重量が矢印として 1 つのニューロンから別に表現する場合、特定の重量のデルタを計算するために右上に指摘したニューロンの勾配値から左側に指摘したニューロンの入力値使用と。

バイアス値の差分を計算する場合、バイアス値は単に、中間の合計に追加されるため、彼らは関連付けられている入力価値があることに注意してください。 だから、バイアス値のデルタを計算する入力値の用語を完全に省略するかダミー 1.0 の値はドキュメントのフォームとして使用します。 たとえば、 図 3、最下位層バイアス-6 の値があります。 そのバイアス値のデルタです。

0.90 ※ ニューロンの勾配を指摘する ※ 1.0
= 0.90 * (-0.11) * 1.0
= 0.099

勢いの用語を追加します。

すべての重みとバイアスのデルタ値が計算された後は、関連付けのデルタ値を追加するだけで、それぞれの重みとバイアスを更新することです。 ただし、ニューラル ネットワークを用いた経験は特定のデータ セットでは、誤差逆伝搬アルゴリズム、繰り返しオーバー シュートということで、ターゲット値と決して重量とバイアス推定の最終的なセットに収束して発振することことを示しています。 この傾向を減らすことには、1 つの方法は、各新しい重量を追加し、勢いと呼ばれる、追加の用語をバイアスします。 重量 (またはバイアス) 勢いだけでいくつかの小さな値 (0.4 デモ プログラムでは) のような重量の以前のデルタ値回です。 以前のデルタ値を格納する必要がありますので勢いを使用して逆伝搬アルゴリズムに複雑さの少量を追加します。 なぜこのテクニック発振防止の背後にある数学は微妙ですが、結果は簡単です。

逆伝播を使用して、重量 (またはバイアス) を更新するにはを要約するには、最初のステップはすべて出力層のニューロンのための勾配を計算するためにです。 2 番目のステップはすべて非表示層のニューロンのための勾配を計算することです。 3 番目のステップは、eta の学習率を使用してすべてのウェイトのデルタを計算するためにです。 4 番目のステップは、各重量に差分を追加します。 5 番目のステップは、各重量を勢い用語を追加します。

Visual Studio の 2012 とコーディング

バックプロパゲーション サンプル コードと共にこの資料の提示の説明を理解し、誤差逆伝搬アルゴリズムをコードに十分な情報を与える必要があります。 逆伝播を最高の重量とデータ セットのバイアス値を推定するのに使用できるいくつかのテクニックの 1 つだけです。 粒子群最適化と進化的最適化アルゴリズムなどの選択肢と比較して、誤差逆伝搬を高速になる傾向があります。 しかし、bp は欠点を持っています。 非可微分活性化関数を使用するニューラル ネットワークを使用できません。 学習の良い値を決定する速度と勢いのパラメーターは、科学よりも芸術で、時間がかかることができます。

この記事、特に、対応していないいくつかの重要なトピックが複数のターゲットのデータ アイテムに対処する方法。 この概念と他のニューラル ネットワークの技術の将来の記事を説明します。

私はこの記事のデモ プログラムのコードとは、Visual Studio の 2012年のベータ版を使用しました。 Visual Studio の 2012年の新機能の多くは、Windows 8 のアプリに関連しても、Visual Studio 2012 良い古いコンソール アプリケーションを処理する方法を参照してくださいしたいと思います。 私を不愉快な Visual Studio 2012 の新機能のいずれかで驚いていないこと愉快に驚いた。 Visual Studio 2012 への移行が楽だった。 私は行っていないが Visual Studio 2012 の新しい非同期機能を使用して、それぞれの重みとバイアスのためのすべてのデルタ値を計算するときに便利されていること。 呼び出し階層の新しい機能をしようとし、それは便利で直感的な発見します。 Visual Studio の 2012 年の私の最初の印象が好調であり、私はできるだけ早く私はそれへの移行を計画します。

Dr.James McCaffreyボルト情報科学株式会社は、彼はマイクロソフトのレドモンド、ワシントン州でキャンパスで働くソフトウェア エンジニアの技術トレーニングを管理するために動作します。これまでに、Internet Explorer、MSN サーチなどの複数のマイクロソフト製品にも携わってきました。彼は「.NET テスト オートメーション レシピ」(Apress、2006年) の著者でありに到達することができます jammc@microsoft.com

この記事のレビュー、次技術専門家のおかげで:ダン Liebling