/// <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> /// 交差確認法(Cross Validation)を用いた特徴ベクトルの評価を行います /// <para>確認結果をファイルとして出力します。ファイル名は引数で指定可能です。</para> /// <para>モデル選択はランダム、モデルからの特徴データの取得もランダムとします。</para> /// <para>本メソッドによる学習成果はModelクラスの保持する識別器へは反映されません。</para> /// <para>交差検定で使用する分割数は教師データ数に合わせて自動的に決定されます。</para> /// <para>コード可読性が低いのでいつか変えると思う。。。</para> /// </summary> /// <param name="learningTimes">一回の試行当たりの学習回数</param> /// <param name="checkNum">試行回数</param> /// <param name="fname">保存ファイル名</param> /// <returns>交差検定で使用した分割数<para>最大でも10となります。</para></returns> public int CV(int learningTimes, int checkNum, string fname = "decision chart.csv") { if (learningTimes == 0 || checkNum == 0) throw new Exception("Teacherクラスにおいてエラーがスローされました。CV()の引数の値が不正です。"); var backupOfPom = this.PickOutMode; // 各設定のバックアップを取る this.PickOutMode = Model.ReadSequenceMode.AtRandom; // Lean()での学習をランダムにする var backupOfMode = this.RandomModelChoice; this.RandomModelChoice = true; int divideLimit = int.MaxValue; foreach (Model model in this._class) { model.Shuffle(); // 学習に使用する教師データをシャッフル if (divideLimit > model.Length) divideLimit = model.Length; // モデル数に合わせて分割数を調整するために、最小の教師データ数を計る model.FeatureSupplyMode = Model.SupplyMode.NeglectParticularGroup; } if (divideLimit > 10) divideLimit = 10; // 最大の分割数を10とする foreach (Model model in this._class) model.DivisionNum = divideLimit; var sequence = new Vector[this.Length, checkNum * divideLimit]; // 時系列の識別率を格納する Parallel.For(0, checkNum * divideLimit, i => //for(int i = 0; i < checkNum * divideLimit; i++) { NeuralNetwork nn = new NeuralNetwork(); // ニューラルネットのインスタンスを確保 nn.Setup(this._NNet.GetParameter()); var localModel = new List<Model>(0); int maskIndex = i % divideLimit; foreach (Model model in this._class) { var cpyModel = new Model(model); cpyModel.IndexForDivision = maskIndex; cpyModel.FeatureSupplyMode = Model.SupplyMode.NeglectParticularGroup; // 特定のグループを無視するモードに切り替える localModel.Add(cpyModel); } this.Learn(learningTimes, nn, localModel); // 学習させる foreach (Model model in localModel) { model.FeatureSupplyMode = Model.SupplyMode.TakeParticularGroup; // 特定のグループのみをテストするモードに切り替える } var tempResult = this.CreateDecisionChart(nn, localModel); // 学習に使わなかった教師データを用いた識別を行う for (int modelIndex = 0; modelIndex < this.Length; modelIndex++) sequence[modelIndex, i] = tempResult[modelIndex]; // 識別の結果を保存しておく }); // 平均の識別率を計算し、ファイルへ保存する var averageDecisionChart = new Vector[this.Length]; for (int modelIndex = 0; modelIndex < this.Length; modelIndex++) averageDecisionChart[modelIndex] = new Vector(this.Length); for (int i = 0; i < sequence.GetLength(1); i++) // 平均の識別率を求めるために積算 for (int modelIndex = 0; modelIndex < this.Length; modelIndex++) averageDecisionChart[modelIndex] += sequence[modelIndex, i]; for (int modelIndex = 0; modelIndex < this.Length; modelIndex++) // 平均の識別率を計算 averageDecisionChart[modelIndex] /= ((double)checkNum * divideLimit); this.SaveDecisionChartBody(averageDecisionChart, this._class, "f1", fname); // ファイルに保存 // 識別率の標準偏差を計算し、ファイルへ保存する string fnameForDev = System.IO.Path.GetFileNameWithoutExtension(fname) + ".dev"; // 標準偏差を計算する準備 var deviation = new Vector[this.Length]; for (int modelIndex = 0; modelIndex < this.Length; modelIndex++) deviation[modelIndex] = new Vector(this.Length); for (int i = 0; i < sequence.GetLength(1); i++) // 分散*(n-1)を計算 for (int modelIndex = 0; modelIndex < this.Length; modelIndex++) deviation[modelIndex] += (sequence[modelIndex, i] - averageDecisionChart[modelIndex]).Pow(2.0); for (int modelIndex = 0; modelIndex < this.Length; modelIndex++) // 標準偏差を求める deviation[modelIndex] = (deviation[modelIndex] / (double)(checkNum * divideLimit - 1)).Pow(0.5); using (System.IO.StreamWriter sw = new System.IO.StreamWriter(fnameForDev, false, Encoding.UTF8)) { for (int j = 0; j < this.Length; j++) sw.Write("," + this.ModelIDs[j].ToString() + "を出力"); // ラベル sw.Write("\n"); for (int i = 0; i < deviation.Length; i++) { sw.Write(this.ModelIDs[i].ToString() + "を入力"); sw.WriteLine("," + deviation[i].ToString("f2")); } sw.Write("\n"); } // 後始末 this.PickOutMode = backupOfPom; this.RandomModelChoice = backupOfMode; for (int modelIndex = 0; modelIndex < this.Length; modelIndex++) { this._class[modelIndex].FeatureSupplyMode = Model.SupplyMode.NonDivide; // 分割しないように戻しておく } return divideLimit; }