Развертывание модели анализа данных в приложении для Windows с помощью интерфейсов API Windows ML
Из предыдущей части этого руководства вы узнали, как создавать и экспортировать модели в формате ONNX. Теперь мы продемонстрируем, как внедрить экспортированную ранее модель в приложение для Windows и локально ее запустить на устройстве с помощью вызова интерфейсов API Windows ML.
По завершении этого процесса у вас будет готовое приложение для анализа данных.
Сведения о примере приложения
На этом этапе вы создадите приложение, которое будет анализировать табличные данные Ирисов Фишера. Приложение позволит добавить файл Excel с необходимыми входными данными или вручную ввести входные параметры (длина и ширина чашелистика и лепестка Ирисов в см). Эти признаки будут обработаны локально хранимой моделью ONNX нейронной сети, которая была создана и обучена в предыдущей части. В зависимости от выходных данных модели приложение будет отображать правильный тип Ирисов.
В этой статье мы подробно рассматриваем этот процесс.
Примечание.
Если вы предпочитаете получить готовый пример кода, клонируйте файл решения. Для этого клонируйте репозиторий, перейдите в нем к нужному примеру и откройте файл Iris Data Analysis.csproj
в Visual Studio. Процесс работы с ним описан далее, в разделе Запуск приложения.
Ниже показано, как создать приложение и добавить в него код Windows ML.
Создание классического приложения (C#) для Windows ML
Чтобы получить работающее приложение Windows ML, сделайте следующее:
- Загрузите модель машинного обучения.
- Создайте привязки для входных и выходных данных модели.
- Оцените модели и отобразите полезные результаты.
Вам также потребуется создать базовый пользовательский интерфейс для повышения удобства работы пользователей.
Открытие нового проекта в Visual Studio
- Итак, приступим. Откройте Visual Studio и выберите
Create a new project
.
- На панели поиска выберите язык
C#
, целевую платформуWindows
и тип проектаDektop
. ВыберитеNUnit Test Project (.NET Core)
в качестве типа проекта, а затем —next
, чтобы открыть окно конфигурации для проекта.
- В окне конфигурации сделайте следующее:
- Присвойте проекту имя. В нашем примере это Анализ данных Ирисов.
- Выберите расположение проекта.
- Если вы используете 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
содержит код XAML для графического пользовательского интерфейса, а файл MainPage.xaml.cs
— код приложения. Если вы уже создавали приложения UWP, эти файлы должны быть вам хорошо знакомы.
Хотя мы и добавили наш файл Network.onnx
в папку ресурсов, необходимо корректно добавить его в этот проект.
- Щелкните правой кнопкой мыши папку ресурсов в Обозревателе решений и выберите
Add > Existing Item
. - Перейдите в папку ресурсов в
Iris Data Analysis [….\Iris Data Analysis \Assets]
, найдитеNetwork.onnx model
, которую вы ранее скопировали туда, и выберитеAdd
. - Чтобы убедиться, что модель успешно создается при компиляции приложения, щелкните правой кнопкой мыши файл
Network.onnx
и выберитеProperties
. Задайте дляBuild Action
значениеContent
.
Вам также потребуется создать файл класса cs-code для размещения некоторого дополнительного кода машинного обучения, включающего классы и методы, которые будут вызывать интерфейсы API Windows ML.
- Щелкните правой кнопкой мыши имя решения в Visual Studio и выберите
add
иnew item
. В открывшемся окне выберитеClass
и присвойте ему имя. В нашем примере этоIrisModel.cs
. В вашем проекте появится новый файл класса.
.
Создание кода машинного обучения
На этом этапе мы создадим все классы и методы, которые будут вызывать интерфейсы API Windows Machine Learning. Это позволит загрузить, привязать и оценить модель машинного обучения ONNX в вашем проекте.
Дважды щелкните файл
IrisModel.cs
.Замените операторы using следующими, чтобы получить доступ ко всем необходимым интерфейсам API.
using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.AI.MachineLearning;
using Windows.Storage;
Инициализация классов машинного обучения
Для взаимодействия с интерфейсами API Windows Machine Learning необходимо добавить несколько классов в IrisModel.cs
.
Чтобы получить доступ к обученной модели машинного обучения, мы будем использовать класс LearningModel
. Этот класс является частью пространства имен Windows.AI.MachineLearning
и представляет обученную модель машинного обучения. Созданный экземпляр LearningModel
является основным объектом, который вы используете для взаимодействия с интерфейсами API Windows ML.
Чтобы оценить модель обучения, необходимо создать сеанс оценки. Для этого используется класс LearningModelSession
. Этот класс используется для оценки моделей машинного обучения и привязки модели к устройству, которое затем запускается и оценивает модель. При создании сеанса с помощью этого API можно также выбрать устройство для выполнения модели (по умолчанию используется ЦП).
Кроме того, необходимо указать метки выходных данных моделей машинного обучения. Эти метки можно позже подключить к прогнозируемым выходным данным модели.
Примечание.
Чтобы узнать больше о классах 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
.
Примечание.
Дополнительные сведения о других способах загрузки модели см. в этой документации.
- Скопируйте следующий код в файл
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);
}
Определение входного тензора модели
Теперь мы определим правильные входные данные на основе требований к модели. Сетевая модель, созданная в предыдущей части, имеет четыре входных значения. Каждое входное значение представляет возможные размеры четырех признаков Ирисов: длина чашелистика в см, ширина чашелистика в см, длина лепестка в см и ширина лепестка в см. На основе этих входных данных модель будет возвращать тип Ирисов, который наилучшим образом соответствует этим параметрам. Необходимо ограничить размер входных значений допустимыми логическими значениями. В этом учебнике мы будем использовать следующие значения:
- длина чашелистика — от 1 до 100 см;
- ширина чашелистика — от 1 до 8 см;
- длина лепестка — от 0,5 до 10 см;
- ширина лепестка — от 0,1 до 5 см.
- Скопируйте следующий код в файл
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;
}
}
}
Интерфейсы API Windows ML принимают входные значения четырех описательных классов, поддерживаемых моделями ONNX: тензоры, последовательности, карты и изображения. В этом случае для модели требуется 32-разрядный свободно перемещаемый объект тензора в форме float32[batch_size,4]. Так как размер пакета равен 1, форма входного тензора имеет значение [1x4].
Для создания входных данных тензора используется класс TensorFloat.
Класс TensorFloat
является частью пространства имен Windows.AI.MachineLearning
и используется для определения 32-разрядного свободно перемещаемого объекта тензора — тензор 32-разрядных значений с плавающей запятой. Этот класс содержит несколько полезных методов для создания тензора. В этом случае будет использоваться метод CreateFromArray для создания входных данных тензора в нужном размере для вашей модели. Мы добавим этот вызов в метод оценки.
Привязка и оценка модели
Теперь, когда вы определили входной тензор модели и создали обученную модель и сеанс, пришло время создать метод для привязки и вычисления обученной модели машинного обучения.
Этот метод является ключевой частью приложения машинного обучения. Он включает преобразование входных значений в тензор и привязку входных данных модели. Эта модель будет использоваться позже в коде приложения для оценки модели.
Для привязки входных и выходных данных нужно использовать класс LearningModelBinding
. Модель машинного обучения имеет выходные и выходные признаки для передачи информации в модель и из нее. Имейте в виду, что требуемые признаки должны поддерживаться интерфейсами API Windows ML. Класс LearningModelBinding
применяется к LearningModelSession
для привязки значений к именованным входным и выходным признакам.
Класс LearningModelBinding
имеет несколько предопределенных методов, которые можно использовать для привязки значений к этим именованным признакам. Здесь для привязки значений к модели будет использоваться метод Bind
.
Чтобы оценить модель и получить из нее результаты, следует вызвать соответствующие предопределенные методы оценки из LearningModelSession
. В нашем случае — метод Evaluate
. Этот метод предоставит необходимые вам функции, оценивая модель машинного обучения с помощью значений функций, предоставляемых классом LearningModelBinding
.
Примечание.
Чтобы узнать о других методах оценки для запуска модели, проверьте, какие методы можно реализовать в LearningModelSession, просмотрев документацию по классу LearningModelSession.
Извлечение и отображение результатов
Модель возвращает прогнозируемые значения в формате тензоров в качестве свободно перемещаемых выходных данных тензора. Теперь вам необходимо извлечь выходные данные модели и отобразить правильные результаты. Для этого преобразуйте формат тензора в векторный, выполнив функцию GetAsVectorView()
в спрогнозированных выходных данных.
Модель возвращает три значения вероятности, каждое из которых представляет один конкретный тип Ирисов. Вам необходимо вернуть метку с наибольшей вероятностью.
- Скопируйте следующий код в файл
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 и управляющий код для тестирования модели с помощью уже созданных методов.
Создание графического пользовательского интерфейса приложения
Чтобы создать код приложения графического пользовательского интерфейса для вашего приложения, дважды щелкните файл кода
MainPage.xaml
и откройте предопределенный шаблон для вашего графического пользовательского интерфейса.Скопируйте и вставьте приведенный ниже код в
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()
, созданный в предыдущей части модели. Этот метод будет применяться четыре раза, по одному разу для каждого входного параметра: длина чашелистика, ширина чашелистика, длина лепестка и ширина лепестка.
Приложение отобразит результат на основе алгоритма прогнозирования машинного обучения.
- Чтобы создать управляющий код приложения, дважды щелкните файл кода
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
. Для запуска проекта на локальном компьютере укажите для параметра "Платформа решения" значение x64 для 64-разрядного устройства или x86 для 32-разрядного.
Графический пользовательский интерфейс приложения содержит четыре ползунка для изменения входных данных обязательных параметров. Любое изменение во входных данных приведет к формированию новых выходных данных на основе алгоритма прогнозирования. Выходные данные отображаются под ползунками ввода.
Вы можете наблюдать, что при заданном наборе входных данных длины чашелистика = 40 мм, ширины чашелистика = 50 мм, ширины лепестка = 75 мм и ширины лепестка = 15 мм приложение создало входные данные типа "Ирис разноцветный"!
Итоги
Вы только что создали свое первое приложение для Windows Machine Learning — от этапа создания модели до этапа успешного выполнения.
Дополнительные ресурсы
Дополнительные сведения см. в следующих статьях:
- Инструменты Windows ML. Ознакомьтесь с дополнительными инструментами, такими как информационная панель Windows ML, WinMLRunner и генератор кода mglen из Windows ML.
- Модель ONNX. Дополнительные сведения о формате ONNX.
- Использование вычислительной мощности и памяти для Windows ML. Узнайте, как управлять производительностью приложений в Windows ML.
- Справочник по API Windows Machine Learning. Узнайте больше о трех областях API-интерфейсов Windows ML.