このチュートリアルの前のパートでは、ONNX 形式でモデルを構築およびエクスポートする方法について説明しました。 次に、エクスポートしたモデルを Windows アプリケーションに埋め込み、Windows ML API を呼び出してデバイス上でローカルに実行する方法について説明します。
完了までに、データ分析アプリが動作します。
サンプル アプリについて
チュートリアルのこの手順では、Irises の表形式データを分析できるアプリを作成します。 このアプリでは、必要な入力情報を含む Excel ファイルを追加したり、入力パラメーター (Iris のセパルと花弁の長さと幅を cm 単位で手動で入力) したりできます。これらの機能は、前のパートで構築およびトレーニングしたローカルに格納されたニューラル ネットワーク ONNX モデルによって処理されます。 モデルの出力に基づいて、アプリに正しい Iris の種類が表示されます。
ここでは、そのプロセスについて説明します。
注
定義済みのコード サンプルを使用する場合は、ソリューション ファイルをクローンできます。 リポジトリをクローンし、このサンプルに移動して、Iris Data Analysis.csproj ファイルを Visual Studio で開きます。このページの「アプリケーションの起動」に進み、それが使用されていることを確認します。
以下では、アプリを作成し、Windows ML コードを追加する方法を説明します。
Windows ML Desktop (C#) アプリを作成する
Windows ML アプリを動作させるには、以下のことを行う必要があります。
- 機械学習モデルを読み込みます。
- モデルの入力と出力をバインドします。
- モデルを評価し、意味のある結果を表示します。
また、より優れたユーザー エクスペリエンスを提供するために、基本的な UI を作成する必要もあります。
Visual Studio で新しいプロジェクトを開く
- 始めましょう。 Visual Studio を開き、[
Create a new project] を選択します。
- 検索バーで、言語として
C#を選択し、ターゲット プラットフォームとしてWindowsし、プロジェクトの種類としてDektopします。 プロジェクトの種類としてNUnit Test Project (.NET Core)を選択し、nextを選択してプロジェクトの構成ウィンドウを開きます。
- 構成ウィンドウで、次のようにします。
- プロジェクトに名前を付けます。 ここでは、 Iris Data Analysis と呼びます。
- プロジェクトの場所を選択します。
- VS2019 を使用している場合は、
Create directory for solutionがオンになっていることを確認します。 - VS2017 を使用している場合は、
Place solution and project in the same directoryがオフになっていることを確認します。
createキーを押してプロジェクトを作成します。 最小ターゲット バージョン ウィンドウがポップアップ表示される場合があります。 最小バージョンは必ず Windows 10 バージョン 1809 (10.0 ビルド 17763) 以降に設定してください。
- プロジェクトが作成されたら、プロジェクト フォルダーに移動して、assetsフォルダー
[….\DataClassifier\Assets]を開き、この場所にNetwork.onnxファイルをコピーします。
プロジェクト ソリューションを探索する
プロジェクト ソリューションを調べてみましょう。
Visual Studio は、ソリューション エクスプローラー内に複数の cs コード ファイルを自動的に作成しました。
MainPage.xaml には GUI の XAML コードが含まれており、 MainPage.xaml.cs にはアプリケーション コードが含まれています。 以前に UWP アプリを作成したことがある場合、これらのファイルは非常に使い慣れているはずです。
Network.onnx ファイルを assets フォルダーに追加しましたが、このプロジェクトに適切に追加する必要があります。
- ソリューション エクスプローラーで [Assets] フォルダーを右クリックし、[
Add > Existing Item] を選択します。 -
Iris Data Analysis [….\Iris Data Analysis \Assets]内の Assets フォルダーに移動し、先にコピーしたNetwork.onnx modelを見つけて、Addを選択します。 - アプリケーションのコンパイル時にモデルが確実にビルドされるようにするには、
Network.onnxファイルを右クリックし、Propertiesを選択します。Build ActionをContentに設定します。
また、Windows ML API を呼び出すクラスとメソッドを含む追加の機械学習コードに対応するために、新しい cs コード クラス ファイルを作成する必要もあります。
- Visual Studio でソリューション名を右クリックし、[
addとnew item] を選択します。 開いているウィンドウでClassを選択し、名前を付けます。ここでは、IrisModel.csを使用します。 新しいクラスファイルがプロジェクトに追加されます。
します。
Machine Learning コードを作成する
この手順では、Windows Machine Learning API を呼び出すすべてのクラスとメソッドを作成します。 これにより、プロジェクト内の ONNX 機械学習モデルを読み込み、バインドし、評価できます。
IrisModel.csファイルをダブルクリックします。必要なすべての API にアクセスするには、 using ステートメントを次のステートメントに置き換えます。
using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.AI.MachineLearning;
using Windows.Storage;
機械学習クラスを初期化する
Windows Machine Learning API の操作に役立ついくつかのクラスを IrisModel.cs に追加する必要があります。
トレーニング済みの機械学習モデルにアクセスするには、 LearningModel クラスを使用します。 このクラスは、 Windows.AI.MachineLearning 名前空間の一部であり、トレーニング済みの機械学習モデルを表します。 インスタンス化された LearningModel は、Windows ML API との対話に使用するメイン オブジェクトです。
学習モデルを評価するには、評価セッションを作成する必要があります。 そのためには、 LearningModelSession クラスを使用します。 このクラスは、機械学習モデルを評価するために使用され、モデルを実行して評価するデバイスにモデルをバインドします。 この API を使用してセッションを作成するときに、モデルを実行するデバイスを選択することもできます (既定値は CPU です)。
さらに、機械学習モデルの出力のラベルを指定する必要があります。 これらのラベルは、後でモデルの予測出力に接続できます。
注
LearningModelクラスとLearningModelSession クラスの詳細については、LearningModel クラスのドキュメントと LearningModelSession クラスのドキュメントを参照してください。
- 次のコードを
IrisModel.csファイルにコピーします。
class IrisModel
{
private LearningModel _learning_model;
private LearningModelSession _session;
private String[] _labels = { "Iris-setosa", "Iris-versicolor", "Iris-virginica"};
モデルを読み込む
次に、機械学習モデルを読み込み、セッションを作成する必要があります。セッションは、定義したクラスで行います。 モデルを読み込むには、 LearningModel クラスのいくつかの静的メソッドを使用します。ここでは LoadFromStorageFileAsync を使用します。これにより、 ISorageFile から ONNX モデルを非同期に読み込むことができます。
注
モデルを読み込むその他の方法の詳細については、 モデルの読み込みのドキュメントを参照してください。
- 次のコードを
IrisModel.csファイルにコピーします。
public async Task Initialize()
{
// Load and create the model and session
var modelFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Assets//Network.onnx"));
_learning_model = await LearningModel.LoadFromStorageFileAsync(modelFile);
_session = new LearningModelSession(_learning_model);
}
モデル入力テンソルを定義する
次に、モデルの要件に基づいて正しい入力を定義します。 前のパートで構築したネットワーク モデルには、4 つの入力値があります。 すべての入力値は、4 つの特徴の可能なサイズを表します。cm の分離長さ、cm のセパル幅、花弁の長さ (cm)、花弁の幅 (cm) です。この入力に基づいて、モデルはそれらのパラメーターに最適な虹彩の種類を返します。 入力値のサイズを有効な論理値に制限する必要があります。このチュートリアルでは、次を使用します。
- ガクの長さ - 1cmから100cm
- セパル幅 – 1cmから8cm
- 花弁の長さ – 0.5cmから10cm
- 花弁の幅 – 0.1cmから5cm
- 次のコードを
IrisModel.csファイルにコピーします。
private float _sepal_length = 1.0f;
public float Sepal_Length
{
get
{
return _sepal_length;
}
set
{
// validate range [1,10]
if (value >= 1 && value <= 10)
{
_sepal_length = value;
}
}
}
private float _sepal_width = 1.0f;
public float Sepal_Width
{
get
{
return _sepal_width;
}
set
{
// validate range [1, 8]
if (value >= 1 && value <= 8)
{
_sepal_width = value;
}
}
}
private float _petal_length = 0.5f;
public float Petal_Length
{
get
{
return _petal_length;
}
set
{
// validate range [0.5, 10]
if (value >= 0.5 && value <= 10)
{
_petal_length = value;
}
}
}
private float _petal_width = 0.1f;
public float Petal_Width
{
get
{
return _petal_width;
}
set
{
// validate range [0.1, 5]
if (value >= 0.1 && value <= 5)
{
_petal_width = value;
}
}
}
Windows ML API は、ONNX モデルでサポートされている 4 つの記述クラス (テンソル、シーケンス、マップ、イメージ) の入力値を受け入れます。 この場合、モデルには float32[batch_size,4] の形状を持つ 32ビットのテンソルフロートオブジェクトが必要です。 バッチ サイズは 1 であるため、入力テンソル図形は [1x4] です。
テンソル入力を作成するには、 TensorFloat クラスを使用します。
TensorFloat クラスはWindows.AI.MachineLearning名前空間の一部であり、32 ビット浮動小数点型のテンソル オブジェクト (32 ビット浮動小数点値のテンソル) を定義するために使用されます。 このクラスには、テンソルを構築するための便利なメソッドがいくつか含まれています。 この場合は、 CreateFromArray メソッドを使用して、モデルに必要な正確なサイズでテンソル入力を作成します。 評価メソッド内にその呼び出しを追加します。
モデルのバインドおよび評価
モデル入力テンソルを定義し、トレーニング済みのモデルとセッションをインスタンス化したので、トレーニング済みの機械学習モデルをバインドして評価するメソッドを作成します。
この方法は、機械学習アプリの重要な部分です。 これには、入力値のテンソル化とモデル入力のバインドが含まれます。 このモデルは、後でアプリケーション コードで使用してモデルを評価します。
入力と出力をバインドするには、 LearningModelBinding クラスを使用します。 機械学習モデルには、モデルとの間で情報を渡す入力機能と出力機能があります。 必要な機能は Windows ML API でサポートされている必要があることに注意してください。
LearningModelBinding クラスは、名前付きの入力および出力機能に値をバインドするために、LearningModelSessionに適用されます。
LearningModelBinding クラスには、これらの名前付き特徴に値をバインドするために使用できる定義済みのメソッドがいくつかあります。 ここでは、 Bind メソッドを使用して、値をモデルにバインドします。
モデルを評価し、そこから結果を受け取るには、 LearningModelSession から relevent 定義済みの回避メソッド (実際の場合は Evaluate メソッド) を呼び出します。 このメソッドは、必要な機能を提供し、 LearningModelBinding クラスによって提供される特徴値を使用して機械学習モデルを評価します。
注
モデルを実行するための他の評価メソッドについては、LearningModelSession クラスのドキュメントを参照して、LearningModelSession にどのようなメソッドを実装できるかを確認してください。
結果を抽出して表示する
このモデルは、テンソル形式の予測値を Tensor 浮動小数点出力として返します。 次に、モデルの出力を抽出し、適切な結果を表示する必要があります。 これを行うには、述語付き出力で GetAsVectorView() 関数を実行して、テンソル形式をベクトルに変換します。
モデルは 3 つの確率値を返し、それぞれが 1 つの特定の虹彩の種類を表します。 最も高い確率でラベルを返す必要があります。
- 次のコードを
IrisModel.csファイルにコピーします。
internal String Evaluate()
{
// input tensor shape is [1x4]
long[] shape = new long[2];
shape[0] = 1;
shape[1] = 4;
// set up the input tensor
float[] input_data = new float[4];
input_data[0] = _sepal_length;
input_data[1] = _sepal_width;
input_data[2] = _petal_length;
input_data[3] = _petal_width;
TensorFloat tensor_float = TensorFloat.CreateFromArray(shape, input_data);
// bind the tensor to "input"
var binding = new LearningModelBinding(_session);
binding.Bind("input", tensor_float);
// evaluate
var results = _session.Evaluate(binding, "");
// get the results
TensorFloat prediction = (TensorFloat)results.Outputs.First().Value;
var prediction_data = prediction.GetAsVectorView();
// find the highest predicted value
int max_index = 0;
float max_value = 0;
for (int i = 0; i < prediction_data.Count; i++)
{
var val = prediction_data.ElementAt(i);
if (val > max_value)
{
max_value = val;
max_index = i;
}
}
// return the label corresponding to the highest predicted value
return _labels.ElementAt(max_index);
}
これで、コードの機械学習部分が完了しました。 これで、モデルを Windows アプリケーションと簡単に統合できるようになりました。 このチュートリアルの最後の部分では、既に作成したメソッドを使用して、モデルをテストするための基本的な Windows GUI とコントロール コードを提供しました。
アプリケーション GUI を作成する
アプリの GUI アプリ コードを作成するには、
MainPage.xamlコード ファイルをダブルクリックし、GUI 用の定義済みのテンプレートを開きます。次のコードをコピーして、
MainPage.xaml行の下の“Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" " Height="939">に貼り付けます。
<Grid Margin="30,30,30,30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock x:Name="title" HorizontalAlignment="Left" Text="Data Analysis App - Windows ML" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="32" TextDecorations="Underline" FontWeight="Bold"/>
<TextBlock x:Name="subtitle" HorizontalAlignment="Left" Text="Provide the input :" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="20" Grid.Row="1" FontWeight="Bold"/>
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="sepal_length" Text="sepal length in mm [range of 10 - 100]:" VerticalAlignment="Center"/>
<TextBlock x:Name="sepal_width" Text="sepal width in mm [range of 10 - 80]:" VerticalAlignment="Center" Grid.Row="1"/>
<TextBlock x:Name="petal_length" Text="petal length in mm [range of 5 - 100]:" VerticalAlignment="Center" Grid.Row="2"/>
<TextBlock x:Name="petal_width" Text="sepal width in mm [range of 1 - 50]:" VerticalAlignment="Center" Grid.Row="3"/>
<Slider x:Name="sepal_length_input" Minimum="10" Maximum="100" Orientation="Horizontal" Grid.Column="1" Width="200" ValueChanged="sepal_length_input_ValueChanged"/>
<Slider x:Name="sepal_width_input" Minimum="10" Maximum="80" Orientation="Horizontal" Grid.Row="1" Grid.Column="1" Width="200" ValueChanged="sepal_width_input_ValueChanged"/>
<Slider x:Name="petal_length_input" Minimum="5" Maximum="100" Orientation="Horizontal" Grid.Row="2" Grid.Column="1" Width="200" ValueChanged="petal_length_input_ValueChanged"/>
<Slider x:Name="petal_width_input" Minimum="1" Maximum="50" Orientation="Horizontal" Grid.Row="3" Grid.Column="1" Width="200" ValueChanged="petal_width_input_ValueChanged"/>
</Grid>
<TextBlock x:Name="output" Text="Output:" FontSize="20" FontWeight="Bold" Grid.Row="3"/>
<Grid Grid.Row="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="output_subtitle" Text="Based on the information provided, the Iris type is:"/>
<TextBlock x:Name="model_output" Text="Model output" FontStyle="Italic" Grid.Column="1" Margin="10,0,0,0"/>
</Grid>
</Grid>
アプリケーション コントロールを作成する
アプリケーション制御コード MainPage.xaml.csには、アプリを実行するための main メソッドと、モデルを実行して出力を実行するいくつかの手順が含まれています。
- このチュートリアルで前に作成した
IrisModelクラスの新しいオブジェクトをインスタンス化します。 - モデルの前の部分でビルドした
Evaluate()メソッドを呼び出します。 このメソッドは、各入力パラメーターに 1 つずつ、セパルの長さ、セパルの幅、花弁の長さ、花弁の幅の 4 回適用されます。
アプリには、機械学習予測アルゴリズムに基づいて結果が表示されます。
- アプリケーション コントロール コードを作成するには、
MainPage.xaml.csコード ファイルをダブルクリックし、次のコードを追加します。
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace Iris_Data_Analysis
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
private IrisModel _iris_model;
public MainPage()
{
this.InitializeComponent();
_iris_model = new IrisModel();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
_iris_model.Initialize();
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}
private void sepal_length_input_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
if (_iris_model != null)
{
_iris_model.Sepal_Length = (float)sepal_length_input.Value / 10.0f;
model_output.Text = _iris_model.Evaluate();
}
}
private void sepal_width_input_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
if (_iris_model != null)
{
_iris_model.Sepal_Width = (float)sepal_width_input.Value / 10.0f;
model_output.Text = _iris_model.Evaluate();
}
}
private void petal_length_input_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
if (_iris_model != null)
{
_iris_model.Petal_Length = (float)petal_length_input.Value / 10.0f;
model_output.Text = _iris_model.Evaluate();
}
}
private void petal_width_input_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
if (_iris_model != null)
{
_iris_model.Petal_Width = (float)petal_width_input.Value / 10.0f;
model_output.Text = _iris_model.Evaluate();
}
}
}
}
アプリケーションを起動する
これで、アプリケーションを起動して結果を表示する準備ができました。
開発者モードを有効にして、Visual Studio からアプリケーションをテストします。 上部のツール バーのドロップダウン メニューが Debug に設定されていることを確認します。 ローカル コンピューター上でプロジェクトを実行するように、デバイスが 64 ビットの場合は x64 に、32 ビットの場合は x86 にソリューション プラットフォームを変更します。
アプリ GUI には、必要なパラメーターの入力を変更するための 4 つのスライダーが含まれています。 入力を変更すると、予測アルゴリズムに基づいて新しい出力が生成されます。 出力は、入力スライダーの下に表示されます。
指定された入力のセパル長 = 40 mm、セパル幅 = 50、花弁の長さ = 75、花びらの幅 = 15、アプリが生成した Iris-versicolor 型の入力を確認できます。
概要
モデルの作成から正常な実行まで、初めての Windows Machine Learning アプリを作成しました。
その他のリソース
このチュートリアルで説明されているトピックの詳細については、次のリソースを参照してください。
- Windows ML ツール: Windows ML ダッシュボード、 WinMLRunner、 mglen Windows ML コード ジェネレーターなどのその他のツールについて説明します。
- ONNX モデル: ONNX 形式の詳細を確認します。
- Windows ML のパフォーマンスとメモリ: Windows ML を使用してアプリのパフォーマンスを管理する方法の詳細について説明します。
- Windows Machine Learning API リファレンス: Windows ML API の 3 つの領域の詳細について説明します。