Tutorial: Erstellen einer UWP-Anwendung für Windows Machine Learning (C#)

In diesem Tutorial erstellen wir eine einfache UWP-Anwendung (Universelle Windows-Plattform), die ein trainiertes Machine Learning-Modell verwendet, um eine Ziffer zu erkennen, die vom Benutzer gezeichnet wurde. Dieses Tutorial ist vorrangig auf das Laden und Verwenden von Windows ML in Ihrer UWP-Anwendung ausgerichtet.

Das folgende Video führt Sie schrittweise durch das Beispiel, auf dem dieses Tutorial basiert.


Wenn Sie sich lieber den Code des fertigen Tutorials ansehen möchten, finden Sie ihn im WinML-GitHub-Repository. Er ist auch in C++/CX- verfügbar.

Voraussetzungen

  • Windows 10 (Version 1809 oder höher)
  • Windows 10 SDK (Build 17763 oder höher)
  • Visual Studio 2019 (oder Visual Studio 2017, Version 15.7.4 oder höher)
  • Windows Machine Learning-Codegeneratorerweiterung für Visual Studio 2019 oder 2017
  • Einige grundlegende UWP- und C#-Kenntnisse

1. Öffnen des Projekts in Visual Studio

Nachdem Sie das Projekt von GitHub heruntergeladen haben, starten Sie Visual Studio und öffnen die Datei MNIST_Demo.sln (sie sollte sich unter <Pfad_zum_Repository>\Windows-Machine-Learning\Samples\MNIST\Tutorial\cs befinden). Wenn die Projektmappe als nicht verfügbar angezeigt wird, müssen Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt klicken und dann Projekt erneut laden auswählen.

Wir haben eine Vorlage mit implementierten XAML-Steuerelementen und Ereignissen bereitgestellt, die Folgendes beinhaltet:

  • Ein InkCanvas zum Zeichnen der Ziffer.
  • Schaltflächen zum Interpretieren der Ziffer und zum Löschen des Zeichenbereichs.
  • Hilfsprogrammroutinen zum Konvertieren der InkCanvas-Ausgabe in einen VideoFrame.

Im Projektmappen-Explorer enthält das Projekt drei Hauptcodedateien:

  • MainPage.xaml: Unser gesamter XAML-Code zum Erstellen der Benutzeroberfläche für InkCanvas, Schaltflächen und Bezeichnungen
  • MainPage.xaml.cs: Informationen zum Speicherort des Anwendungscodes.
  • Helper.cs: Hilfsroutinen zum Zuschneiden und Konvertieren von Bildformaten.

Visual Studio solution explorer with project files

2. Erstellen und Ausführen des Projekts

Ändern Sie in der Visual Studio-Symbolleiste die Projektmappen-Plattform in x64, um das Projekt auf dem lokalen Computer auszuführen, wenn es sich um ein 64-Bit-Gerät handelt, oder in x86 für einen 32-Bit-Computer. (Sie können dies in der Windows-Einstellungen-App überprüfen: System > Info > Gerätespezifikationen > Systemtyp.)

Klicken Sie zum Ausführen des Projekts auf der Symbolleiste auf die Schaltfläche Debuggen starten, oder drücken Sie F5. Die Anwendung sollte ein InkCanvas-Steuerelement, in das Benutzer eine Ziffer schreiben können, die Schaltfläche Recognize (Erkennen) zum Interpretieren der Zahl, ein leeres Bezeichnungsfeld, in dem die übersetzten Ziffer als Text angezeigt wird, und die Schaltfläche Clear Digit (Ziffer löschen) zum Löschen des InkCanvas-Steuerelements anzeigen.

Application screenshot

Hinweis

Wenn das Projekt nicht erstellt wird, müssen Sie möglicherweise die Version des Bereitstellungsziels des Projekts ändern. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie dann Eigenschaften aus. Legen Sie auf der Registerkarte Anwendung die Zielversion und die Mindestversion entsprechend dem Betriebssystem und SDK fest.

Hinweis

Wenn Sie eine Warnung erhalten, dass die Anwendung bereits installiert ist, wählen Sie einfach Ja aus, um die Bereitstellung fortzusetzen. Möglicherweise müssen Sie Visual Studio schließen und dann erneut öffnen, wenn es immer noch nicht funktioniert.

3. Herunterladen eines Modells

Als Nächstes rufen wir ein Machine Learning-Modell ab, um es unserer Anwendung hinzuzufügen. In diesem Tutorial verwenden wir ein bereits trainiertes MNIST-Modell, das mit dem Microsoft Cognitive Toolkit (CNTK) trainiert und in das ONNX Format exportiert wurde.

Das MNIST-Modell wurde dem Ordner Assets bereits hinzugefügt, und Sie müssen es Ihrer Anwendung als vorhandenes Element hinzufügen. Sie können das bereits trainierte Modell auch aus ONNX Model Zoo auf GitHub herunterladen.

4. Hinzufügen des Modells

Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Ordner Assets, und wählen Sie Hinzufügen>Vorhandenes Element aus. Verweisen Sie die Dateiauswahl auf den Speicherort des ONNX-Modells, und klicken Sie dann auf Hinzufügen.

Das Projekt sollte nun zwei neue Dateien aufweisen:

  • mnist.onnx: Ihr trainiertes Modell.
  • mnist.cs: Der von Windows ML generierte Code.

Solution explorer with new files

Um sicherzustellen, dass das Modell beim Kompilieren der Anwendung erstellt wird, klicken Sie mit der rechten Maustaste auf die Datei mnist.onnx, und wählen Sie dann Eigenschaften aus. Wählen Sie als Buildaktion die Option Inhalt aus.

Betrachten wir nun den neu generierten Code in der Datei mnist.cs. Es gibt drei Klassen:

  • mnistModel erstellt die Machine Learning-Modelldarstellung sowie eine Sitzung auf dem Systemstandardgerät, bindet die spezifischen Eingaben und Ausgaben an das Modell und wertet das Modell dann asynchron aus.
  • mnistInput initialisiert die Eingabetypen, die das Modell erwartet. In diesem Fall erwartet die Eingabe ImageFeatureValue.
  • mnistOutput initialisiert die Typen, die das Modell ausgibt. In diesem Fall ist die Ausgabe eine Liste mit dem Namen Plus214_Output_0 vom Typ TensorFloat.

Wir verwenden diese Klassen jetzt zum Laden, Binden und Auswerten des Modells in unserem Projekt.

5. Laden, Binden und Auswerten des Modells

Für Windows ML-Anwendungen folgen wir diesem Muster: Laden > Binden > Auswerten.

  1. Laden des Machine Learning-Modells.
  2. Binden der Ein- und Ausgaben an das Modell.
  3. Auswerten des Modells und Anzeigen der Ergebnisse.

Wir verwenden den Benutzeroberflächencode, der in mnist.cs erstellt wurde, um das Modell in unserer Anwendung zu laden, zu binden und auszuwerten.

Lassen Sie uns zunächst das Modell sowie Ein- und Ausgaben in MainPage.xaml.cs instanziieren. Fügen Sie der MainPage-Klasse die folgenden Membervariablen hinzu:

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

Anschließend laden wir das Modell in LoadModelAsync. Diese Methode sollte aufgerufen werden, bevor wir eine der Methoden des Modells verwenden (d. h. bei einem Loaded-Ereignis von MainPage, bei einer OnNavigatedTo-Außerkraftsetzung oder vor einem Aufruf von recognnizeButton_Click). Die mnistModel-Klasse stellt das MNIST-Modell dar und erstellt die Sitzung auf dem Systemstandardgerät. Um das Modell zu laden, wird die Methode CreateFromStreamAsync aufgerufen. Dabei wird die ONNX-Datei als Parameter übergeben.

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);
}

