Dela via


Självstudie: Skapa ett Windows Machine Learning UWP-program (C#)

I den här självstudien ska vi skapa ett enkelt Universal Windows Platform-program som använder en tränad maskininlärningsmodell för att identifiera en numerisk siffra som ritats av användaren. Den här handledningen fokuserar främst på hur du läser in och använder Windows ML i din UWP-applikation.

Följande video går igenom exemplet som denna handledning baseras på.


Om du föredrar att bara titta på koden för den färdiga självstudien kan du hitta den på WinML GitHub-lagringsplatsen. Den finns också i C++/CX.

Förutsättningar

  • Windows 10 (version 1809 eller senare)
  • Windows 10 SDK (build 17763 eller senare)
  • Visual Studio 2019 (eller Visual Studio 2017, version 15.7.4 eller senare)
  • Windows Machine Learning Code Generator-tillägg för Visual Studio 2019 eller 2017
  • Några grundläggande UWP- och C#-kunskaper

1. Öppna projektet i Visual Studio

När du har laddat ned projektet från GitHub startar du Visual Studio och öppnar filen MNIST_Demo.sln (den bör finnas på <Sökväg till lagringsplats>\Windows-Machine-Learning\Samples\MNIST\Tutorial\cs). Om lösningen visas som otillgänglig måste du högerklicka på projektet i Solution Explorer och välja Läs in projektet igen.

Vi har tillhandahållit en mall med implementerade XAML-kontroller och händelser, inklusive:

  • En InkCanvas för att rita siffran.
  • Knappar för att tolka siffran och rensa arbetsytan.
  • Hjälprutiner för att konvertera InkCanvas-utdata till en VideoFrame.

I Solution Explorer har projektet tre huvudkodfiler:

  • MainPage.xaml – All vår XAML-kod för att skapa användargränssnittet för InkCanvas, knappar och etiketter.
  • MainPage.xaml.cs – var vår programkod finns.
  • Helper.cs – Hjälprutiner för att beskära och konvertera bildformat.

Visual Studio Solution Explorer med projektfiler

2. Skapa och köra projektet

I Visual Studio-verktygsfältet ändrar du Solution Platform till x64 för att köra projektet på den lokala datorn om enheten är 64-bitars eller x86 om den är 32-bitars. (Du kan kontrollera i Windows-inställningar: System > Om > Enhetsspecifikationer > Systemtyp.)

Om du vill köra projektet klickar du på knappen Starta felsökning i verktygsfältet eller trycker på F5. Programmet ska visa en InkCanvas där användare kan skriva en siffra, en identifiera-knapp för att tolka talet, ett tomt etikettfält där den tolkade siffran visas som text och en clear digit-knapp för att rensa InkCanvas.

Skärmbild av programmet

Anmärkning

Om projektet inte skapas kan du behöva ändra projektets distributionsmålversion. Högerklicka på projektet i Solution Explorer och välj Egenskaper. På fliken Program anger du Målversion och Min-version så att de matchar ditt operativsystem och SDK.

Anmärkning

Om du får en varning om att programmet redan är installerat väljer du Bara Ja för att fortsätta med distributionen. Du kan behöva stänga Visual Studio och öppna igen om det fortfarande inte fungerar.

3. Ladda ned en modell

Nu ska vi skaffa en maskininlärningsmodell att lägga till i vårt program. I den här självstudien använder vi en förtränad MNIST-modell som har tränats med Microsoft Cognitive Toolkit (CNTK) och exporterats till ONNX-format.

MNIST-modellen har redan inkluderats i mappen Tillgångar och du måste lägga till den i ditt program som ett befintligt objekt. Du kan också ladda ned den förtränade modellen från ONNX Model Zoo på GitHub.

4. Lägg till modellen

Högerklicka på mappen Tillgångar i Solution Explorer och välj Lägg till>befintligt objekt. Peka filväljaren på platsen för din ONNX-modell och klicka på Lägg till.

Projektet bör nu ha två nya filer:

  • mnist.onnx – Din tränade modell.
  • mnist.cs – Den Windows ML-genererade koden.

Solution Explorer med nya filer

För att se till att modellen byggs när vi kompilerar vårt program högerklickar du på filen mnist.onnx och väljer Egenskaper. För Skapa åtgärd väljer du Innehåll.

Nu ska vi ta en titt på den nyligen genererade koden i filen mnist.cs . Vi har tre klasser:

  • mnistModel skapar maskininlärningsmodellens representation, skapar en session på systemets standardenhet, binder specifika indata och utdata till modellen och utvärderar modellen asynkront.
  • mnistInput initierar de indatatyper som modellen förväntar sig. I det här fallet förväntar sig indata en ImageFeatureValue.
  • mnistOutput initierar de typer som modellen ska mata ut. I det här fallet är utdata en lista med namnet Plus214_Output_0 av typen TensorFloat.

Nu ska vi använda dessa klasser för att läsa in, binda och utvärdera modellen i vårt projekt.

5. Läs in, binda och utvärdera modellen

För Windows ML-program är mönstret vi vill följa: Läs in > binda > utvärdera.

  1. Läs in maskininlärningsmodellen.
  2. Binda indata och utdata till modellen.
  3. Utvärdera modellen och se resultat.

Vi använder den gränssnittskod som genereras i mnist.cs för att läsa in, binda och utvärdera modellen i vårt program.

Först i MainPage.xaml.cs ska vi instansiera modellen, indata och utdata. Lägg till följande medlemsvariabler i klassen MainPage :

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

Sedan läser vi in modellen i LoadModelAsync. Den här metoden bör anropas innan vi använder någon av modellens metoder (dvs. vid MainPagesinlästa händelse, vid en OnNavigatedTo-åsidosättning eller någonstans innan recognizeButton_Click anropas). Klassen mnistModel representerar MNIST-modellen och skapar sessionen på systemets standardenhet. För att läsa in modellen anropar vi metoden CreateFromStreamAsync och skickar in ONNX-filen som parameter.

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

Anmärkning

Om du får röda understrykningar under IRandomAccessStreamReference måste du inkludera dess namnområde. Placera markören över den, tryck Ctrl + . och välj använda Windows.Storage.Streams från rullgardinsmenyn.

Sedan vill vi binda våra indata och utdata till modellen. Den genererade koden innehåller även omslutningsklasser för mnistInput och mnistOutput . Klassen mnistInput representerar modellens förväntade indata och klassen mnistOutput representerar modellens förväntade utdata.

Om du vill initiera modellens indataobjekt anropar du klasskonstruktorn mnistInput , skickar in dina programdata och kontrollerar att dina indata matchar den indatatyp som din modell förväntar sig. Klassen mnistInput förväntar sig en ImageFeatureValue, så vi använder en hjälpmetod för att hämta en ImageFeatureValue för indata.

Med hjälp av våra inkluderade hjälpfunktioner i helper.cs kopierar vi innehållet i InkCanvas, konverterar det till typen ImageFeatureValue och binder det till vår 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);
}

För utdata anropar vi bara EvaluateAsync med angivna indata. När dina indata har initierats anropar du modellens EvaluateAsync-metod för att utvärdera din modell på indata. EvaluateAsync binder dina indata och utdata till modellobjektet och utvärderar modellen på indata.

Eftersom modellen returnerar en utdatatensor vill vi först konvertera den till en vänlig datatyp och sedan tolka den returnerade listan för att avgöra vilken siffra som hade högst sannolikhet och visa den.

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

Slutligen vill vi rensa InkCanvas så att användarna kan rita ett annat nummer.

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

6. Starta programmet

När vi har skapat och lanserat programmet (tryck på F5) kan vi identifiera ett tal som ritats på InkCanvas.

slutför programmet

Nu är det klart – du har gjort ditt första Windows ML-program! Fler exempel som visar hur du använder Windows ML finns i vår Windows-Machine-Learning-lagringsplats på GitHub.

Anmärkning

Använd följande resurser för hjälp med Windows ML:

  • Om du vill ställa eller besvara tekniska frågor om Windows ML använder du taggen windows-machine-learningStack Overflow-.
  • Om du vill rapportera en bugg, skicka in en felrapport på vår GitHub-sida .