読者です 読者をやめる 読者になる 読者になる

プログラムの事とか

お約束ですが「掲載内容は私個人の見解です」

機械学習でよくわからないまま画像識別して遊んでみる その2

f:id:puni-o:20160316142110j:plain

いよいよ作っていきます。

といっても学習ロジックは既存のライブラリに任せるので、そのライブラリをよくわからずに使うだけです。 学習部分を作るなんて無理っすよ。

プロジェクトを作る

画像やリストを出してみたい予定なのでWPFでつくります。

MVVMは面倒なのでやめます。

コードビハインドにガンガン書きます。

Accord.NETをつかう

accord-framework.net

C#」「機械学習」で検索したら出てきたのでこれを使います。

f:id:puni-o:20160316142821p:plain

NuGetでAccord.Imagingをインストールすれば必要なのがまとめて入ります。 画像を扱うのでSystem.Drawingの参照も忘れずに。

Accord.NETにはサンプルも用意されているので、このサンプルを参考に作っていきます。(というか写経していきます)

よくわからないのでサンプルの中から「Classification (BoW)」というのを選択しました。

BoWはBag of Wordsの略っぽいです。Bag of Wordsの説明はググればでてきますが下記ページを参考にしました。

d.hatena.ne.jp

画像から特徴を抽出してどうにかするってことですかね?よくわかりません。

学習の流れ

上記サンプルをみると

1.画像集から特徴を抽出する子を鍛える

2.鍛えた子から各画像の特徴をもらう

3.各画像の特徴がどのグループの画像なのかを学習させる

4.学習させた子で遊ぶ

という流れになるようです。よくわかりません。

1.抽出する子を鍛える

BagOfVisualWordsというクラスが抽出する子になるようです。

const int NumberOfWords = 200;  // 特徴点数?
private BagOfVisualWords _surfBow;
private void ComputeBagOfWords()
{
    // BinarySplitっていうアルゴリズムを使って特徴点を抽出するみたいだよ
    var binarySplit = new BinarySplit(NumberOfWords);
    this._surfBow = new BagOfVisualWords(binarySplit);

    // 学習用画像を配列にしておく
    var trainImages = new Bitmap[]{・・・・};

    // がんばってもらう
    this._surfBow.Compute(trainImages);
}

インスタンスを作ってBitmapの配列を渡せば頑張るらしいです。Bitmapクラスを渡せるところなんかは.Netのライブラリっぽくていいですね。

学習用画像は元の画像を左右反転させたのを追加するだけでも効果があるらしいので、そんな感じにしておきます。

2.鍛えた子から各画像の特徴をもらう

上で鍛えた_surfBowに画像を渡すとその画像の特徴をdouble[]で返してくれます。

foreach(var image in trainImages)
{
    // 特徴点を取得
    var vector = this._surfBow.GetFeatureVector(image);
    ・・・
});

3.各画像の特徴がどのグループの画像なのかを学習させる

MulticlassSupportVectorMachineっていうのを作ります(学習させます)。よくわかりません。

学習するにあたって学習方法(?)を指定する必要があります。 サンプルでは4種類から選ぶようになっていたので、私もそんな感じにしました。

private IKernel GetKernel()
{
    //return new Gaussian();
    //return new Linear();
    //return new Polynomial();
    return new ChiSquare();
    //return new HistogramIntersection(1, 1);
}

カイ二乗検定 - Wikipedia 固定デス。

コメント外せば選べるよ。

private MulticlassSupportVectorMachine _ksvm;
private void CreateVectorMachine()
{
    var classes = 6;    // 分類数
    var kernel = GetKernel();   // 学習手法?

    // 入力(抽出君が作ったVector)と出力(分類)を渡して学習してもらう(配列のIndexでみているっぽい)
    var input = new double[][]{・・・};
    var output = new int[]{・・・};
    var teacher = new MulticlassSupportVectorLearning(_ksvm, input, output);

    teacher.Algorithm = (svm, classInputs, classOutputs, i, j) => new SequentialMinimalOptimization(svm, classInputs, classOutputs);

    // 学習開始
    teacher.Run();
}

これで準備完了です。よくわかりません。

出来上がった_surfBow_ksvmを使って画像識別をします。

それぞれSaveメソッドLoadメソッドを持っていたのできっと保存できるんだと思います。 ということで保存して2回目移行は学習しなくてもいいようにしてみました。(ちゃんと状態が保存できているのかよくわかりませんが)

次回は実際に試してみます。