Udostępnij przez


Samouczek: tworzenie uniwersalnej aplikacji systemu Windows Machine Learning (C#)

W tym samouczku zbudujemy prostą aplikację Universal Windows Platform, która korzysta z wytrenowanego modelu uczenia maszynowego do rozpoznawania cyfry rysowanej przez użytkownika. Ten samouczek koncentruje się głównie na tym, jak ładować i używać uczenia maszynowego z systemem Windows w aplikacji platformy UWP.

Poniższy film wideo przeprowadzi cię przez przykład, na podstawie którego jest oparty ten samouczek.


Jeśli wolisz po prostu przyjrzeć się kodowi ukończonego samouczka, możesz go znaleźć w repozytorium GitHub WinML. Jest również dostępny w języku C++/CX.

Wymagania wstępne

1. Otwieranie projektu w programie Visual Studio

Po pobraniu projektu z usługi GitHub uruchom program Visual Studio i otwórz plik MNIST_Demo.sln (powinien on znajdować się w <ścieżce do repozytorium>\Windows-Machine-Learning\Samples\MNIST\Tutorial\cs). Jeśli rozwiązanie jest wyświetlane jako niedostępne, musisz kliknąć prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybrać polecenie Załaduj ponownie projekt.

Udostępniliśmy szablon z zaimplementowanymi kontrolkami i zdarzeniami XAML, w tym:

  • Aby narysować cyfrę, użyj InkCanvas.
  • Przyciski do interpretowania cyfry i czyszczenia kanwy.
  • Funkcje pomocnicze do konwertowania wyników InkCanvas na VideoFrame.

W Eksploratorze rozwiązań projekt ma trzy główne pliki kodu:

  • MainPage.xaml — cały nasz kod XAML umożliwiający utworzenie interfejsu użytkownika dla elementów InkCanvas, przycisków i etykiet.
  • MainPage.xaml.cs — gdzie znajduje się nasz kod aplikacji.
  • Helper.cs — funkcje pomocnicze do przycinania i konwersji formatów obrazów.

Eksplorator rozwiązań programu Visual Studio z plikami projektu

2. Skompiluj i uruchom projekt

Na pasku narzędzi programu Visual Studio zmień platformę rozwiązania na x64 , aby uruchomić projekt na komputerze lokalnym, jeśli urządzenie jest 64-bitowe lub x86 , jeśli jest to 32-bitowe. Możesz sprawdzić w Ustawieniach systemu Windows: System > Informacje > Specyfikacje urządzenia > Typ systemu.

Aby uruchomić projekt, kliknij przycisk Rozpocznij debugowanie na pasku narzędzi lub naciśnij F5. Aplikacja powinna wyświetlić inkCanvas , w którym użytkownicy mogą napisać cyfrę, przycisk Rozpoznaj w celu zinterpretowania numeru, puste pole etykiety, w którym interpretowana cyfra będzie wyświetlana jako tekst, oraz przycisk Wyczyść cyfrę w celu wyczyszczenia elementu InkCanvas.

Zrzut ekranu aplikacji

Uwaga / Notatka

Jeśli projekt nie zostanie skompilowany, może być koniecznością zmienienie wersji docelowej dla wdrożenia projektu. Kliknij prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybierz polecenie Właściwości. Na karcie Aplikacja ustaw wersję docelową i minimalną wersję tak, aby odpowiadała systemowi operacyjnemu i zestawowi SDK.

Uwaga / Notatka

Jeśli zostanie wyświetlone ostrzeżenie, że aplikacja jest już zainstalowana, wybierz pozycję Tak , aby kontynuować wdrażanie. Może być konieczne zamknięcie programu Visual Studio i ponowne otwarcie go, jeśli nadal nie działa.

3. Pobieranie modelu

Następnie uzyskamy model uczenia maszynowego, który zostanie dodany do naszej aplikacji. W tym samouczku użyjemy wstępnie wytrenowanego modelu MNIST, który został wytrenowany przy użyciu zestawu narzędzi Microsoft Cognitive Toolkit (CNTK) i wyeksportowany do formatu ONNX.

Model MNIST został już uwzględniony w folderze Assets i musisz dodać go do aplikacji jako istniejący element. Możesz również pobrać wstępnie wytrenowany model z zoo modeli ONNX na GitHub.

4. Dodawanie modelu

Kliknij prawym przyciskiem myszy folder Assets w Eksploratorze rozwiązań, a następnie wybierz pozycję Dodaj>istniejący element. Wskaż selektor plików do lokalizacji modelu ONNX, a następnie kliknij przycisk Dodaj.

Projekt powinien teraz mieć dwa nowe pliki:

  • mnist.onnx — wytrenowany model.
  • mnist.cs — kod generowany przez uczenie maszynowe systemu Windows.

Eksplorator rozwiązań z nowymi plikami

Aby upewnić się, że model jest kompilowany podczas kompilowania aplikacji, kliknij prawym przyciskiem myszy plik mnist.onnx i wybierz polecenie Właściwości. W polu Akcja kompilacji wybierz pozycję Zawartość.

Teraz przyjrzyjmy się nowo wygenerowanej kodzie w pliku mnist.cs . Mamy trzy klasy:

  • mnistModel tworzy reprezentację modelu uczenia maszynowego, tworzy sesję na domyślnym urządzeniu systemowym, wiąże określone dane wejściowe i wyjściowe z modelem i ocenia model asynchronicznie.
  • mnistInput inicjuje typy danych wejściowych, których oczekuje model. W takim przypadku dane wejściowe oczekują wartości ImageFeatureValue.
  • mnistOutput inicjuje typy, których dane wyjściowe będą zwracane przez model. W takim przypadku dane wyjściowe będą listą o nazwie Plus214_Output_0 typu TensorFloat.

Teraz użyjemy tych klas, aby załadować, powiązać i ocenić model w naszym projekcie.

5. Ładowanie, wiązanie i ocenianie modelu

W przypadku aplikacji Windows ML wzorzec, który chcemy stosować, to: Ładuj > Wiąż > Oceniaj.

  1. Załaduj model uczenia maszynowego.
  2. Powiąż dane wejściowe i wyjściowe z modelem.
  3. Oceń model i wyświetl wyniki.

Użyjemy kodu interfejsu wygenerowanego w mnist.cs , aby załadować, powiązać i ocenić model w naszej aplikacji.

Najpierw w MainPage.xaml.cs stwórzmy instancję modelu, danych wejściowych i wyjściowych. Dodaj następujące zmienne składowe do klasy MainPage :

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

Następnie w narzędziu LoadModelAsync załadujemy model. Ta metoda powinna być wywoływana przed użyciem dowolnej z metod modelu (czyli na zdarzeniu Załadowane strony MainPage, w przesłonięciu OnNavigatedTo lub gdziekolwiek przed wywołaniem recognizeButton_Click). Klasa mnistModel reprezentuje model MNIST i tworzy sesję na domyślnym urządzeniu systemowym. Aby załadować model, wywołujemy metodę CreateFromStreamAsync , przekazując plik ONNX jako parametr.

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

Uwaga / Notatka

Jeśli otrzymasz czerwone podkreślenia pod IRandomAccessStreamReference, musisz uwzględnić jego przestrzeń nazwową. Umieść kursor na nim, naciśnij Ctrl + . i wybierz użycie Windows.Storage.Streams z menu rozwijanego.

Następnie chcemy powiązać nasze dane wejściowe i wyjściowe z modelem. Wygenerowany kod zawiera również klasy wrapper mnistInput i mnistOutput. Klasa mnistInput reprezentuje oczekiwane dane wejściowe modelu, a klasa mnistOutput reprezentuje oczekiwane dane wyjściowe modelu.

Aby zainicjować obiekt wejściowy modelu, wywołaj konstruktor klasy mnistInput , przekazując dane aplikacji i upewnij się, że dane wejściowe są zgodne z typem wejściowym oczekiwanym przez model. Klasa mnistInput oczekuje wartości ImageFeatureValue, dlatego używamy metody pomocniczej, aby uzyskać wartość ImageFeatureValue dla danych wejściowych.

Korzystając z naszych dołączonych funkcji pomocnika w helper.cs, skopiujemy zawartość inkCanvas, przekonwertujemy ją na typ ImageFeatureValue i powiążemy ją z naszym modelem.

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

W przypadku danych wyjściowych po prostu wywołujemy metodę EvaluateAsync z określonymi danymi wejściowymi. Po zainicjowaniu wejść, wywołaj metodę EvaluateAsync, aby ocenić wyniki modelu na podstawie danych wejściowych. Funkcja EvaluateAsync wiąże dane wejściowe i wyjściowe z obiektem modelu i ocenia model na danych wejściowych.

Ponieważ model zwraca tensor danych wyjściowych, najpierw chcemy przekonwertować go na przyjazny typ danych, a następnie przeanalizować zwróconą listę, aby określić, która cyfra ma najwyższe prawdopodobieństwo i wyświetlić ten typ.

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

Na koniec chcemy wyczyścić InkCanvas , aby umożliwić użytkownikom rysowanie innej liczby.

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

6. Uruchamianie aplikacji

Gdy skompilujemy i uruchomimy aplikację (naciśnij F5), będziemy mogli rozpoznać liczbę rysowaną na inkCanvas.

kompletna aplikacja

To wszystko — twoja pierwsza aplikacja uczenia maszynowego systemu Windows została utworzona! Aby uzyskać więcej przykładów, które pokazują, jak używać uczenia maszynowego z systemem Windows, zapoznaj się z naszym repozytorium Windows-Machine-Learning w witrynie GitHub.

Uwaga / Notatka

Skorzystaj z następujących zasobów, aby uzyskać pomoc dotyczącą uczenia maszynowego z systemem Windows:

  • Aby zadać lub odpowiedzieć na pytania techniczne dotyczące uczenia maszynowego z systemem Windows, użyj tagu windows-machine-learning w witrynie Stack Overflow.
  • Aby zgłosić usterkę, popełnij zgłoszenie na GitHubie .