Compartir a través de


Tutorial: Creación de una aplicación para UWP de Windows Machine Learning (C#)

En este tutorial, crearemos una aplicación sencilla para la Plataforma universal de Windows que usa un modelo de aprendizaje automático entrenado para reconocer un dígito numérico dibujado por el usuario. Este tutorial se centra principalmente en cómo cargar y usar Windows ML en tu aplicación para UWP.

En el vídeo siguiente se explica el ejemplo en el que se basa este tutorial.


Si prefiere ver simplemente el código del tutorial terminado, puede encontrarlo en el repositorio de GitHub de WinML. También está disponible en C++/CX.

Prerrequisitos

  • Windows 10 (versión 1809 o posterior)
  • SDK de Windows 10 (compilación 17763 o posterior)
  • Visual Studio 2019 (o Visual Studio 2017, versión 15.7.4 o posterior)
  • Extensión del generador de código de Windows Machine Learning para Visual Studio 2019 o 2017
  • Algunos conocimientos básicos de UWP y C#

1. Abra el proyecto en Visual Studio

Una vez descargado el proyecto desde GitHub, inicie Visual Studio y abra el archivo MNIST_Demo.sln (debe encontrarse en <Ruta de acceso al repositorio>\Windows-Machine-Learning\Samples\MNIST\Tutorial\cs). Si la solución se muestra como no disponible, deberá hacer clic con el botón derecho en el proyecto en el Explorador de soluciones y seleccionar Volver a cargar proyecto.

Hemos proporcionado una plantilla con eventos y controles XAML implementados, entre los que se incluyen:

  • Un InkCanvas para dibujar el dígito.
  • Botones para interpretar el dígito y borrar el lienzo.
  • Rutinas auxiliares para convertir la salida InkCanvas en un VideoFrame.

Dentro del Explorador de soluciones, el proyecto tiene tres archivos de código principales:

  • MainPage.xaml : todo nuestro código XAML para crear la interfaz de usuario para inkCanvas, botones y etiquetas.
  • MainPage.xaml.cs : donde reside nuestro código de aplicación.
  • Helper.cs : rutinas auxiliares para recortar y convertir formatos de imagen.

Explorador de soluciones de Visual Studio con archivos de proyecto

2. Compilar y ejecutar el proyecto

En la barra de herramientas de Visual Studio, cambie la plataforma de soluciones a x64 para ejecutar el proyecto en el equipo local si el dispositivo es de 64 bits o x86 si es de 32 bits. (Puedes consultar en la aplicación Configuración de Windows: System > About > Device specifications > Tipo de sistema.)

Para ejecutar el proyecto, haga clic en el botón Iniciar depuración de la barra de herramientas o presione F5. La aplicación debe mostrar un control InkCanvas donde los usuarios podrán escribir un dígito, un botón Reconocer para interpretar el número, un campo de etiqueta vacío donde se mostrará el dígito interpretado como texto y un botón Borrar dígito para borrar el control InkCanvas.

Captura de pantalla de la aplicación

Nota:

Si el proyecto no se compilará, es posible que tenga que cambiar la versión de destino de implementación del proyecto. Haga clic con el botón derecho en el proyecto en el Explorador de soluciones y seleccione Propiedades. En la pestaña Aplicación , establezca la versión de destino y la versión mínima para que coincidan con el SISTEMA operativo y el SDK.

Nota:

Si recibe una advertencia de que la aplicación ya está instalada, seleccione para continuar con la implementación. Es posible que tenga que cerrar Visual Studio y volver a abrirlo si aún no funciona.

3. Descargar un modelo

A continuación, vamos a obtener un modelo de aprendizaje automático para agregar a nuestra aplicación. En este tutorial, usaremos un modelo MNIST entrenado previamente que se entrenó con Microsoft Cognitive Toolkit (CNTK) y exportaremos al formato ONNX.

El modelo MNIST ya se ha incluido en la carpeta Assets y tendrá que agregarlo a la aplicación como un elemento existente. También puede descargar el modelo entrenado previamente desde ONNX Model Zoo en GitHub.

4. Agregar el modelo

Haga clic con el botón derecho en la carpeta Activos en el Explorador de soluciones y seleccione Agregar>elemento existente. Apunte el selector de archivos a la ubicación del modelo ONNX y haga clic en Agregar.

El proyecto debería tener ahora dos archivos nuevos:

  • mnist.onnx: el modelo entrenado.
  • mnist.cs : código generado por Windows ML.

Explorador de soluciones con archivos nuevos

Para asegurarse de que el modelo se compila al compilar la aplicación, haga clic con el botón derecho en el archivo mnist.onnx y seleccione Propiedades. En Acción de compilación, seleccione Contenido.

Ahora, echemos un vistazo al código recién generado en el archivo mnist.cs . Tenemos tres clases:

  • mnistModel crea la representación del modelo de aprendizaje automático, crea una sesión en el dispositivo predeterminado del sistema, enlaza las entradas y salidas específicas al modelo y evalúa el modelo de forma asincrónica.
  • mnistInput inicializa los tipos de entrada que espera el modelo. En este caso, la entrada espera ImageFeatureValue.
  • mnistOutput inicializa los tipos que generará el modelo. En este caso, la salida será una lista denominada Plus214_Output_0 de tipo TensorFloat.

Ahora usaremos estas clases para cargar, enlazar y evaluar el modelo en nuestro proyecto.

5. Cargar, enlazar y evaluar el modelo

Para las aplicaciones de Windows ML, el patrón que queremos seguir es: Load > Bind > Evaluate.

  1. Cargue el modelo de Machine Learning.
  2. Enlazar entradas y salidas al modelo.
  3. Evalúe el modelo y vea los resultados.

Usaremos el código de interfaz generado en mnist.cs para cargar, enlazar y evaluar el modelo en nuestra aplicación.

En primer lugar, en MainPage.xaml.cs, vamos a crear instancias del modelo, las entradas y las salidas. Agregue las siguientes variables de miembro a la clase MainPage :

private mnistModel ModelGen;
private mnistInput ModelInput = new mnistInput();
private mnistOutput ModelOutput;

A continuación, en LoadModelAsync, cargaremos el modelo. Se debe llamar a este método antes de usar cualquiera de los métodos del modelo (es decir, en el evento Loaded de MainPage, en una sobrescritura OnNavigatedTo o en cualquier momento antes de que se llame a recognizeButton_Click). La clase mnistModel representa el modelo MNIST y crea la sesión en el dispositivo predeterminado del sistema. Para cargar el modelo, llamamos al método CreateFromStreamAsync , pasando el archivo ONNX como parámetro.

private async Task LoadModelAsync()
{
    // Load a machine learning model
    StorageFile modelFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Assets/mnist.onnx"));
    ModelGen = await mnistModel.CreateFromStreamAsync(modelFile as IRandomAccessStreamReference);
}

Nota:

Si aparece un subrayado rojo en IRandomAccessStreamReference, debes incluir su espacio de nombres. Coloque el cursor sobre él, presione Ctrl + . y seleccione usar Windows.Storage.Streams en el menú desplegable.

A continuación, queremos enlazar nuestras entradas y salidas al modelo. El código generado también incluye clases contenedoras mnistInput y mnistOutput . La clase mnistInput representa las entradas esperadas del modelo y la clase mnistOutput representa las salidas esperadas del modelo.

Para inicializar el objeto de entrada del modelo, llame al constructor de clase mnistInput , pase los datos de la aplicación y asegúrese de que los datos de entrada coincidan con el tipo de entrada que espera el modelo. La clase mnistInput espera un imageFeatureValue, por lo que usamos un método auxiliar para obtener un imageFeatureValue para la entrada.

Con nuestras funciones auxiliares incluidas en helper.cs, copiaremos el contenido de InkCanvas, lo convertiremos en el tipo ImageFeatureValue y lo enlazaremos a nuestro modelo.

private async void recognizeButton_Click(object sender, RoutedEventArgs e)
{
    // Bind model input with contents from InkCanvas
    VideoFrame vf = await helper.GetHandWrittenImage(inkGrid);
    ModelInput.Input3 = ImageFeatureValue.CreateFromVideoFrame(vf);
}

Para la salida, simplemente llamamos a EvaluateAsync con la entrada especificada. Una vez inicializadas las entradas, llame al método EvaluateAsync del modelo para evaluar el modelo en los datos de entrada. EvaluateAsync enlaza las entradas y salidas al objeto de modelo y evalúa el modelo en las entradas.

Dado que el modelo devuelve un tensor de salida, primero queremos convertirlo en un tipo de datos descriptivo y, a continuación, analizar la lista devuelta para determinar qué dígito tenía la mayor probabilidad y mostrarlo.

private async void recognizeButton_Click(object sender, RoutedEventArgs e)
{
    // Bind model input with contents from InkCanvas
    VideoFrame vf = await helper.GetHandWrittenImage(inkGrid);
    ModelInput.Input3 = ImageFeatureValue.CreateFromVideoFrame(vf);

    // Evaluate the model
    ModelOutput = await ModelGen.EvaluateAsync(ModelInput);

    // Convert output to datatype
    IReadOnlyList<float> vectorImage = ModelOutput.Plus214_Output_0.GetAsVectorView();
    IList<float> imageList = vectorImage.ToList();

    // Query to check for highest probability digit
    var maxIndex = imageList.IndexOf(imageList.Max());

    // Display the results
    numberLabel.Text = maxIndex.ToString();
}

Por último, queremos borrar InkCanvas para permitir que los usuarios dibujen otro número.

private void clearButton_Click(object sender, RoutedEventArgs e)
{
    inkCanvas.InkPresenter.StrokeContainer.Clear();
    numberLabel.Text = "";
}

6. Iniciar la aplicación

Una vez que compilamos e iniciamos la aplicación (presione F5), podremos reconocer un número dibujado en InkCanvas.

aplicación completa

Es decir, ha realizado su primera aplicación de Windows ML. Para obtener más ejemplos que muestran cómo usar Windows ML, consulte nuestro repositorio de Windows-Machine-Learning en GitHub.

Nota:

Use los siguientes recursos para obtener ayuda con Windows ML:

  • Para formular o responder a preguntas técnicas sobre Windows Machine Learning, utilice la etiqueta windows-machine-learning en Stack Overflow.
  • Para notificar un error, registre un problema en GitHub.