Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
C++ masaüstü (Win32) uygulamalarındaki makine öğrenmesi modelleriyle kolayca etkileşime geçmek için Windows ML API'leri kullanılabilir. Yükleme, bağlama ve değerlendirmenin üç adımını kullanarak uygulamanız makine öğrenmesinin gücünden yararlanabilir.
GitHub'da bulunan SqueezeNet Nesne Algılama örneğinin biraz basitleştirilmiş bir sürümünü oluşturacağız. bitirdiğinizde nasıl olacağını görmek istiyorsanız, örneğin tamamını indirebilirsiniz.
WinML API'lerine erişmek için C++/WinRT kullanacağız. Daha fazla bilgi için bkz. C++/WinRT .
Bu öğreticide aşağıdakilerin nasıl yapılacağını öğreneceksiniz:
- Makine öğrenmesi modeli yükleme
- Görüntüyü VideoFrame olarak yükleme
- Modelin girişlerini ve çıkışlarını bağlama
- Modeli değerlendirme ve anlamlı sonuçlar yazdırma
Önkoşullar
- Visual Studio 2019 (veya Visual Studio 2017, sürüm 15.7.4 veya üzeri)
- Windows 10, sürüm 1809 veya üzeri
- Windows SDK, derleme 17763 veya üzeri
- C++/WinRT için Visual Studio uzantısı
- Visual Studio'da Araçlar > Uzantılar ve Güncelleştirmeler'i seçin.
- Çevrimiçi'yi sol bölmeden seçin ve sağ taraftaki arama kutusuna "WinRT" yazın.
- C++/WinRT'yi seçin, İndir'e tıklayın ve Visual Studio'yu kapatın.
- Yükleme yönergelerini izleyin, ardından Visual Studio'yu yeniden açın.
- Windows- github deposunuMachine-Learning (zip dosyası olarak indirebilir veya makinenize kopyalayabilirsiniz)
Projeyi oluşturma
İlk olarak projeyi Visual Studio'da oluşturacağız:
- Dosya > Yeni > Proje'yi seçerek Yeni Proje penceresini açın.
- Sol bölmede Yüklü > Visual C++ > Windows Masaüstü'nü seçin ve ortada Windows Konsol Uygulaması (C++/WinRT) öğesini seçin.
- Projenize bir Ad ve Konum verin, ardından Tamam'a tıklayın.
- Yeni Evrensel Windows Platformu Projesi penceresinde Hedef ve En Düşük Sürümler'i 17763 veya sonraki bir sürüme ayarlayın ve Tamam'a tıklayın.
- Üst araç çubuğundaki açılan menülerin, bilgisayarınızın mimarisine bağlı olarak Hata Ayıkla ve x64 veya x86 olarak ayarlandığından emin olun.
- Programı hata ayıklamadan çalıştırmak için Ctrl+F5 tuşlarına basın. Terminal bir "Merhaba dünya" metniyle açılmalıdır. Kapatmak için herhangi bir tuşa basın.
Modeli yükleme
Şimdi LearningModel.LoadFromFilePath kullanarak ONNX modelini programımıza yükleyeceğiz:
pch.h dosyasında (Üst Bilgi Dosyaları klasörüne) aşağıdaki
includedeyimleri ekleyin (bunlar bize ihtiyacımız olan tüm API'lere erişim sağlar):#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>main.cpp(Kaynak Dosyalar klasörüne) aşağıdaki
usingdeyimleri ekleyin: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;usingifadelerinden sonra aşağıdaki değişken bildirimlerini ekleyin.// 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;Genel değişkenlerinizden sonra aşağıdaki iletme bildirimlerini ekleyin:
// Forward declarations void LoadModel(); VideoFrame LoadImageFile(hstring filePath); void BindModel(); void EvaluateModel(); void PrintResults(IVectorView<float> results); void LoadLabels();main.cpp'de,
main'den sonrakiinit_apartmentişlevindeki "Merhaba dünya" kodunu kaldırın.Windows-Machine-Learning deposunun yerel kopyasında SqueezeNet.onnx dosyasını bulun. \Windows-Machine-Learning\SharedContent\models konumunda olmalıdır.
Dosya yolunu kopyalayın ve en üstte tanımladığımız değişkeninize
modelPathatayın. Dizeyi bir geniş karakter dizgisi yapmak veLile düzgün çalışmasını sağlamak için başına birhstringeklemeyi ve ters eğik çizgileri (\) kaçış karakteri olarak kaydetmek için ekstra bir ters eğik çizgi eklemeyi unutmayın. Örneğin:hstring modelPath = L"C:\\Repos\\Windows-Machine-Learning\\SharedContent\\models\\SqueezeNet.onnx";İlk olarak yöntemini uygulayacağız
LoadModel. yönteminden sonramainaşağıdaki yöntemi ekleyin. Bu yöntem modeli yükler ve ne kadar sürdüğünü çıkış olarak oluşturur: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); }Son olarak, bu yöntemi
mainyönteminden çağırın.LoadModel();Hata ayıklamadan programınızı çalıştırın. Modelinizin başarıyla yüklendiğini görmeniz gerekir!
Görüntüyü yükleme
Ardından görüntü dosyasını programımıza yükleyeceğiz:
Aşağıdaki yöntemi ekleyin. Bu yöntem, verilen yoldan görüntüyü yükler ve görüntüden bir VideoFrame oluşturur:
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; }Bu yönteme,
mainyönteminde bir çağrı ekleyin.imageFrame = LoadImageFile(imagePath);Windows-Machine-Learning deposunun yerel kopyasında medya klasörünü bulun. \Windows-Machine-Learning\SharedContent\media konumunda olmalıdır.
Bu klasördeki görüntülerden birini seçin ve dosya yolunu en üstte tanımladığımız değişkene
imagePathatayın. Bunu geniş bir karakter dizesi yapmak ve ters eğik çizgilerden başka bir ters eğik çizgiyle kaçmak için bir ön ekiLeklemeyi unutmayın. Örneğin:hstring imagePath = L"C:\\Repos\\Windows-Machine-Learning\\SharedContent\\media\\kitten_224.png";Programı hata ayıklamadan çalıştırın. Görüntünün başarıyla yüklendiğini görmeniz gerekir!
Girişi ve çıkışı bağlama
Ardından modeli temel alan bir oturum oluşturacak ve LearningModelBinding.Bind kullanarak oturumdaki giriş ve çıkışı bağlayacağız. Bağlama hakkında daha fazla bilgi için bkz Model bağlama.
BindModelyöntemini uygulayın. Bu, modeli ve cihazı temel alan bir oturum ve bu oturumu temel alan bir bağlama oluşturur. Ardından girişleri ve çıkışları, adlarını kullanarak oluşturduğumuz değişkenlere bağlarız. Giriş özelliğinin "data_0" ve çıkış özelliğinin "softmaxout_1" olarak adlandırıldığını önceden biliyoruz. Bu özellikleri çevrimiçi bir model görselleştirme aracı olan Netron'da açarak herhangi bir modelin özelliklerini görebilirsiniz.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); }BindModelçağrısınımainyöntemine ekleyin.BindModel();Programı hata ayıklamadan çalıştırın. Modelin girişleri ve çıkışları başarıyla bağlanmalıdır. Neredeyse geldik!
Modeli değerlendirme
Şimdi bu öğreticinin başındaki diyagramdaki son adım olan Değerlendir'deyiz. LearningModelSession.Evaluate kullanarak modeli değerlendireceğiz:
EvaluateModelyöntemini uygulayın. Bu yöntem oturumumuzu alır ve bağlama ve bağıntı kimliğimizi kullanarak değerlendirir. Bağıntı kimliği, daha sonra çıkış sonuçlarıyla belirli bir değerlendirme çağrısını eşleştirmek için kullanabileceğimiz bir kimliktir. Yine, çıkışın adının "softmaxout_1" olduğunu önceden biliyoruz.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); }PrintResults'yi şimdi uygulayalım. Bu yöntem, görüntüde hangi nesnenin olabileceğine ilişkin ilk üç olasılığı alır ve bunları yazdırır: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]); } }Ayrıca
LoadLabelsuygulamamız gerekir. Bu yöntem, modelin tanıyabileceği tüm farklı nesneleri içeren etiket dosyasını açar ve ayrıştırabilir: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; } }Windows-Machine-Learning deposunun yerel kopyasında Labels.txt dosyasını bulun. \Windows-Machine-Learning\Samples\SqueezeNetObjectDetection\Desktop\cpp içinde olmalıdır.
Bu dosya yolunu
labelsFilePathen üstte tanımladığımız değişkene atayın. Ters eğik çizgilerden başka bir ters eğik çizgiyle kaçış yaptığınızdan emin olun. Örneğin:string labelsFilePath = "C:\\Repos\\Windows-Machine-Learning\\Samples\\SqueezeNetObjectDetection\\Desktop\\cpp\\Labels.txt";EvaluateModelyöntemindemainçağrısı ekleyin.EvaluateModel();Programı hata ayıklamadan çalıştırın. Artık görüntüdekileri doğru şekilde tanıması gerekir! Örnek olarak çıktısının ne olabileceği aşağıda verilmiştir:
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
Sonraki Adımlar
Yaşasın, C++ masaüstü uygulamanızda nesne algılamayı çalıştırmayı başardınız! Ardından, GitHub'daki örneğin yaptığı gibi model ve görüntü dosyalarını sabit kodlamak yerine giriş yapmak için komut satırı bağımsız değişkenlerini kullanmayı deneyebilirsiniz. Performansın nasıl farklılık gösterdiğini görmek için değerlendirmeyi GPU gibi farklı bir cihazda çalıştırmayı da deneyebilirsiniz.
GitHub'da diğer örneklerle oynayın ve istediğiniz gibi genişletin!
Ayrıca bakınız
Uyarı
Windows ML ile ilgili yardım için aşağıdaki kaynakları kullanın:
- Windows ML hakkında teknik sorular sormak veya yanıtlamak için stack overflow'dawindows-machine-learning etiketini kullanın.
- Bir hatayı bildirmek için lütfen GitHub'ımızda bir sorun oluşturun.