Compartilhar via


Implante um modelo de análise de dados em um aplicativo do Windows com a API do Windows ML

Na parte anterior deste tutorial, você aprendeu a criar e exportar um modelo no formato ONNX. Agora, vamos mostrar como inserir o modelo exportado em um aplicativo do Windows e executá-lo localmente em um dispositivo chamando as APIs do Windows ML.

No final desta atividade, você terá um aplicativo de análise de dados.

Sobre o aplicativo de amostra

Nesta etapa do tutorial, você criará um aplicativo que analisa dados tabulares de Íris. Nesse aplicativo, é possível adicionar o arquivo Excel com as informações de entrada necessárias ou inserir manualmente os parâmetros de entrada: o comprimento e a largura em centímetros da sépala e da pétala da Íris. Esses recursos serão processados por um modelo ONNX de rede neural armazenado localmente, que você já criou e treinou na parte anterior. Com base na saída do modelo, o aplicativo exibirá a espécie correta de Íris.

Aqui, percorreremos esse processo com você.

Observação

Se você optar por usar o exemplo de código predefinido, poderá clonar o arquivo da solução. Clone o repositório, navegue até este exemplo e abra o arquivo Iris Data Analysis.csproj com o Visual Studio. Vá diretamente para a parte Iniciar o aplicativo desta página para vê-lo em uso.

A seguir, vamos descrever como criar o aplicativo e adicionar código do Windows ML a ele.

Criar um aplicativo de área de trabalho do Windows ML (C#)

Para criar um aplicativo do Windows ML funcional, você precisará fazer o seguinte:

  • Carregar um modelo de machine learning.
  • Associar as entradas e as saídas do modelo.
  • Avaliar o modelo e exibir os resultados significativos.

Também é preciso criar uma IU básica para proporcionar uma experiência melhor ao usuário.

Abrir um novo projeto no Visual Studio

  1. Vamos começar. Abra o Visual Studio e escolha Create a new project.

Create new Visual Studio project

  1. Na barra de pesquisa, escolha C# como linguagem, Windows como plataforma de destino e Dektop como tipo de projeto. Selecione a opção NUnit Test Project (.NET Core) como tipo de projeto e clique em next para abrir a janela de configuração do projeto.

Create new NUnit Test Project app

  1. Na janela de configuração, faça o seguinte:
  • Nomeie o projeto. O nome será Iris Data Analysis.
  • Escolha o local do projeto.
  • Se você está usando o VS2019, verifique se Create directory for solution está marcado.
  • Se estiver usando o VS2017, verifique se a opção Place solution and project in the same directory está desmarcada.

Pressione create para criar o projeto. A janela de versão de destino mínima pode aparecer. Verifique se a versão mínima está definida como Windows 10, versão 1809 (10.0; build 17763) ou posterior.

  1. Depois que o projeto for criado, navegue até a pasta do projeto, abra a pasta de ativos [….\DataClassifier\Assets] e copie o arquivo Network.onnx para esse local.

Explorar a solução do projeto

Vamos explorar sua solução de projeto.

O Visual Studio criou automaticamente vários arquivos cs-code dentro do Gerenciador de Soluções. O MainPage.xaml contém o código XAML para sua GUI e o MainPage.xaml.cs contém o código do aplicativo. Se você já criou um aplicativo UWP, esses arquivos devem ser muito familiares.

O arquivo Network.onnx foi adicionado à pasta de ativos, mas é preciso incluí-lo neste projeto.

  1. Clique com o botão direito do mouse na pasta "Assets" no Gerenciador de Soluções e selecione Add > Existing Item.
  2. Navegue até a pasta "Assets" em Iris Data Analysis [….\Iris Data Analysis \Assets], localize o Network.onnx model que você copiou e clique em Add.
  3. Para garantir que o modelo seja compilado com o seu aplicativo, clique com o botão direito do mouse no arquivo Network.onnx e selecione Properties. Defina o Build Action para Content.

Também será necessário criar um novo arquivo de classe cs-code para códigos extra de machine learning, que incluem classes e métodos que chamarão as APIs do Windows ML.

  1. Clique com o botão direito do mouse no nome da solução no Visual Studio e escolha add e new item. Na janela aberta, selecione Class e dê um nome. Aqui, usamos IrisModel.cs. Um novo arquivo de classe aparecerá no projeto.

Add a new class file to your VS project.

Criar código do Machine Learning

Nesta etapa, você criará todas as classes e métodos que chamarão as APIs do Windows Machine Learning. Assim, será possível carregar, associar e avaliar um modelo de machine learning ONNX no projeto.

  1. Clique duas vezes no arquivo IrisModel.cs.

  2. Substitua as instruções using pelo indicado a seguir para ter acesso a todas as APIs necessárias.

using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.AI.MachineLearning;
using Windows.Storage;

Inicializar classes de machine learning

Será necessário adicionar várias classes ao IrisModel.cs para ajudar você a interagir com as APIs do Windows Machine Learning.

Para ter acesso ao modelo de machine learning treinado, use a classe LearningModel. Essa classe faz parte do namespace Windows.AI.MachineLearning e representa um modelo de machine learning treinado. Uma vez instanciado, o LearningModel é o objeto inicial usado para interagir com as APIs do Windows ML.

Para avaliar o modelo de aprendizado, você terá que criar uma sessão de avaliação. Use a classe LearningModelSession para fazer isso. Essa classe é usada para avaliar modelos de machine learning e associa o modelo a um dispositivo que, por sua vez, executa e avalia o modelo. Ao criar uma sessão com essa API, você também pode selecionar um dispositivo para executar o modelo (o padrão é a CPU).

Além disso, será necessário especificar os rótulos da saída dos modelos de machine learning. Você pode conectar esses rótulos à saída prevista do modelo mais tarde.

Observação

Para saber mais sobre as classes LearningModel e LearningModelSession, confira as documentações das classes LearningModel e LearningModelSession.

  1. Copie o código a seguir para o arquivo IrisModel.cs.
class IrisModel
    {
        private LearningModel _learning_model;
        private LearningModelSession _session;
        private String[] _labels = { "Iris-setosa", "Iris-versicolor", "Iris-virginica"};

Carregar o modelo

Em seguida, é preciso carregar o modelo de machine learning e criar uma sessão, e isso é feito com as classes que você acabou de definir. Para carregar o modelo, você usará diversos métodos estáticos da classe LearningModel. Neste caso, LoadFromStorageFileAsync, que permite carregar um modelo ONNX de um ISorageFile de modo assíncrono.

Observação

Para descobrir outras maneiras de carregar o modelo, confira a documentação "Carregar um modelo".

  1. Copie o código a seguir para o arquivo 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);
}