Hinweis

Wenn unter IRandomAccessStreamReference rote Unterstreichungen angezeigt werden, müssen Sie den zugehörigen Namespace einschließen. Platzieren Sie den Cursor darüber, drücken Sie STRG+., und wählen Sie dann im Dropdownmenü using Windows.Storage.Streams aus.

Als Nächstes möchten wir unsere Ein- und Ausgaben an das Modell binden. Der generierte Code enthält auch die Wrapperklassen mnistInput und mnistOutput. Die Klasse mnistInput stellt die erwarteten Eingaben und die Klasse mnistOutput die erwarteten Ausgaben des Modells dar.

Rufen Sie zum Initialisieren des Eingabeobjekts des Modells den mnistInput-Klassenkonstruktor auf, und übergeben Sie Ihre Anwendungsdaten. Stellen Sie dabei sicher, dass Ihre Eingabedaten dem Eingabetyp entsprechen, den Ihr Modell erwartet. Die mnistInput--Klasse erwartet einen ImageFeatureValue. Daher verwenden wir eine Hilfsmethode, um einen ImageFeatureValue für die Eingabe abzurufen.

Mit den in helper.cs enthaltenen Hilfsfunktionen kopieren wir den Inhalt von InkCanvas, konvertieren ihn in den Typ ImageFeatureValue und binden ihn an unser Modell.

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);
}

Zur Ausgabe rufen wir einfach EvaluateAsync mit der angegebenen Eingabe auf. Nachdem Ihre Eingaben initialisiert wurden, rufen Sie die EvaluateAsync-Methode des Modells auf, um Ihr Modell anhand der Eingabedaten auszuwerten. EvaluateAsync bindet Ihre Ein- und Ausgaben an das Modellobjekt und wertet das Modell anhand der Eingaben aus.

Da das Modell einen Ausgangstensor zurückgibt, wollen wir ihn zunächst in einen benutzerfreundlichen Datentyp konvertieren und dann die zurückgegebene Liste analysieren, um zu bestimmen, welche Ziffer die höchste Wahrscheinlichkeit hatte, und diese anzeigen.

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();
}

Schließlich müssen wir InkCanvas löschen, damit Benutzer eine andere Ziffer zeichnen können.

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

6. Starten der Anwendung

Sobald wir die Anwendung erstellt und gestartet haben (drücken Sie F5), können wir eine auf InkCanvas gezeichnete Ziffer erkennen.

complete application

Das war's – Sie haben Ihre erste Windows ML-Anwendung erstellt! Weitere Beispiele, die die Verwendung von Windows ML veranschaulichen, finden Sie in unserem Windows Machine Learning-Repository auf GitHub.

Hinweis

Verwende die folgenden Ressourcen, wenn du Hilfe mit Windows ML benötigst:

  • Wenn du technische Fragen zu Windows ML stellen oder beantworten möchtest, verwende das Tag windows-machine-learning auf Stack Overflow.
  • Wenn du einen Fehler melden möchtest, erstelle eine Anfrage auf GitHub.