Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Windows ML-API's kunnen worden gebruikt om eenvoudig te communiceren met machine learning-modellen in C++-bureaubladtoepassingen (Win32). Met behulp van de drie stappen van laden, koppelen en evalueren kan uw applicatie profiteren van de kracht van machine learning.
We maken een enigszins vereenvoudigde versie van het SqueezeNet Object Detection-voorbeeld, dat beschikbaar is op GitHub. U kunt het volledige voorbeeld downloaden als u wilt zien hoe het zal zijn wanneer u klaar bent.
We gebruiken C++/WinRT om toegang te krijgen tot de WinML-API's. Zie C++/WinRT voor meer informatie.
In deze handleiding leer je hoe je:
- Een machine learning-model laden
- Een afbeelding laden als een VideoFrame
- De invoer en uitvoer van het model binden
- Het model evalueren en zinvolle resultaten afdrukken
Vereiste voorwaarden
- Visual Studio 2019 (of Visual Studio 2017, versie 15.7.4 of hoger)
- Windows 10, versie 1809 of hoger
- Windows SDK, build 17763 of hoger
- Visual Studio-extensie voor C++/WinRT
- Selecteer in Visual Studio Hulpmiddelen > Extensies en Updates.
- Selecteer Online in het linkerdeelvenster en zoek naar WinRT met behulp van het zoekvak aan de rechterkant.
- Selecteer C++/WinRT, klik op Downloaden en sluit Visual Studio.
- Volg de installatie-instructies en open Visual Studio opnieuw.
- Windows-Machine-Learning Github-opslagplaats (u kunt deze downloaden als een ZIP-bestand of klonen naar uw computer)
Het project maken
Eerst maken we het project in Visual Studio:
- Selecteer Bestand > Nieuw > Project om het venster Nieuw project te openen.
- Selecteer in het linkerdeelvenster Geïnstalleerde > Visual C++ > Windows Desktop en selecteer in het midden Windows Console Application (C++/WinRT).
- Geef uw project een naam en locatie en klik vervolgens op OK.
- Stel in het venster Nieuw Universeel Windows-platformproject het doel en de minimale versies in op build 17763 of hoger en klik op OK.
- Zorg ervoor dat de vervolgkeuzelijsten in de bovenste werkbalk zijn ingesteld op Foutopsporing en x64 of x86 , afhankelijk van de architectuur van uw computer.
- Druk op Ctrl+F5 om het programma uit te voeren zonder foutopsporing. Er moet een terminal worden geopend met een beetje tekst 'Hallo wereld'. Druk op een willekeurige toets om deze te sluiten.
Het model laden
Vervolgens laden we het ONNX-model in ons programma met behulp van LearningModel.LoadFromFilePath:
Voeg in pch.h (in de map Header Files ) de volgende
includeinstructies toe (deze geven ons toegang tot alle API's die we nodig hebben):#include <winrt/Windows.AI.MachineLearning.h> #include <winrt/Windows.Foundation.Collections.h> #include <winrt/Windows.Graphics.Imaging.h> #include <winrt/Windows.Media.h> #include <winrt/Windows.Storage.h> #include <string> #include <fstream> #include <Windows.h>Voeg in main.cpp (in de map Bronbestanden ) de volgende
usinginstructies toe:using namespace Windows::AI::MachineLearning; using namespace Windows::Foundation::Collections; using namespace Windows::Graphics::Imaging; using namespace Windows::Media; using namespace Windows::Storage; using namespace std;Voeg de volgende variabeledeclaraties toe na de
usinginstructies:// Global variables hstring modelPath; string deviceName = "default"; hstring imagePath; LearningModel model = nullptr; LearningModelDeviceKind deviceKind = LearningModelDeviceKind::Default; LearningModelSession session = nullptr; LearningModelBinding binding = nullptr; VideoFrame imageFrame = nullptr; string labelsFilePath; vector<string> labels;Voeg de volgende forward-declaraties toe na uw globale variabelen:
// Forward declarations void LoadModel(); VideoFrame LoadImageFile(hstring filePath); void BindModel(); void EvaluateModel(); void PrintResults(IVectorView<float> results); void LoadLabels();Verwijder in main.cpp de code 'Hallo wereld' (alles in de
mainfunctie ernainit_apartment).Zoek het SqueezeNet.onnx-bestand in uw lokale kloon van de Windows-Machine Learning-opslagplaats . Deze moet zich bevinden in \Windows-Machine-Learning\SharedContent\models.
Kopieer het bestandspad en wijs het toe aan uw
modelPathvariabele waar we het bovenaan hebben gedefinieerd. Vergeet niet om de tekenreeks te beginnen met eenLzodat het een brede tekenreeks wordt, zodat deze goed werkt methstring, en om backslashes (\) te escapen met een extra backslash. Voorbeeld:hstring modelPath = L"C:\\Repos\\Windows-Machine-Learning\\SharedContent\\models\\SqueezeNet.onnx";Eerst implementeren we de
LoadModelmethode. Voeg de volgende methode toe na demainmethode. Met deze methode wordt het model geladen en wordt uitgevoerd hoe lang het duurde:void LoadModel() { // load the model printf("Loading modelfile '%ws' on the '%s' device\n", modelPath.c_str(), deviceName.c_str()); DWORD ticks = GetTickCount(); model = LearningModel::LoadFromFilePath(modelPath); ticks = GetTickCount() - ticks; printf("model file loaded in %d ticks\n", ticks); }Roep tot slot deze methode aan vanuit de
mainmethode:LoadModel();Voer uw programma uit zonder foutopsporing. U zou moeten zien dat uw model succesvol is geladen!
De afbeelding laden
Vervolgens laden we het afbeeldingsbestand in ons programma:
Voeg de volgende methode toe. Met deze methode wordt de afbeelding vanuit het opgegeven pad geladen en wordt er een VideoFrame van gemaakt:
VideoFrame LoadImageFile(hstring filePath) { printf("Loading the image...\n"); DWORD ticks = GetTickCount(); VideoFrame inputImage = nullptr; try { // open the file StorageFile file = StorageFile::GetFileFromPathAsync(filePath).get(); // get a stream on it auto stream = file.OpenAsync(FileAccessMode::Read).get(); // Create the decoder from the stream BitmapDecoder decoder = BitmapDecoder::CreateAsync(stream).get(); // get the bitmap SoftwareBitmap softwareBitmap = decoder.GetSoftwareBitmapAsync().get(); // load a videoframe from it inputImage = VideoFrame::CreateWithSoftwareBitmap(softwareBitmap); } catch (...) { printf("failed to load the image file, make sure you are using fully qualified paths\r\n"); exit(EXIT_FAILURE); } ticks = GetTickCount() - ticks; printf("image file loaded in %d ticks\n", ticks); // all done return inputImage; }Voeg een aanroep toe aan deze methode in de
mainmethode:imageFrame = LoadImageFile(imagePath);Zoek de mediamap in uw lokale kloon van de Windows-Machine Learning-opslagplaats . Deze moet zich bevinden op \Windows-Machine-Learning\SharedContent\media.
Kies een van de afbeeldingen in die map en wijs het bestandspad toe aan de
imagePathvariabele waar we deze bovenaan hebben gedefinieerd. Vergeet niet om het te voorzien van een voorvoegselLom er een brede tekenreeks van te maken en om eventuele backslashes met een tweede backslash te escapen. Voorbeeld:hstring imagePath = L"C:\\Repos\\Windows-Machine-Learning\\SharedContent\\media\\kitten_224.png";Voer het programma uit zonder foutopsporing. U zou moeten zien dat de afbeelding succesvol is geladen!
De invoer en uitvoer binden
Vervolgens maken we een sessie op basis van het model en binden we de invoer en uitvoer van de sessie met behulp van LearningModelBinding.Bind. Zie Een model binden voor meer informatie over binding.
Implementeer de methode
BindModel. Hiermee maakt u een sessie op basis van het model en apparaat en een binding op basis van die sessie. Vervolgens binden we de invoer en uitvoer aan variabelen die we hebben gemaakt met behulp van hun namen. We weten van tevoren dat de invoerfunctie de naam 'data_0' heeft en dat de uitvoerfunctie de naam 'softmaxout_1' heeft. U kunt deze eigenschappen voor elk model zien door ze te openen in Netron, een hulpprogramma voor onlinemodelvisualisatie.void BindModel() { printf("Binding the model...\n"); DWORD ticks = GetTickCount(); // now create a session and binding session = LearningModelSession{ model, LearningModelDevice(deviceKind) }; binding = LearningModelBinding{ session }; // bind the intput image binding.Bind(L"data_0", ImageFeatureValue::CreateFromVideoFrame(imageFrame)); // bind the output vector<int64_t> shape({ 1, 1000, 1, 1 }); binding.Bind(L"softmaxout_1", TensorFloat::Create(shape)); ticks = GetTickCount() - ticks; printf("Model bound in %d ticks\n", ticks); }Voeg een aanroep toe aan
BindModelvanuit demain-methode.BindModel();Voer het programma uit zonder foutopsporing. De invoer en uitvoer van het model moeten succesvol worden gekoppeld. We zijn er bijna!
Het model evalueren
We zijn nu bezig met de laatste stap in het diagram aan het begin van deze zelfstudie, Evalueren. We evalueren het model met behulp van LearningModelSession.Evaluate:
Implementeer de methode
EvaluateModel. Deze methode neemt onze sessie en evalueert deze met behulp van onze binding en een correlatie-id. De correlatie-id is iets dat we later kunnen gebruiken om een bepaalde evaluatieoproep aan te passen aan de uitvoerresultaten. Nogmaals, we weten van tevoren dat de naam van de uitvoer 'softmaxout_1' is.void EvaluateModel() { // now run the model printf("Running the model...\n"); DWORD ticks = GetTickCount(); auto results = session.Evaluate(binding, L"RunId"); ticks = GetTickCount() - ticks; printf("model run took %d ticks\n", ticks); // get the output auto resultTensor = results.Outputs().Lookup(L"softmaxout_1").as<TensorFloat>(); auto resultVector = resultTensor.GetAsVectorView(); PrintResults(resultVector); }Laten we nu
PrintResultsimplementeren. Met deze methode worden de drie belangrijkste waarschijnlijkheden opgehaald voor welk object zich in de afbeelding kan bevinden en worden ze afgedrukt:void PrintResults(IVectorView<float> results) { // load the labels LoadLabels(); // Find the top 3 probabilities vector<float> topProbabilities(3); vector<int> topProbabilityLabelIndexes(3); // SqueezeNet returns a list of 1000 options, with probabilities for each, loop through all for (uint32_t i = 0; i < results.Size(); i++) { // is it one of the top 3? for (int j = 0; j < 3; j++) { if (results.GetAt(i) > topProbabilities[j]) { topProbabilityLabelIndexes[j] = i; topProbabilities[j] = results.GetAt(i); break; } } } // Display the result for (int i = 0; i < 3; i++) { printf("%s with confidence of %f\n", labels[topProbabilityLabelIndexes[i]].c_str(), topProbabilities[i]); } }We moeten ook
LoadLabelsimplementeren. Met deze methode wordt het labelbestand geopend dat alle verschillende objecten bevat die het model kan herkennen en parseert:void LoadLabels() { // Parse labels from labels file. We know the file's entries are already sorted in order. ifstream labelFile{ labelsFilePath, ifstream::in }; if (labelFile.fail()) { printf("failed to load the %s file. Make sure it exists in the same folder as the app\r\n", labelsFilePath.c_str()); exit(EXIT_FAILURE); } std::string s; while (std::getline(labelFile, s, ',')) { int labelValue = atoi(s.c_str()); if (labelValue >= labels.size()) { labels.resize(labelValue + 1); } std::getline(labelFile, s); labels[labelValue] = s; } }Zoek het Labels.txt bestand in uw lokale kloon van de Windows-Machine Learning-opslagplaats . Deze moet zich in \Windows-Machine-Learning\Samples\SqueezeNetObjectDetection\Desktop\cpp bevinden.
Wijs dit bestandspad toe aan de
labelsFilePathvariabele waar we het bovenaan hebben gedefinieerd. Zorg ervoor dat u alle backslashes met een andere backslash escapet. Voorbeeld:string labelsFilePath = "C:\\Repos\\Windows-Machine-Learning\\Samples\\SqueezeNetObjectDetection\\Desktop\\cpp\\Labels.txt";Voeg een aanroep toe aan
EvaluateModelin demain-methode.EvaluateModel();Voer het programma uit zonder foutopsporing. Het moet nu correct herkennen wat er in de afbeelding staat. Hier volgt een voorbeeld van wat het kan uitvoeren:
Loading modelfile 'C:\Repos\Windows-Machine-Learning\SharedContent\models\SqueezeNet.onnx' on the 'default' device model file loaded in 250 ticks Loading the image... image file loaded in 78 ticks Binding the model...Model bound in 15 ticks Running the model... model run took 16 ticks tabby, tabby cat with confidence of 0.931461 Egyptian cat with confidence of 0.065307 Persian cat with confidence of 0.000193
Volgende stappen
Hoera, u hebt objectdetectie werkend gekregen in een C++-bureaubladtoepassing! Vervolgens kunt u opdrachtregelargumenten gebruiken om het model- en afbeeldingsbestanden in te voeren in plaats van ze te coderen, vergelijkbaar met wat het voorbeeld op GitHub doet. U kunt ook proberen de evaluatie uit te voeren op een ander apparaat, zoals de GPU, om te zien hoe de prestaties verschillen.
Speel met de andere voorbeelden op GitHub en breid ze uit zoals u wilt.
Zie ook
Opmerking
Gebruik de volgende bronnen voor hulp bij Windows ML:
- Als u technische vragen over Windows ML wilt stellen of beantwoorden, gebruikt u de tag windows-machine learning op Stack Overflow.
- Als u een fout wilt melden, kunt u een ticket aanmaken op onze GitHub-pagina .