Definir o tensor de entrada do modelo

Agora, defina a entrada correta com base nos requisitos do modelo. O modelo de rede criado na parte anterior tem quatro valores de entrada. Cada valor de entrada representa os tamanhos possíveis de quatro recursos de íris: comprimento da sépala em centímetros, largura da sépala em centímetros, comprimento da pétala em centímetros e largura da pétala em centímetros. Com base nessa entrada, o modelo retornará a espécie de íris que melhor se ajusta a esses parâmetros. Você precisará limitar o tamanho dos valores de entrada aos valores lógicos válidos – neste tutorial, vamos usar o seguinte:

  • Comprimento da sépala: de 1 cm a 100 cm
  • Largura da sépala: de 1 cm a 8 cm
  • Comprimento da pétala: de 0,5 cm a 10 cm
  • Largura da pétala: de 0,1 cm a 5 cm
  1. Copie o código a seguir para o arquivo 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;
        }
    }
}

As APIs do Windows ML aceitam valores de entrada das quatro classes descritivas compatíveis com modelos ONNX: tensores, sequências, mapas e imagens. Nesse caso, o modelo requer um objeto tensor flutuante de 32 bits em uma forma de float32[batch_size,4]. Como o tamanho do lote é 1, a forma do tensor de entrada será [1x4].

Para criar uma entrada de tensor, use a classe TensorFloat.

A classe TensorFloat faz parte do namespace Windows.AI.MachineLearning e é usada para definir um objeto tensor flutuante de 32 bits – um tensor de valores de ponto flutuante de 32 bits. Essa classe contém vários métodos úteis para criar um tensor. Neste caso, você usará o método CreateFromArray para criar uma entrada de tensor no tamanho exato exigido pelo modelo. Adicione essa chamada ao método de avaliação.

Associar e avaliar o modelo

Agora que você definiu o tensor de entrada do modelo e instanciou o modelo treinado e a sessão, é hora de criar um método para associar e avaliar o modelo de machine learning treinado.

