Поделиться через


Развертывание модели анализа данных в приложении для 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

  1. Итак, приступим. Откройте Visual Studio и выберите Create a new project.

Create new Visual Studio project

  1. На панели поиска выберите язык C#, целевую платформу Windows и тип проекта Dektop. Выберите NUnit Test Project (.NET Core) в качестве типа проекта, а затем — next, чтобы открыть окно конфигурации для проекта.

Create new NUnit Test Project app

  1. В окне конфигурации сделайте следующее:
  • Присвойте проекту имя. В нашем примере это Анализ данных Ирисов.
  • Выберите расположение проекта.
  • Если вы используете VS 2019, установите флажок Create directory for solution.
  • Если вы используете VS2017, снимите флажок Place solution and project in the same directory.

Щелкните create, чтобы создать проект. Может появиться окно для ввода минимальной целевой версией. Убедитесь, что в качестве минимальной версии указана версия Windows 10 версии 1809 (10.0; сборка 17763) или более поздняя.

  1. После создания проекта перейдите в папку этого проекта, откройте папку assets ([….\DataClassifier\Assets]) и скопируйте файл Network.onnx в это расположение.

Обзор решения проекта

Давайте изучим решение проекта.

Visual Studio автоматически создает несколько файлов cs-code в Обозревателе решений. Файл MainPage.xaml содержит код XAML для графического пользовательского интерфейса, а файл MainPage.xaml.cs — код приложения. Если вы уже создавали приложения UWP, эти файлы должны быть вам хорошо знакомы.

Хотя мы и добавили наш файл Network.onnx в папку ресурсов, необходимо корректно добавить его в этот проект.

  1. Щелкните правой кнопкой мыши папку ресурсов в Обозревателе решений и выберите Add > Existing Item.
  2. Перейдите в папку ресурсов в Iris Data Analysis [….\Iris Data Analysis \Assets], найдите Network.onnx model, которую вы ранее скопировали туда, и выберите Add.
  3. Чтобы убедиться, что модель успешно создается при компиляции приложения, щелкните правой кнопкой мыши файл Network.onnx и выберите Properties. Задайте для Build Action значение Content.

Вам также потребуется создать файл класса cs-code для размещения некоторого дополнительного кода машинного обучения, включающего классы и методы, которые будут вызывать интерфейсы API Windows ML.

  1. Щелкните правой кнопкой мыши имя решения в Visual Studio и выберите add и new item. В открывшемся окне выберите Class и присвойте ему имя. В нашем примере это IrisModel.cs. В вашем проекте появится новый файл класса.

Add a new class file to your VS project.

Создание кода машинного обучения

На этом этапе мы создадим все классы и методы, которые будут вызывать интерфейсы API Windows Machine Learning. Это позволит загрузить, привязать и оценить модель машинного обучения ONNX в вашем проекте.

  1. Дважды щелкните файл IrisModel.cs.

  2. Замените операторы 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.

  1. Скопируйте следующий код в файл IrisModel.cs.
class IrisModel
    {
        private LearningModel _learning_model;
        private LearningModelSession _session;
        private String[] _labels = { "Iris-setosa", "Iris-versicolor", "Iris-virginica"};

Загрузка модели

Далее необходимо загрузить модель машинного обучения и создать сеанс, который будет выполнен с помощью только что определенных классов. Чтобы загрузить модель, воспользуйтесь несколькими статическими методами класса LearningModel. В нашем примере мы будем использовать класс LoadFromStorageFileAsync, который позволяет асинхронно загрузить модель ONNX из ISorageFile.

Примечание.

Дополнительные сведения о других способах загрузки модели см. в этой документации.

  1. Скопируйте следующий код в файл 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 см.
  1. Скопируйте следующий код в файл 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() в спрогнозированных выходных данных.

Модель возвращает три значения вероятности, каждое из которых представляет один конкретный тип Ирисов. Вам необходимо вернуть метку с наибольшей вероятностью.

  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 и управляющий код для тестирования модели с помощью уже созданных методов.

Создание графического пользовательского интерфейса приложения

  1. Чтобы создать код приложения графического пользовательского интерфейса для вашего приложения, дважды щелкните файл кода MainPage.xaml и откройте предопределенный шаблон для вашего графического пользовательского интерфейса.

  2. Скопируйте и вставьте приведенный ниже код в 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 включает основной метод для запуска приложения и несколько этапов выполнения модели и выходных данных:

  1. Вам потребуется создать объект класса IrisModel, созданного ранее в этом учебнике.
  2. Затем вызовите метод Evaluate(), созданный в предыдущей части модели. Этот метод будет применяться четыре раза, по одному разу для каждого входного параметра: длина чашелистика, ширина чашелистика, длина лепестка и ширина лепестка.

Приложение отобразит результат на основе алгоритма прогнозирования машинного обучения.

  1. Чтобы создать управляющий код приложения, дважды щелкните файл кода 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 мм приложение создало входные данные типа "Ирис разноцветный"!

Successful classification in your app

Итоги

Вы только что создали свое первое приложение для Windows Machine Learning — от этапа создания модели до этапа успешного выполнения.

Дополнительные ресурсы

Дополнительные сведения см. в следующих статьях: