/// <summary> /// NeuralNetTeacherクラスを使って、既に生成されている特徴ベクトルをまとめたファイルを読み込ませて学習を行う part2 /// </summary> public static void Iris_learning2() { var minPara = new MinParameter(13, 1, 0.1); var NNteacher = new Teacher(minPara); // ニューラルネットの教師クラスのインスタンスを生成 NNteacher.Setup("教師データの例 Iris"); int timeOfLearning = 10000; for (int i = 1; i <= 2; i++) // 2回ループさせる { NNteacher.Learn(timeOfLearning); NNteacher.SaveDecisionChart("decision chart " + (i * timeOfLearning).ToString() + ".csv"); } NNteacher.SaveLearnigOutcome(); // 学習した結合係数などをファイルに保存 // これ以降は識別テスト var feature = new Feature("5.4 3.4 1.7 0.2"); // セトナのデータ // 学習済みのニューラルネットワーククラスオブジェクトを渡して学習器を構成 var discriminator = new Discriminator(NNteacher.GetNeuralNetwork(), NNteacher.ModelIDs);// これ以降、学習成果を利用して識別を行うことができる。 var test = discriminator.Discriminate(feature, 2); // 結果を降順で2つもらう string outputstr = ""; for (int i = 0; i < test.Length; i++) outputstr += test[i].ID + ", " + test[i].Likelihood.ToString("0.00") + "\n"; Console.WriteLine(outputstr, "識別テストその1の結果"); // ファイルから結合係数を読み込ませても同じ結果が出ることを確認する var discriminator2 = new Discriminator(); discriminator2.Setup(); var test2 = discriminator.Discriminate(feature); // テストを実施し、表示する Console.WriteLine("識別結果: " + test2.ID + ", " + test2.Likelihood.ToString("0.00"), "識別テストその2の結果"); return; }
// ---- メソッド --------------------------------------- /// <summary> /// 特徴ベクトルを返す /// </summary> /// <returns>特徴ベクトル</returns> public override PatternRecognition.Feature GetFeature() { if (this.Ready) { // 最大のパワーとなった帯域を探すとその最大値を求める double maxPSDofBand = this._sumOfPSDbyBand.Max(); // 最大値を取得 int indexOfMax = -1; // -1としておくことで、↓2行のアルゴリズムにより最大となる帯域のインデックス-1を得る for (int i = 0; i < this._sumOfPSDbyBand.Length && this._sumOfPSDbyBand[i] != maxPSDofBand; i++) { indexOfMax = i; // 最大となった帯域のインデックス-1を取得する } indexOfMax++; // 等しいと代入の前にループを抜けるので、抜けた後で加算してインデックスとする // SN比を求める。求まればよいが。 double noiseLevelPSD = this._timeSeriesPSD[0][indexOfMax]; // フレームの初めはノイズレベルに近いはず double maxPSDofFlame = double.MinValue; for (int i = 0; i < this._timeSeriesPSD.Count; i++) { if (maxPSDofFlame < this._timeSeriesPSD[i][indexOfMax]) { maxPSDofFlame = this._timeSeriesPSD[i][indexOfMax]; } } this._SNratio = 10.0 * Math.Log10(maxPSDofFlame / noiseLevelPSD); // 帯域パワーの最大値が1になるように正規化 var fea1 = new PatternRecognition.Feature(this._sumOfPSDbyBand); fea1.Normalizing(); // 変調スペクトルをもとめる double[] modulatedSongAtUniBand = new double[this._timeSeriesPSD.Count]; for (int i = 0; i < modulatedSongAtUniBand.Length; i++) { modulatedSongAtUniBand[i] = this._timeSeriesPSD[i][indexOfMax]; // 最大であった帯域のパワーを取得する(変調されたパワー) } DFT fft = new DFT(modulatedSongAtUniBand.Length, Window.WindowKind.Hanning); // FFTを実施する準備 FFTresult modulationSpectrum = fft.FFT(modulatedSongAtUniBand, this._condition.FrequencyOfFFT); double[] spectrum = new double[this._condition.MaxModulationSpectrumFrequency * 10]; //for (int i = 0; i < spectrum.Length; i++) Parallel.For(0, spectrum.Length, i => { double minFrequency = (double)i * 0.1; double maxFrequency = minFrequency + 0.1; spectrum[i] = modulationSpectrum.GetPSD(minFrequency, maxFrequency); // 帯域毎にコピー }); // コピーした変調スペクトルを正規化 var fea2 = new PatternRecognition.Feature(spectrum); fea2.Normalizing(); // 特徴ベクトルとしてまとめる var ans = new PatternRecognition.Feature(fea1.ToArray()); ans.Add(fea2.ToArray()); ans.Normalizing(); return(ans); } else { return(null); } }
/// <summary> /// コンストラクタです。 /// <para>パラメータの初期化を行います。</para> /// </summary> /// <param name="filterName">帯域フィルタ名</param> /// <param name="time">検出時刻[s]<para>発声部分として検出された区間の検出立ち上がり時刻を表します。</para></param> /// <param name="timeWidth">検出期間[s]<para>発声区間の時間幅です。</para></param> /// <param name="SNratio">SN比</param> /// <param name="feature">特徴ベクトル</param> public Result(string filterName, double time, double timeWidth, double SNratio, PatternRecognition.Feature feature) { this._filterName = filterName; this.DiscriminationResult = ""; this._time = time; this._timeWidth = timeWidth; this._SNratio = SNratio; this._feature = feature; return; }
// ---- メソッド --------------------------------------- /// <summary> /// 特徴ベクトルを返す /// </summary> /// <returns>特徴ベクトル</returns> public override PatternRecognition.Feature GetFeature() { if (this.Ready) { // 最大のパワーとなった帯域を探すとその最大値を求める double maxPSDofBand = this._sumOfPSDbyBand.Max(); // 最大値を取得 int indexOfMax = -1; // -1としておくことで、↓2行のアルゴリズムにより最大となる帯域のインデックス-1を得る for (int i = 0; i < this._sumOfPSDbyBand.Length && this._sumOfPSDbyBand[i] != maxPSDofBand; i++) indexOfMax = i;// 最大となった帯域のインデックス-1を取得する indexOfMax++; // 等しいと代入の前にループを抜けるので、抜けた後で加算してインデックスとする // SN比を求める。求まればよいが。 double noiseLevelPSD = this._timeSeriesPSD[0][indexOfMax]; // フレームの初めはノイズレベルに近いはず double maxPSDofFlame = double.MinValue; for (int i = 0; i < this._timeSeriesPSD.Count; i++) if (maxPSDofFlame < this._timeSeriesPSD[i][indexOfMax]) maxPSDofFlame = this._timeSeriesPSD[i][indexOfMax]; this._SNratio = 10.0 * Math.Log10(maxPSDofFlame / noiseLevelPSD); // 帯域パワーの最大値が1になるように正規化 var fea1 = new PatternRecognition.Feature(this._sumOfPSDbyBand); fea1.Normalizing(); // 変調スペクトルをもとめる double[] modulatedSongAtUniBand = new double[this._timeSeriesPSD.Count]; for (int i = 0; i < modulatedSongAtUniBand.Length; i++) modulatedSongAtUniBand[i] = this._timeSeriesPSD[i][indexOfMax];// 最大であった帯域のパワーを取得する(変調されたパワー) DFT fft = new DFT(modulatedSongAtUniBand.Length, Window.WindowKind.Hanning); // FFTを実施する準備 FFTresult modulationSpectrum = fft.FFT(modulatedSongAtUniBand, this._condition.FrequencyOfFFT); double[] spectrum = new double[this._condition.MaxModulationSpectrumFrequency * 10]; //for (int i = 0; i < spectrum.Length; i++) Parallel.For(0, spectrum.Length, i => { double minFrequency = (double)i * 0.1; double maxFrequency = minFrequency + 0.1; spectrum[i] = modulationSpectrum.GetPSD(minFrequency, maxFrequency); // 帯域毎にコピー }); // コピーした変調スペクトルを正規化 var fea2 = new PatternRecognition.Feature(spectrum); fea2.Normalizing(); // 特徴ベクトルとしてまとめる var ans = new PatternRecognition.Feature(fea1.ToArray()); ans.Add(fea2.ToArray()); ans.Normalizing(); return ans; } else return null; }
/// <summary> /// 特徴ベクトルの追加 /// </summary> /// <param name="newMember">追加メンバ</param> public void Add(Feature newMember) { this.buff.Add(newMember); if (this.Length == 1) this.MemberSize = newMember.Length; else if (this.MemberSize != newMember.Length) throw new SystemException("既に登録された特徴ベクトルのサイズと追加しようとした特徴ベクトルのサイズが異なります。"); return; }
/// <summary> /// コピーコンストラクタ /// </summary> /// <param name="_vector">Featureクラスオブジェクト</param> /// <exception cref="SystemException">配列がnullならスロー</exception> public Feature(Feature _vector) : base(_vector) { }
/// <summary> /// メンバの初期化付コンストラクタ /// <para>クラスメンバはディープコピーされます。</para> /// </summary> /// <param name="_id">クラス名</param> /// <param name="_members">メンバ</param> /// <exception cref="SystemException">メンバがnullであったりメンバ数が0もしくは渡された特徴ベクトルの時限数が不一致だとスロー</exception> public Model(string _id, Feature[] _members) : base() { this.className = _id; this.SequenceMode = ReadSequenceMode.AtRandom; this.FeatureSupplyMode = SupplyMode.NonDivide; this.DivisionNum = 1; this.IndexForDivision = 0; if (_members == null) throw new SystemException("メンバがnullです。"); if (_members.Length == 0) throw new SystemException("配列サイズが0です。"); this.MemberSize = _members[0].Length; foreach (Feature newMenber in _members) { this.buff.Add(new Feature(newMenber)); if (this.MemberSize != newMenber.Length) throw new SystemException("渡された特徴ベクトルのサイズが不統一です。"); } this.myRandom = new Random(this.className.GetHashCode()); }
/// <summary> /// 識別結果をIDと尤度の配列で返す /// </summary> /// <param name="feature">特徴ベクトル</param> /// <param name="productionVolume">配列の生成数(1以上かつ出力ベクトルの次元を超えないようにして下さい)</param> /// <returns>IDと尤度をセットにした識別結果の配列</returns> public IDandLikelihood[] Discriminate(Feature feature, int productionVolume) { IDandLikelihood[] ans = null; if (this.Ready) { Vector result = this._NNet.Recognize(feature); ans = this.GetIDandLikelihood(result, productionVolume); } return ans; }
/// <summary> /// 識別結果をIDと尤度で返す /// </summary> /// <param name="feature">特徴ベクトル</param> /// <returns>IDと尤度をセットにした識別結果</returns> public IDandLikelihood Discriminate(Feature feature) { IDandLikelihood ans = new IDandLikelihood(); if (this.Ready) { Vector result = this._NNet.Recognize(feature); ans = this.GetIDandLikelihood(result, 1)[0]; } return ans; }
/// <summary> /// フォルダを指定してモデルデータを読み込む /// <para>既にセットされていたモデルは初期化されます。</para> /// <para>読み込んだファイル名の一覧よりモデルリストを作成し、ファイルの中身から入力層に必要なユニット数を確保します。</para> /// <para>読み込まれた特徴量がモデルによって異なる場合は、学習の段階で入力ユニット数と特徴ベクトルのサイズの不一致に関するエラーがスローされます。</para> /// </summary> /// <param name="dirName">特徴データの格納されたフォルダ名</param> /// <exception cref="SystemException">ファイルから読み込んだ特徴ベクトルの長さとニューラルネットの入力層ユニット数が一致しない場合にスロー</exception> public void Setup(string dirName) { this._class = new List<Model>(0); if (System.IO.Directory.Exists(dirName) == false) throw new ArgumentException("TeacherクラスのSetup()メソッドにてエラーがスローされました。指定されたフォルダは存在しません。"); string[] fnames = System.IO.Directory.GetFiles(dirName, "*.fea"); // フォルダ内の指定拡張子を持つファイル一覧を取得 if (fnames.Length > 1) { Hashtable modelID = Teacher.GetModelIDs(fnames); // ファイル名の一覧からユニークなモデルIDを取得 if (modelID.Count >= 2) { var models = new Model[modelID.Count]; // 存在するファイルの数だけモデルを生成する // クラスモデルを構成 foreach(var fname in fnames) { string id = Teacher.GetModelIDname(fname); // ファイル名からモデル名を取得 var index = (int)modelID[id]; // modelID[id]で、番号を得ることができる if (models[index] == null) models[index] = new Model(id); // インスタンスが未生成なら作る using (System.IO.StreamReader sr = new System.IO.StreamReader(fname, Encoding.UTF8)) { try { while (sr.EndOfStream == false) { string line = sr.ReadLine(); // 一行読み込み Feature feature = new Feature(line); // 読み込んだテキストデータから特徴ベクトルを生成 models[index].Add(feature); // 特徴を追加 } } catch (Exception e) { string message = "エラーがスローされました。\nエラーメッセージ:" + e.Message + "エラーの発生したファイル名:" + fname; Console.WriteLine(message); throw new Exception(message); // さらにスロー } } } this.Setup(models); } else throw new Exception("TeacherクラスのSetup()メソッドにてエラーがスローされました。モデルが2つ以上見つかりませんでした。"); } else throw new Exception("TeacherクラスのSetup()メソッドにてエラーがスローされました。特徴ベクトルを格納したファイル(*.fea)が2つ以上見つかりませんでした。フォルダ若しくは拡張子をチェックして下さい。"); return; }