在本教學課程中,我們將建置簡單的通用 Windows 平台應用程式,以使用定型的機器學習模型來辨識用戶繪製的數值數位。 本教學課程主要著重於如何在UWP應用程式中載入和使用Windows ML。
下列影片會逐步解說本教學課程所依據的範例。
如果您想要只查看已完成教學課程的程式代碼,您可以在 WinML GitHub 存放庫中找到它。 它也可在 C++/CX 中使用。
先決條件
- Windows 10 (版本 1809 或更高版本)
- Windows 10 SDK (組建 17763 或更高版本)
- Visual Studio 2019 (或 Visual Studio 2017 15.7.4 版或更新版本)
- Visual Studio 2019 或 2017 的 Windows Machine Learning 程式代碼產生器擴充功能
- 一些基本的 UWP 和 C# 知識
1.在 Visual Studio 中開啟專案
從 GitHub 下載項目之後,請啟動 Visual Studio 並開啟 MNIST_Demo.sln 檔案(它應該位於 <存放庫>路徑\Windows-Machine-Learning\Samples\MNIST\Tutorial\cs)。 如果方案顯示為無法使用,您必須以滑鼠右鍵按兩下方案總管中的 項目,然後 選取 [ 重載專案]。
我們已提供具有實作 XAML 控件和事件的範本,包括:
- 用來繪製數字的 InkCanvas。
- 按鈕 用來辨識數字並清除畫布。
- 協助程式例程,將 InkCanvas 輸出轉換成 VideoFrame。
在 方案總管內,專案有三個主要的程式代碼檔案:
- MainPage.xaml - 我們所有的 XAML 程式代碼,以建立 InkCanvas、按鈕和標籤的 UI。
- MainPage.xaml.cs - 應用程式程序代碼所在的位置。
- Helper.cs - 協助程式例程裁剪和轉換影像格式。
2.建置並執行專案
在 Visual Studio 工具列中,如果您的裝置是 64 位,請將 [方案平臺 ] 變更為 x64 ,以在本機電腦上執行專案,如果它是 32 位,則為 x86 。 (您可以在 Windows 設定中查看: 系統 > 關於 > 裝置規格 > 系統類型。
若要執行專案,請按下工具列上的 [ 開始偵錯] 按鈕,或按 F5。 應用程式應該會顯示 InkCanvas,讓使用者可以寫入數位、可解譯數位的 [辨識] 按鈕、將解譯數字顯示為文字的空白卷標字段,以及清除 InkCanvas 的 [清除數位] 按鈕。
備註
如果專案不會建置,您可能需要變更專案的部署目標版本。 以滑鼠右鍵按兩下 方案 總管中的項目,然後選取 [ 屬性]。 在 [ 應用程式] 索引標籤中,設定 [目標版本 ] 和 [ 最小版本 ] 以符合您的 OS 和 SDK。
備註
如果您收到已安裝應用程式的警告,只要選取 [ 是 ] 繼續部署即可。 如果 Visual Studio 仍然無法運作,您可能需要關閉 Visual Studio 並重新開啟。
3.下載模型
接下來,讓我們取得要新增至應用程式的機器學習模型。 在本教學課程中,我們將使用預先定型的 MNIST 模型,該模型是以 Microsoft 認知工具組 (CNTK) 定型,並 導出至 ONNX 格式。
MNIST 模型已包含在 [資產 ] 資料夾中,您必須將它新增至您的應用程式做為現有專案。 您也可以從 GitHub 上的 ONNX 模型動物園 下載預先定型的模型。
4.新增模型
以滑鼠右鍵按兩下 [方案總管] 中的 [資產] 資料夾,然後選取 [新增>現有專案]。 將檔案選擇器指向 ONNX 模型的位置,然後按兩下 [ 新增]。
項目現在應該有兩個新的檔案:
- mnist.onnx - 已定型的模型。
- mnist.cs - Windows ML 產生的程式代碼。
若要確定模型會在編譯應用程式時建置,請以滑鼠右鍵按兩下 mnist.onnx 檔案,然後選取 [ 屬性]。 針對建置動作,選取內容。
現在,讓我們看看 mnist.cs 檔案中新產生的程序代碼。 我們有三個類別:
- mnistModel 會建立機器學習模型表示法、在系統預設裝置上建立會話、將特定輸入和輸出系結至模型,並以異步方式評估模型。
- mnistInput 會初始化模型預期的輸入類型。 在此情況下,輸入需要 ImageFeatureValue。
- mnistOutput 會初始化模型將輸出的類型。 在此情況下,輸出會是名為 Plus214_Output_0 的 TensorFloat 類型清單。
我們現在會使用這些類別來載入、系結和評估專案中的模型。
5.載入、系結及評估模型
針對 Windows ML 應用程式,我們想要遵循的模式是:載入 > 系結 > 評估。
- 載入機器學習模型。
- 將輸入和輸出系結至模型。
- 評估模型並檢視結果。
我們將使用 mnist.cs 中產生的介面程式代碼來載入、系結及評估應用程式中的模型。
首先,在 MainPage.xaml.cs中,讓我們具現化模型、輸入和輸出。 將下列成員變數新增至 MainPage 類別:
private mnistModel ModelGen;
private mnistInput ModelInput = new mnistInput();
private mnistOutput ModelOutput;
然後,在 LoadModelAsync 中,我們將載入模型。 在使用模型的任何方法之前,應該先呼叫這個方法,也就是可以在MainPage的Loaded事件中,OnNavigatedTo覆寫時,或在呼叫recognizeButton_Click之前的任何地方進行。 mnistModel 類別代表 MNIST 模型,並在系統預設裝置上建立會話。 為了載入模型,我們呼叫 CreateFromStreamAsync 方法,傳入 ONNX 檔案做為 參數。
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);
}
備註
如果您在 IRandomAccessStreamReference 底下取得紅色底線,則需要包含其命名空間。 將游標放在其上方,按 Ctrl + 。 然後從下拉功能表中選取 [使用 Windows.Storage.Streams ]。
接下來,我們想要將輸入和輸出系結至模型。 產生的程式代碼也包含 mnistInput 和 mnistOutput 包裝函式類別。 mnistInput 類別代表模型的預期輸入,mnistOutput 類別代表模型的預期輸出。
若要初始化模型的輸入物件,請呼叫 mnistInput 類別建構函式、傳入應用程式數據,並確定您的輸入數據符合模型預期的輸入類型。 mnistInput 類別需要 ImageFeatureValue,因此我們使用輔助方法來取得輸入的 ImageFeatureValue。
在 helper.cs中使用我們的協助程式函式,我們會複製 InkCanvas 的內容、將它轉換成 ImageFeatureValue 類型,並將它系結至我們的模型。
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);
}
針對輸出,我們只需使用指定的輸入來呼叫 EvaluateAsync 。 初始化輸入之後,請呼叫模型的 EvaluateAsync 方法來評估輸入數據上的模型。 EvaluateAsync 會將輸入和輸出系結至模型物件,並在輸入上評估模型。
由於模型會傳回輸出張量,因此我們會先將它轉換成易記的數據類型,然後剖析傳回的清單,以判斷哪一個數位的機率最高,並顯示該數位。
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();
}
最後,我們希望清除 InkCanvas,以便讓使用者可以繪製另一個數字。
private void clearButton_Click(object sender, RoutedEventArgs e)
{
inkCanvas.InkPresenter.StrokeContainer.Clear();
numberLabel.Text = "";
}
6.啟動應用程式
一旦建置並啟動應用程式(按 F5),我們就能辨識 InkCanvas 上繪製的數位。
就是這樣 - 您已建立第一個 Windows ML 應用程式! 如需示範如何使用 Windows ML 的更多範例,請參閱 GitHub 上的 Windows-Machine-Learning 存放庫。
備註
使用以下資源以獲得 Windows ML 的協助。
- 如需詢問或回答有關 Windows ML 的技術問題,請使用 Stack Overflow 上的 windows-machine-learning 標籤。
- 如需回報錯誤 (bug),請在 GitHub 上提出問題。