#author("2019-05-31T18:01:36+09:00","default:kyo-in","kyo-in")
**機械学習による図形推定 [#e2875e85]
機械学習ライブラリ[[ML.net:https://docs.microsoft.com/ja-jp/dotnet/machine-learning/]]を使用し,描かれたストロークの図形を推定して,整形された図形に置き換える機能を実装する.

#ref(./shapepredict.gif,50%);

**ML.netのインストール [#sf3d923f]
ML.netは.NET standard 2.0に依存している.UWPで.NET standard 2.0を使用可能な状態にするには最小ターゲットバージョンを1809にする必要がある.

ソリューションエクスプローラーから,Kisozemiプロジェクトのプロパティを開き,[アプリケーション]-[ターゲットバージョン]と[最小バージョン]を共に,1809に変更し,保存,いったんVisual Studioを再起動する.

#ref(./target.png,50%);

再起動後,[プロジェクト]-[NuGetパッケージの管理]を開き,[参照]からML.netを検索し,プロジェクトにインストールする.

#ref(./nuget.png,50%);

**学習モデルの読み込み [#r5ec9fc9]
本来,今回のような分類の機械学習を行う場合,学習データの準備と学習モデルの作成が必要となる.

しかし,時間も限られているため,今回はすでに作成されている学習モデルを読み込み,図形の分類推定に使用することとする.

以下のmodel.zipは,楕円と四角の図形を約60個学習させたモデルとなる.model.zipを置いておく場所は後述する.

#ref(./model.zip);

適当なButtonを用意し,Clickイベントでmodel.zipを読み込む.

ML.netを使用するため,usingに以下を追加:

 using Microsoft.ML;
 using Microsoft.ML.Data;

クラスのメンバに以下を追加:

 MLContext mlContext = null; 
 ITransformer strokePredictModel = null;

クリックイベント内で実際にmodel.zipを読み込む,''非同期処理(await, async)を使用しているため,イベントメソッドの先頭にasyncを追加すること'':

            Windows.Storage.StorageFolder storageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
            Windows.Storage.StorageFile modelFile = await storageFolder.GetFileAsync("model.zip");
 
            mlContext = new MLContext();
 
            //Define DataViewSchema for data preparation pipeline and trained model
            DataViewSchema modelSchema;
 
            // Load trained model
            using (System.IO.Stream stream = await modelFile.OpenStreamForReadAsync())
            {
                strokePredictModel = mlContext.Model.Load(stream, out modelSchema);
                stream.Flush();
            }

''注意''

UWPで作成されるアプリはiOSやAndroidのアプリ同様に,端末内のストレージに自由にアクセスすることはできない.

そのため,

             Windows.Storage.StorageFolder storageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;

によって,アプリが自由に使えるフォルダを取得している.このフォルダにmodel.zipを置いておくことになるが,このフォルダの場所は環境によりことなるため,各自確認すること.

ブレークポイントなどを使用することで,確認,パスのコピーができる.

#ref(./path.png,50%);

**図形の推定 [#ab8dd1e6]
以下の.csファイルをプロジェクトに追加する.中には機械学習用の入力データ(StrokeData),出力データ(StrokePredict)クラスが定義されている.

#ref(./StrokeData.cs);

学習モデルを読み込んだ状態であれば,ストロークを描き終えた後,そのストロークを特徴ベクトルに変換し,それを学習モデルに入力,図形の推定を行い,推定結果を基に該当する図形をストロークの大きさ,位置に生成する.

                    StrokeData input; 
                    //input に ストロークを特徴ベクトル化したデータを生成(後述)
 
                    StrokeData[] inputdata = new[] { input };
                    IDataView batchinput = mlContext.Data.LoadFromEnumerable(inputdata);
                    IDataView predictions = strokePredictModel.Transform(batchinput);
                    IEnumerable<StrokePredict> strokePredict = mlContext.Data.CreateEnumerable<StrokePredict>(predictions, reuseRowObject: false);
                    foreach(StrokePredict sp in strokePredict)
                    {
                        AddMessage($"Prediction: {(Convert.ToBoolean(sp.Prediction) ? "Ellipse" : "Rect")} | Probability: {sp.Probability} ");
                        var rect = drawingStroke.PathShape.Data.Bounds;
                        if (sp.Prediction == true) //trueであれば楕円として推定されたのでEllipseをrectのサイズ,位置で生成する
                        {

Shapeクラスの位置指定はCanvas.Set〜メソッドで行う.

 Canvas.SetLeft(ellipse, rect.X);
 Canvas.SetTop(ellipse, rect.Y);

**ストロークから特徴ベクトルの生成 [#ea8301d7]

トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS