Windows ML API を使用してデータ分析モデルを Windows アプリに展開する
このチュートリアルの前のパートでは、モデルを ONNX 形式で構築し、エクスポートする方法を学習しました。 ここでは、エクスポートしたモデルを Windows アプリケーションに埋め込み、Windows ML API を呼び出してローカル環境のデバイスで実行する方法について説明します。
完了すると、データ分析アプリが機能するようになります。
サンプル アプリケーションについて
チュートリアルのこの手順では、アヤメの表形式のデータを分析できるアプリを作成します。 このアプリでは、必要な入力情報を含む Excel ファイルを追加することも、入力パラメーター (アヤメのがく片と花弁の長さおよび幅 (cm)) を手動で入力することもできます。これらの特徴は、前のパートで作成してトレーニングし、ローカルに保存したニューラル ネットワーク ONNX モデルによって処理されます。 このアプリにより、モデルの出力に基づいて、正しいアヤメの種類が表示されます。
ここでは、そのプロセスについて説明します。
Note
定義済みのコード サンプルを使用する場合は、ソリューション ファイルをクローンできます。 リポジトリをクローンし、このサンプルに移動して、Iris Data Analysis.csproj
ファイルを Visual Studio で開きます。このページの「アプリケーションの起動」に進み、それが使用されていることを確認します。
以下では、アプリを作成し、Windows ML コードを追加する方法を説明します。
Windows ML デスクトップ (C#) アプリを作成する
Windows ML アプリを動作させるには、以下のことを行う必要があります。
- 機械学習モデルを読み込みます。
- モデルの入力と出力をバインドします。
- モデルを評価し、意味のある結果を表示します。
さらに、より優れたユーザー エクスペリエンスを提供するために、基本的な UI を作成することも必要です。
Visual Studio で新しいプロジェクトを開く
- では、始めましょう。 Visual Studio を開き、
Create a new project
を選択します。
- 検索バーで、言語として [
C#
]、ターゲット プラットフォームとして [Windows
]、プロジェクトの種類として [Dektop
] を選択します。 プロジェクトの種類として [NUnit Test Project (.NET Core)
] を選択し、[next
] を選択して、プロジェクトの構成ウィンドウを開きます。
- 構成ウィンドウで、次のようにします。
- プロジェクトに名前を付けます。 ここでは、「Iris Data Analysis」という名前にします。
- プロジェクトの場所を選択します。
- VS 2019 を使用する場合は、[
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-code ファイルが自動的に作成されました。 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
に設定します。
さらに、追加の機械学習コードに対応するために、新しい cs-code クラス ファイルを作成する必要があります。これには、Windows ML API を呼び出すクラスとメソッドが含まれます。
- Visual Studio でソリューション名を右クリックし、[
add
] と [new item
] を選択します。 開いたウィンドウで、[Class
] を選択し、名前を付けます。ここでは、「IrisModel.cs
」を使用します。 プロジェクトの下に、新しいクラス ファイルが表示されます。
。
機械学習コードを作成する
この手順では、Windows Machine Learning API を呼び出すすべてのクラスとメソッドを作成します。 これらを使用して、プロジェクト内の ONNX 機械学習モデルを読み込んでバインドし、評価を行います。
IrisModel.cs
ファイルをダブルクリックします。using ステートメントを次のように置き換えて、必要なすべての API にアクセスできるようにします。
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 です)。
さらに、機械学習モデルの出力のラベルを指定する必要があります。 これらのラベルは、後でモデルの予測出力に接続できます。
Note
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 を使用します。これにより、ONNX モデルを ISorageFile
から非同期に読み込むことができます。
Note
モデルを読み込むためのその他の方法の詳細については、「モデルを読み込む」を参照してください。
- 次のコードを
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)) の可能なサイズを表します。モデルでは、この入力に基づいて、これらのパラメーターに最適なアヤメの種類を返します。 入力値のサイズを有効な論理値に制限する必要があります。このチュートリアルでは、次の値を使用します。
- がく片の長さ - 1 cm から 100 cm
- がく片の幅 - 1 cm から 8 cm
- 花弁の長さ - 0.5 cm から 10 cm
- 花弁の幅 - 0.1 cm から 5 cm
- 次のコードを
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
から関連する定義済みの評価メソッドを呼び出します。ここでは、Evaluate
メソッドを使用します。 このメソッドにより、必要な機能が提供され、LearningModelBinding
クラスによって提供される特徴値を使用して機械学習モデルを評価できます。
Note
モデルを実行するための他の評価メソッドについては、LearningModelSession クラスのドキュメントを参照して、LearningModelSession にどのようなメソッドを実装できるかを確認してください。
結果の抽出と表示
モデルによって、テンソル浮動小数点数出力としてテンソル形式の予測値が返されます。 次に、モデル出力を抽出して、適切な結果を表示する必要があります。 このためには、予測された出力に対して 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
には、アプリを実行するメイン メソッドと、モデルを実行して出力を実行するためのいくつかのステップが含まれています。
- このチュートリアルで前に作成した
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 の 3 つの領域について説明します。