このチュートリアルでは、トレーニング済みの機械学習モデルを使用して、ユーザーが描画した数字を認識するシンプルなユニバーサル Windows プラットフォーム アプリケーションを構築します。 このチュートリアルでは、主に UWP アプリケーションで Windows ML を読み込んで使用する方法について説明します。
次のビデオでは、このチュートリアルの基になっているサンプルについて説明します。
完成したチュートリアルのコードを簡単に確認したい場合は、 WinML GitHub リポジトリで見つけることができます。 C++/CX でも使用できます。
[前提条件]
- Windows 10 (バージョン 1809 以降)
- Windows 10 SDK (ビルド 17763 以降)
- Visual Studio 2019 (または Visual Studio 2017 バージョン 15.7.4 以降)
- Visual Studio 2019 または 2017 用 Windows Machine Learning Code Generator 拡張機能
- 基本的な UWP と C# の知識
1. Visual Studio でプロジェクトを開く
GitHub からプロジェクトをダウンロードしたら、Visual Studio を起動し、 MNIST_Demo.sln ファイルを開きます ( <Path to repo>\Windows-Machine-Learning\Samples\MNIST\Tutorial\cs にあります)。 ソリューションが利用不可と表示されている場合は、 ソリューション エクスプローラー でプロジェクトを右クリックし、[ プロジェクトの再読み込み] を選択する必要があります。
実装された XAML コントロールとイベントを含むテンプレートを提供しました。
- 数字を描くためのInkCanvas。
- 数字 を解釈し、キャンバスをクリアするためのボタン。
- InkCanvas 出力を VideoFrame に変換するヘルパー ルーチン。
ソリューション エクスプローラー内には、プロジェクトに次の 3 つの主要なコード ファイルがあります。
- MainPage.xaml - InkCanvas、ボタン、ラベルの UI を作成するためのすべての XAML コード。
- MainPage.xaml.cs - アプリケーション コードが存在する場所。
- Helper.cs - イメージ形式をトリミングおよび変換するためのヘルパー ルーチン。
2. プロジェクトをビルドして実行する
Visual Studio ツール バーで、 ソリューション プラットフォーム を x64 に変更して、デバイスが 64 ビットの場合はローカル コンピューターでプロジェクトを実行し、32 ビットの場合は x86 に変更します。 (Windows 設定アプリで確認できます: システム >> デバイスの仕様 > システムの種類について)。
プロジェクトを実行するには、ツール バーの [デバッグの開始 ] ボタンをクリックするか、 F5 キーを押します。 アプリケーションには、ユーザーが数字を書き込むことができる InkCanvas、数字を解釈するための [認識] ボタン、解釈された数字がテキストとして表示される空のラベル フィールド、InkCanvas をクリアするための [Clear Digit] ボタンが表示されます。
注
プロジェクトがビルドされない場合は、プロジェクトの配置ターゲットのバージョンを変更する必要があります。 ソリューション エクスプローラーでプロジェクトを右クリックし、[プロパティ] を選択します。 [ アプリケーション ] タブで、OS と SDK に合わせて ターゲット バージョン と 最小バージョン を設定します。
注
アプリケーションが既にインストールされていることを示す警告が表示された場合は、[ はい ] を選択して展開を続行します。 それでも動作しない場合は、Visual Studio を閉じて再度開く必要があります。
3. モデルをダウンロードする
次に、アプリケーションに追加する機械学習モデルを取得しましょう。 このチュートリアルでは、 Microsoft Cognitive Toolkit (CNTK) でトレーニングされ、 ONNX 形式にエクスポートされた事前トレーニング済みの MNIST モデルを使用します。
MNIST モデルは既に Assets フォルダーに含まれており、既存の項目としてアプリケーションに追加する必要があります。 事前トレーニング済みのモデルは、GitHub の ONNX Model Zoo からダウンロードすることもできます。
4. モデルを追加する
ソリューション エクスプローラーで [Assets] フォルダーを右クリックし、[追加>項目の作成] を選択します。 ファイル ピッカーを ONNX モデルの場所にポイントし、[ 追加] をクリックします。
プロジェクトには、次の 2 つの新しいファイルが必要です。
- mnist.onnx - トレーニング済みのモデル。
- mnist.cs - Windows ML で生成されたコード。
アプリケーションのコンパイル時にモデルがビルドされるようにするには、 mnist.onnx ファイルを右クリックし、[プロパティ] を選択 します。 [ビルド アクション] で、[コンテンツ] を選択します。
次に、 mnist.cs ファイルで新しく生成されたコードを見てみましょう。 次の 3 つのクラスがあります。
- mnistModel は、機械学習モデル表現を作成し、システムの既定のデバイスでセッションを作成し、特定の入力と出力をモデルにバインドして、モデルを非同期的に評価します。
- mnistInput は、モデルが期待する入力型を初期化します。 この場合、入力には ImageFeatureValue が必要です。
- mnistOutput は、モデルが出力する型を初期化します。 この場合、出力は TensorFloat 型のPlus214_Output_0と呼ばれるリストになります。
次に、これらのクラスを使用して、プロジェクト内のモデルの読み込み、バインド、評価を行います。
5. モデルの読み込み、バインド、評価
Windows ML アプリケーションの場合、次のパターンは、Load > Bind > Evaluate です。
- 機械学習モデルを読み込みます。
- 入力と出力をモデルにバインドします。
- モデルを評価し、結果を表示します。
mnist.csで生成されたインターフェイス コードを使用して、アプリケーションでモデルの読み込み、バインド、評価を行います。
まず、 MainPage.xaml.csで、モデル、入力、出力をインスタンス化してみましょう。 MainPage クラスに次のメンバー変数を追加します。
private mnistModel ModelGen;
private mnistInput ModelInput = new mnistInput();
private mnistOutput ModelOutput;
次に、 LoadModelAsync でモデルを読み込みます。 このメソッドは、モデルのいずれかのメソッドを使用する前に呼び出す必要があります (つまり、 MainPage の Loaded イベント、 OnNavigatedTo オーバーライド、または recognizeButton_Click が呼び出される前の任意の場所)。 mnistModel クラスは MNIST モデルを表し、システムの既定のデバイスにセッションを作成します。 モデルを読み込むには、 CreateFromStreamAsync メソッドを呼び出し、ONNX ファイルをパラメーターとして渡します。
private async Task LoadModelAsync()
{
// Load a machine learning model
StorageFile modelFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Assets/mnist.onnx"));
ModelGen = await mnistModel.CreateFromStreamAsync(modelFile as IRandomAccessStreamReference);
}
注
IRandomAccessStreamReference の下に赤い下線が表示される場合は、その名前空間を含める必要があります。 カーソルを置き、 Ctrl キー を押しながら . キーを押し、ドロップダウン メニューから Windows.Storage.Streams の使用 を選択します。
次に、入力と出力をモデルにバインドします。 生成されたコードには、 mnistInput および mnistOutput ラッパー クラスも含まれます。 mnistInput クラスはモデルの予期される入力を表し、mnistOutput クラスはモデルの期待される出力を表します。
モデルの入力オブジェクトを初期化するには、 mnistInput クラス コンストラクターを呼び出してアプリケーション データを渡し、入力データがモデルで想定される入力型と一致していることを確認します。 mnistInput クラスは ImageFeatureValue を受け取るので、ヘルパー メソッドを使用して入力の ImageFeatureValue を取得します。
helper.csに含まれているヘルパー関数を使用して、InkCanvas の内容をコピーし、ImageFeatureValue 型に変換して、モデルにバインドします。
private async void recognizeButton_Click(object sender, RoutedEventArgs e)
{
// Bind model input with contents from InkCanvas
VideoFrame vf = await helper.GetHandWrittenImage(inkGrid);
ModelInput.Input3 = ImageFeatureValue.CreateFromVideoFrame(vf);
}
出力の場合は、指定された入力を使用して EvaluateAsync を呼び出すだけです。 入力が初期化されたら、モデルの EvaluateAsync メソッドを呼び出して、入力データでモデルを評価します。 EvaluateAsync は、入力と出力をモデル オブジェクトにバインドし、入力でモデルを評価します。
モデルは出力テンソルを返すので、最初にわかりやすいデータ型に変換し、返されたリストを解析して、最も高い確率を持つ数字を特定し、そのテンソルを表示します。
private async void recognizeButton_Click(object sender, RoutedEventArgs e)
{
// Bind model input with contents from InkCanvas
VideoFrame vf = await helper.GetHandWrittenImage(inkGrid);
ModelInput.Input3 = ImageFeatureValue.CreateFromVideoFrame(vf);
// Evaluate the model
ModelOutput = await ModelGen.EvaluateAsync(ModelInput);
// Convert output to datatype
IReadOnlyList<float> vectorImage = ModelOutput.Plus214_Output_0.GetAsVectorView();
IList<float> imageList = vectorImage.ToList();
// Query to check for highest probability digit
var maxIndex = imageList.IndexOf(imageList.Max());
// Display the results
numberLabel.Text = maxIndex.ToString();
}
最後に、ユーザーが別の数値を描画できるように InkCanvas をクリアします。
private void clearButton_Click(object sender, RoutedEventArgs e)
{
inkCanvas.InkPresenter.StrokeContainer.Clear();
numberLabel.Text = "";
}
6. アプリケーションを起動する
アプリケーションをビルドして起動すると ( F5 キーを押すと)、 InkCanvas に描画された数値を認識できるようになります。
これで、初めての Windows ML アプリケーションが作成されました。 Windows ML の使用方法を示すその他のサンプルについては、GitHub の Windows-Machine-Learning リポジトリを参照してください。
注
Windows ML のヘルプについては、次のリソースを使用してください。
- Windows ML に関する技術的な質問や回答を行うには、Stack Overflow の windows-machine-learning タグを使用してください。
- バグを報告するには、 GitHub で問題を報告してください。