/// <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> /// 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> /// 学習を実行させる /// <para>学習強度を引数で設定可能です。</para> /// </summary> /// <param name="learningTimes">学習回数</param> /// <param name="learningStrength">学習強度(要素数はモデル数と一致すること)</param> /// <param name="discriminator">学習させる識別器</param> /// <param name="classForLearning">学習用教師データモデル</param> /// <returns>識別器の出力誤差積算値</returns> private double Learn(int learningTimes, int[] learningStrength, NeuralNetwork discriminator, List<Model> classForLearning) { if (this.Ready == false) throw new SystemException("学習の準備はまだ完了しておりません。モデルを追加して下さい。"); if (classForLearning.Count != learningStrength.Length) throw new SystemException("学習強度の要素数がモデル数と一致しません。"); if (discriminator == null) throw new Exception("判別器のインスタンスが確保されておらず、学習ができません。"); // 学習をスタート foreach (Model model in classForLearning) model.SequenceMode = this.PickOutMode; int learningCount = 0; double[] errorEachModel = new double[classForLearning.Count]; Boolean need = CheckLearningStrength(learningStrength); // 学習させる必要性を学習強度からチェック int backupOfModelIndex = int.MaxValue; int sameCount = 0; while (learningCount < learningTimes && need) // 学習回数をチェックしながらループ { int modelIndex; if (this.RandomModelChoice) modelIndex = this.myRandom.Next(classForLearning.Count); else modelIndex = learningCount % classForLearning.Count; if (backupOfModelIndex != modelIndex) // 2回連続で学習させると学習が偏ってしまうので回避。エニグマみたい。 { Vector teature = this.CreateTeachingVector(modelIndex); double error = 0.0; int count = 0; // 指定された強度分配に基づき、計算した回数分モデルを呼び出す for (int i = 0; i < learningStrength[modelIndex]; i++) { Feature feature = classForLearning[modelIndex].GetFeature(); Vector outputForDebug = discriminator.Learn(feature, teature); // 学習 learningCount++; error += discriminator.TotalOutputError; count++; } error /= (double)count; // 特徴量1件当たりの誤差量を計算 errorEachModel[modelIndex] = error; // シーケンス上では何の役にも立っていないが、デバッグ用と思ってください。将来的には誤差の収束条件を入れたいと思っています。 sameCount = 0; } else { if (sameCount < 100) // 同じ数が出るようになったらインスタンスをもう一度作ってみる sameCount++; // 乱数ジェネレータが壊れるとかあほかと(並列演算が悪いの?) else // これで一応うまくいくことを確認した this.myRandom = new Random(); } backupOfModelIndex = modelIndex; } return discriminator.TotalOutputError; }