다음을 통해 공유


자습서: Windows Machine Learning UWP 애플리케이션 만들기(C#)

이 자습서에서는 학습된 기계 학습 모델을 사용하여 사용자가 필기한 숫자를 인식하는 간단한 유니버설 Windows 플랫폼 애플리케이션을 빌드합니다. 이 자습서는 주로 UWP 애플리케이션에서 Windows ML을 로드하여 사용하는 방법을 중점적으로 설명합니다.

다음 비디오는 이 자습서의 기반이 되는 샘플을 보여줍니다.


완료한 자습서의 코드만 살펴보려면, WinML GitHub 리포지토리에서 찾을 수 있습니다. C++/CX로도 제공됩니다.

필수 조건

1. Visual Studio에서 프로젝트 열기

GitHub에서 프로젝트를 다운로드했으면 Visual Studio를 시작하고 MNIST_Demo.sln 파일(파일의 위치는 <리포지토리 경로>\Windows-Machine-Learning\Samples\MNIST\Tutorial\cs임)을 엽니다. 솔루션이 사용 불가능으로 표시되면 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하여 프로젝트 다시 로드를 선택해야 합니다.

다음을 포함하여 XAML 컨트롤 및 이벤트가 구현된 템플릿이 제공됩니다.

  • 숫자를 그릴 수 있는 InkCanvas
  • 숫자를 해석하고 캔버스를 지울 수 있는 Buttons
  • InkCanvas 출력을 VideoFrame으로 변환하는 도우미 루틴

솔루션 탐색기 내에 프로젝트에는 세 가지 주요 코드 파일이 있습니다.

  • MainPage.xaml - InkCanvas, 단추 및 레이블의 UI를 만드는 모든 XAML 코드
  • MainPage.xaml.cs - 애플리케이션 코드가 있는 곳
  • Helper.cs - 이미지 형식을 자르고 변환하는 도우미 루틴

Visual Studio solution explorer with project files

2. 프로젝트 빌드 및 실행

디바이스가 64비트인 경우 Visual Studio 도구 모음에서 솔루션 플랫폼x64로 변경하여 로컬 머신에서 프로젝트를 실행하고 32비트인 경우 x86으로 변경합니다. (Windows 설정 앱(시스템 > 정보 > 디바이스 사양 > 시스템 형식)에서 확인할 수 있습니다.)

프로젝트를 실행하려면 도구 모음에서 디버깅 시작 단추를 클릭하거나 F5를 누릅니다. 사용자가 숫자를 쓸 수 있는 InkCanvas, 숫자를 해석할 수 있는 Recognize 단추, 해석된 숫자가 텍스트로 표시될 빈 레이블 필드 및 InkCanvas를 지우는 Clear Digit 단추가 애플리케이션에 표시되어야 합니다.

Application screenshot

참고 항목

프로젝트가 빌드되지 않으면 프로젝트의 배포 대상 버전을 변경해야 할 수도 있습니다. 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다. 애플리케이션 탭에서 OS와 SDK가 일치하도록 대상 버전최소 버전을 설정합니다.

참고 항목

애플리케이션이 이미 설치되었다는 경고가 표시되는 경우 를 선택하여 배포를 계속합니다. 그래도 해결되지 않으면 Visual Studio를 닫았다가 다시 열어야 할 수도 있습니다.

3. 모델 다운로드

다음으로 애플리케이션에 추가할 기계 학습 모델을 살펴보겠습니다. 이 자습서에서는 미리 학습된 MNIST 모델을 사용합니다. 이 모델은 Microsoft CNTK(Cognitive Toolkit)을 사용하여 학습되었으며 ONNX 형식으로 내보내졌습니다.

MNIST 모델은 자산 폴더에 이미 포함되어 있으며 애플리케이션에 기존 항목으로 추가해야 합니다. GitHub의 ONNX Model Zoo에서 미리 학습된 모델을 다운로드할 수도 있습니다.

4. 모델 추가

솔루션 탐색기에서 자산 폴더를 마우스 오른쪽 단추로 클릭하고 추가>기존 항목을 선택합니다. 파일 선택기에서 ONNX 모델 위치를 가리킨 후 추가를 클릭합니다.

이제 프로젝트에 두 개의 새 파일이 있습니다.

  • mnist.onnx - 학습된 모델
  • mnist.cs - Windows ML 생성 코드

Solution explorer with new files

애플리케이션을 컴파일할 때 모델이 빌드되도록 하려면 mnist.onnx 파일을 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다. 빌드 작업콘텐츠를 선택합니다.

이제 mnist.cs 파일에서 새로 생성된 코드를 살펴보겠습니다. 세 가지 클래스가 있습니다.

  • mnistModel은 기계 학습 모델 표현을 만들고 시스템 기본 디바이스에 세션을 생성하고 특정 입력과 출력을 모델에 바인딩하며 모델을 비동기적으로 평가합니다.
  • mnistInput은 모델의 예상 입력 형식을 초기화합니다. 이 경우 예상 입력은 ImageFeatureValue입니다.
  • mnistOutput은 모델의 출력 형식을 초기화합니다. 이 경우 출력은 TensorFloat 유형의 Plus214_Output_0이라는 목록이 됩니다.

이제 이러한 클래스를 사용하여 프로젝트에서 모델을 로드, 바인딩 및 평가합니다.

5. 모델 로드, 바인딩 및 평가

Windows ML 애플리케이션의 경우 이용하려는 패턴은 로드 > 바인딩 > 평가입니다.

  1. 기계 학습 모델을 로드합니다.
  2. 입력 및 출력을 모델에 바인딩합니다.
  3. 모델을 평가하고 결과를 봅니다.

mnist.cs에 생성된 인터페이스 코드를 사용하여 애플리케이션에서 모델을 로드, 바인딩 및 평가합니다.

먼저 MainPage.xaml.cs에서 모델, 입력 및 출력을 인스턴스화합니다. MainPage 클래스에 다음 멤버 변수를 추가합니다.

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

그런 다음 LoadModelAsync에서 모델을 로드합니다. 이 메서드는 모델의 메서드를 사용하기 전(즉, MainPageLoaded 이벤트, 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 사용을 선택합니다.

다음으로 입력 및 출력을 모델에 바인딩하려고 합니다. 생성된 코드에는 mnistInputmnistOutput 래퍼 클래스도 포함됩니다. 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에 그려진 숫자를 인식할 수 있습니다.

complete application

완료되었습니다. 첫 번째 Windows ML 애플리케이션이 생성되었습니다! Windows ML 사용 방법을 보여주는 추가 샘플은 GitHub의 Windows-Machine-Learning 리포지토리를 확인하세요.

참고 항목

Windows ML에 대한 도움말은 다음 리소스를 참조하세요.

  • Windows ML에 대한 기술적인 질문을 하거나 질문에 답하려면, Stack Overflow에서 windows-machine-learning 태그를 사용하세요.
  • 버그를 보고하려면 GitHub에서 문제를 제출하세요.