/// <summary> /// sin()関数の学習の例 /// <para>NeuralNetworkクラスを直接利用して関数近似を行わせるサンプルです。</para> /// <para> /// 2011/12/25現在、0~1までの出力しか得られない。 /// 出力関数と学習則を変更するか、関数近似時には値のマッピングが必要である。 /// 他の人はどうやってんだろう?</para> /// </summary> public static void sin_learnig() { var para = new Parameter(1, 13, 1, 3, 0.01); // ニューラルネットのパラメータ設定 var NNforSin = new NeuralNetwork(); // ニューラルネットクラスのインスタンス生成 NNforSin.Setup(para); for (int i = 0; i < 500; i++) // 学習開始 { Console.Write("\nnow i: " + i.ToString() + "@ "); Console.Write("ans = "); for (int k = 0; k < 15; k++) { double theta = (double)k / 15.0 * 2.0 * Math.PI; double ans = 0.0; for (int l = 0; l < 100; l++) ans = NNforSin.Learn(theta, Math.Sin(theta)); // 特徴ベクトルと教師ベクトルを渡す Console.Write(", " + ans.ToString("0.000")); } } NNforSin.Save("NN.ini"); return; }
/// <summary> /// XORの学習の例 /// <para>NeuralNetworkクラスを直接操作して論理演算を実行する例です。</para> /// </summary> public static void XOR_learning() { var para = new Parameter(2, 5, 1, 1, 0.1); // ニューラルネットのパラメータ設定(中間層が多いと、学習係数を小さくとる必要がある)7層が限界・・ var NNforXOR = new NeuralNetwork(); // ニューラルネットクラスのインスタンス生成 NNforXOR.Setup(para); for (int i = 0; i < 100; i++) // 学習開始 { var ans = new double[4]; Console.Write("now i: " + i.ToString() + "@ "); for (int k = 0; k < 100; k++) { ans[0] = NNforXOR.Learn(new double[2] { 0.0, 0.0 }, 0.0); // 特徴ベクトルと教師ベクトルを渡す ans[1] = NNforXOR.Learn(new double[2] { 0.0, 1.0 }, 1.0); ans[2] = NNforXOR.Learn(new double[2] { 1.0, 0.0 }, 1.0); ans[3] = NNforXOR.Learn(new double[2] { 1.0, 1.0 }, 0.0); } Console.WriteLine("ans = " + ans[0].ToString("0.000") + ", " + ans[1].ToString("0.000") + ", " + ans[2].ToString("0.000") + ", " + ans[3].ToString("0.000") + ", 最後の学習結果→Error variation," + NNforXOR.VariationOfError.ToString("0.000") + ", Total Error," + NNforXOR.TotalOutputError.ToString("0.000")); } NNforXOR.Save("NN.ini"); return; }
/// <summary> /// 最小パラメータ構造体及び入力層と出力層のユニット数で初期化する /// </summary> /// <param name="minParameter">最小パラメータ</param> /// <param name="_numOfUnitInInputLayer">入力層のユニット数<para>特徴ベクトルの次元数と同じ数を指定して下さい。</para></param> /// <param name="_numOfUnitInOutputLayer">出力層のユニット数<para>この数は出力状態量と同じ数を指定して下さい。</para></param> public void Setup(Object minParameter, int _numOfUnitInInputLayer, int _numOfUnitInOutputLayer) { if (minParameter is MinParameter) { MinParameter _minPara = (MinParameter)minParameter; if (_minPara.NumOfHiddenLayer == 0) Console.WriteLine("中間層数が0でしたので中間層のユニット数は無視しました。"); // 実質無視されます。 Parameter para = new Parameter(_minPara, _numOfUnitInInputLayer, _numOfUnitInOutputLayer); this.parameter = para; if (this.parameter.Error) throw new Exception("NeuralNetworkクラスのSetup()メソッドにおいてエラーがスローされました。設定パラメータの値が不正です。"); this.Init(); return; } else throw new Exception("不正なパラメータが渡されました。minParameterの型をチェックして下さい。"); }
/// <summary> /// パラメータ構造体で初期化する /// </summary> /// <param name="_parameter">ニューラルネットワーク構造を規定するパラメータ</param> public void Setup(Parameter _parameter) { this.parameter = _parameter; if (this.parameter.Error) throw new Exception("NeuralNetworkクラスのSetup()メソッドにおいてエラーがスローされました。設定パラメータの値が不正です。"); this.Init(); return; }
/// <summary> /// ファイルを指定して結合係数を読み込ませる /// <para>ファイル名はデフォルトでは"NN.ini"です。</para> /// </summary> /// <param name="fname">初期化用のパラメータの書かれたファイルのパス</param> public void Setup(string fname = "NN.ini") { if (System.IO.File.Exists(fname) == false) throw new SystemException("NeuralNetworkクラスのSetup()メソッドにおいてエラーがスローされました。指定されたファイルは存在しません。"); Parameter para = new Parameter(fname); this.parameter = para; if (this.parameter.Error) throw new Exception("NeuralNetworkクラスのSetup()メソッドにおいてエラーがスローされました。設定パラメータの値が不正です。"); this.Init(); this.layer.Setup(fname); // 実際の処理はlayerに丸投げ return; }
// 3層以上と限定すれば、numOfPreLayerUnitは要らないんだけど2層も試したかったので導入した /// <summary> /// レイヤークラスのコンストラクタ /// <para>このクラスインスタンスを一つ生成すれば、入力層から出力層までを表現可能です。</para> /// <para> /// 本クラスを生成する際、numOfPreLayerUnitは0と設定することをお勧めします。 /// 0でなくともエラーは出ませんが、入力層には結合係数が定義されないためです。 /// </para> /// </summary> /// <param name="_parameter">ニューラルネットのパラメータ</param> /// <param name="_myLayerNum">層番号</param> /// <param name="numOfPreLayerUnit">前の層のユニット数(省略可能です。デフォルトでは0となります。)</param> public Layer(Parameter _parameter, int _myLayerNum, int numOfPreLayerUnit = 0) { this.parameter = _parameter; this.grossLayerNum = this.parameter.TotalLayer; this.myLayerNum = _myLayerNum; // ユニットの準備と、前層のユニット数を記憶する switch (this.MyKind) { case Kind.InputLayer: // 入力層 this.units = new Unit[this.parameter.NumOfUnitInInputLayer]; // 層の種類に合わせて、ユニット数を宣言する break; case Kind.HiddenLayer: // 中間層 this.units = new Unit[this.parameter.NumOfUnitInHiddenLayer]; break; case Kind.OutputLayer: // 出力層 this.units = new Unit[this.parameter.NumOfUnitInOutputLayer]; break; } for (int i = 0; i < this.units.Length; i++) this.units[i] = new Unit(numOfPreLayerUnit); // 前の層のユニット数だけ結合係数を生成させる this.preLayerUnitNum = numOfPreLayerUnit; // 前の層のユニット数を記憶しておく if (this.MyKind != Kind.OutputLayer) this.subsidiaryLayer = new Layer(this.parameter, this.myLayerNum - 1, this.units.Length); // 出力層以外なら子レイヤを生成 }