Esse método é a parte principal de um aplicativo de machine learning, pois inclui a tensorização dos valores de entrada e a associação da entrada do modelo. Você usará esse modelo posteriormente no código do aplicativo para avaliar seu modelo.

Para associar entrada e saída, use a classe LearningModelBinding. Um modelo de machine learning tem recursos de entrada e saída, que transmitem informações para dentro e fora do modelo. Lembre-se de que os recursos necessários devem ser compatíveis com as APIs do Windows ML. A classe LearningModelBinding é aplicada em um LearningModelSession para associar valores aos recursos de entrada e saída nomeados.

A classe LearningModelBinding tem vários métodos predefinidos que você pode usar para associar valores a esses recursos nomeados. Aqui, você usará o método Bind para associar valores ao modelo.

Para avaliar o modelo e receber os resultados dele, chame os métodos de avaliação predefinidos de LearningModelSession, neste caso, o método Evaluate. Esse método oferece a funcionalidade de que você precisa, porque avalia o modelo de machine learning usando os valores de recursos fornecidos pela classe LearningModelBinding.

Observação

Para saber mais sobre outros métodos de avaliação para executar o modelo, verifique quais métodos podem ser implementados em LearningModelSession examinando a documentação da Classe LearningModelSession.

Extrair e exibir os resultados

O modelo retorna os valores previstos no formato de tensor como uma saída de tensor flutuante. Agora, você precisa extrair a saída do modelo e exibir os resultados corretos. Para fazer isso, converta o formato de tensor em um vetor executando a função GetAsVectorView() na saída com o predicado.

O modelo retorna três valores de probabilidade, e cada um representa uma espécie específica de íris. Você precisará retornar o rótulo com a maior probabilidade.

  1. Copie o código a seguir para o arquivo 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);
}

Você concluiu a parte de machine learning do código. Agora, pode integrar facilmente o modelo com um aplicativo do Windows. Na última parte deste tutorial, há uma GUI básica do Windows e um código de controle para testar o modelo usando os métodos que você já criou.

Criar a GUI do aplicativo

  1. Para criar um código de aplicativo de GUI para o aplicativo, clique duas vezes no arquivo de código MainPage.xaml e abra um modelo predefinido para a GUI.

  2. Copie e cole o código abaixo em MainPage.xaml, abaixo da linha “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>

Criar o controle do aplicativo

O código de controle do aplicativo, MainPage.xaml.cs, inclui o método main para executar o aplicativo e várias etapas para executar o modelo e executar a saída:

  1. Você criará uma instância de um novo objeto da classe IrisModel criada anteriormente neste tutorial.
  2. Você chamará o método Evaluate() criado na parte anterior no modelo. Esse método será aplicado quatro vezes, uma em cada um dos parâmetros de entrada: comprimento da sépala, largura da sépala, comprimento da pétala e largura da pétala.

O aplicativo exibirá o resultado com base no algoritmo de previsão de machine learning.

  1. Para criar um código de controle de aplicativo, clique duas vezes no arquivo de código MainPage.xaml.cs e adicione o código a seguir.
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();
            }
        }
    }
}

Iniciar o aplicativo

Agora está tudo pronto para iniciar o aplicativo e ver os resultados.

Habilite o modo de desenvolvedor e teste seu aplicativo com o Visual Studio. Verifique se os menus suspensos na barra de ferramentas superior estão definidos como Debug. Altere a Plataforma de Solução para x64 para executar o projeto no computador local se seu dispositivo for de 64 bits ou x86 se for de 32 bits.

A GUI do aplicativo inclui quatro controles deslizantes para alterar a entrada dos parâmetros necessários. Qualquer alteração na entrada gera uma nova saída com base no algoritmo de previsão. A saída é exibida abaixo dos controles deslizantes de entrada.

Veja que, dada a entrada de comprimento da sépala = 40 mm, largura da sépala = 50, comprimento da pétala = 75 e largura da pétala = 15, a entrada gerada pelo aplicativo é a espécie {i>Iris versicolor

Successful classification in your app

Resumo

Você acabou de criar seu primeiro aplicativo do Windows Machine Learning, da criação do modelo até a execução bem-sucedida.

Recursos adicionais

Para saber mais sobre os tópicos mencionados neste tutorial, visite os seguintes recursos: