Windows ML API를 사용하여 Windows 앱에 데이터 분석 모델 배포
이 자습서의 이전 부분에서 ONNX 형식으로 모델을 빌드하고 내보내는 방법을 알아보았습니다. 이제는 내보낸 모델을 Windows 애플리케이션에 포함하고, Windows ML API를 호출하여 디바이스에서 로컬로 실행하는 방법을 보여줍니다.
작업이 완료되면 데이터 분석 앱이 작동할 것입니다.
샘플 앱 정보
자습서의 이 단계에서는 붓꽃의 테이블 형식 데이터를 분석할 수 있는 앱을 만듭니다. 앱을 사용하면 필요한 입력 정보가 포함된 Excel 파일을 추가하거나 입력 매개 변수(붓꽃의 꽃받침과 꽃잎의 길이와 너비(cm))를 수동으로 입력할 수 있습니다. 이러한 특징은 이전 파트에서 빌드하고 학습한 로컬 저장 신경망 ONNX 모델에 의해 처리됩니다. 모델 출력에 따라 앱에 올바른 붓꽃 종류가 표시됩니다.
여기서는 이 과정을 안내합니다.
참고 항목
미리 정의된 코드 샘플을 사용하도록 선택하면 솔루션 파일을 복제할 수 있습니다. 리포지토리를 복제하고, 이 샘플로 이동한 다음, Visual Studio에서 Iris Data Analysis.csproj
파일을 엽니다. 이를 사용하고 있는지 확인하려면 이 페이지의 애플리케이션 시작 부분으로 건너뜁니다.
아래에서는 앱을 만들고 Windows ML 코드를 추가하는 방법을 안내합니다.
Windows ML 데스크톱(C#) 앱 만들기
작동하는 Windows ML 앱을 만들려면 다음을 수행해야 합니다.
- 기계 학습 모델을 로드합니다.
- 모델의 입력과 출력을 바인딩합니다.
- 모델을 평가하고, 의미 있는 결과를 표시합니다.
더 나은 사용자 환경을 제공하려면 기본 UI도 만들어야 합니다.
Visual Studio 내에서 새 프로젝트 열기
- 시작하겠습니다. Visual Studio를 열고,
Create a new project
를 선택합니다.
- 검색 창에서 사용자의 언어로
C#
을, 대상 플랫폼으로Windows
를, 프로젝트 형식으로Dektop
을 선택합니다. 프로젝트 형식으로NUnit Test Project (.NET Core)
를 선택하고,next
를 선택하여 프로젝트의 구성 창을 엽니다.
- 구성 창에서 다음을 수행합니다.
- 프로젝트 이름을 지정합니다. 여기서는 이를 붓꽃 데이터 분석이라고 합니다.
- 프로젝트의 위치를 선택합니다.
- VS2019를 사용하는 경우
Create directory for solution
을 선택해야 합니다. - VS2017을 사용하는 경우
Place solution and project in the same directory
를 선택 취소해야 합니다.
create
를 눌러 프로젝트를 만듭니다. 최소 대상 버전 창이 팝업될 수 있습니다. 최소 버전이 Windows 10, 버전 1809(10.0, 빌드 17763) 이상으로 설정되어 있어야 합니다.
- 프로젝트가 만들어지면 프로젝트 폴더로 이동하여 assets 폴더(
[….\DataClassifier\Assets]
)를 열고,Network.onnx
파일을 이 위치에 복사합니다.
프로젝트 솔루션 살펴보기
프로젝트 솔루션을 살펴보겠습니다.
여러 개의 CS 코드 파일이 Visual Studio의 솔루션 탐색기 내에 자동으로 만들어졌습니다. MainPage.xaml
에는 GUI에 대한 XAML 코드가 포함되어 있고, MainPage.xaml.cs
에는 애플리케이션 코드가 포함되어 있습니다. 이전에 UWP 앱을 만든 적이 있으면 이러한 파일에 매우 익숙할 것입니다.
Assets 폴더에 Network.onnx
파일을 추가했지만, 이 파일을 이 프로젝트에도 적절하게 추가해야 합니다.
- 솔루션 탐색기에서 Assets 폴더를 마우스 오른쪽 단추로 클릭하고
Add > Existing Item
을 선택합니다. Iris Data Analysis [….\Iris Data Analysis \Assets]
내의 Assets 폴더로 이동하여 이전에 복사한Network.onnx model
을 찾은 다음,Add
를 선택합니다.- 애플리케이션을 컴파일할 때 모델이 빌드되도록 하려면
Network.onnx
파일을 마우스 오른쪽 단추로 클릭하고Properties
를 선택합니다.Build Action
를Content
로 설정합니다.
또한 Windows ML API를 호출하는 클래스와 메서드가 포함된 몇 가지 추가 기계 학습 코드를 수용하기 위해 새 cs-code 클래스 파일을 만들어야 합니다.
- Visual Studio에서 솔루션 이름을 마우스 오른쪽 단추로 클릭하고
add
및new item
을 선택합니다. 열린 창에서Class
를 선택하고 이름을 지정합니다. 여기서는IrisModel.cs
를 사용합니다. 새 클래스 파일은 프로젝트 아래에 나타납니다.
.
Machine Learning 코드 만들기
이 단계에서는 Windows Machine Learning API를 호출할 모든 클래스와 메서드를 만듭니다. 이를 통해 프로젝트에서 ONNX 기계 학습 모델을 로드, 바인딩 및 평가할 수 있습니다.
IrisModel.cs
파일을 두 번 클릭합니다.필요한 모든 API에 액세스하려면 using 문을 다음으로 바꿉니다.
using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.AI.MachineLearning;
using Windows.Storage;
기계 학습 클래스 초기화
Windows Machine Learning API와 상호 작용할 수 있도록 IrisModel.cs
에 여러 클래스를 추가해야 합니다.
학습된 기계 학습 모델에 액세스하기 위해 LearningModel
클래스를 사용합니다. 이 클래스는 Windows.AI.MachineLearning
네임스페이스의 일부이며 학습된 기계 학습 모델을 나타냅니다. 인스턴스화되면 LearningModel
은 Windows ML API와 상호 작용하는 데 사용하는 기본 개체가 됩니다.
학습 모델을 평가하려면 평가 세션을 만들어야 합니다. 이를 위해 LearningModelSession
클래스를 사용합니다. 이 클래스는 기계 학습 모델을 평가하고, 모델을 디바이스에 바인딩한 다음, 모델을 실행하고 평가하는 데 사용됩니다. 이 API로 세션을 만들 때 모델을 실행할 디바이스를 선택할 수도 있습니다(기본값은 CPU).
또한 기계 학습 모델의 출력 레이블을 지정해야 합니다. 나중에 해당 레이블을 모델의 예측 출력에 연결할 수 있습니다.
참고 항목
LearningModel
및 LearningModelSession
클래스에 대해 자세히 알아보려면 LearningModel 클래스 설명서 및 LearningModelSession 클래스 설명서를 참조하세요.
- 다음 코드를
IrisModel.cs
파일에 추가합니다.
class IrisModel
{
private LearningModel _learning_model;
private LearningModelSession _session;
private String[] _labels = { "Iris-setosa", "Iris-versicolor", "Iris-virginica"};
모델 로드
다음으로, 기계 학습 모델을 로드하고 방금 정의한 클래스로 세션을 만들어야 합니다. 모델을 로드하려면 LearningModel
클래스의 여러 정적 메서드를 사용합니다. 이 경우 ISorageFile
에서 ONNX 모델을 비동기식으로 로드할 수 있는 LoadFromStorageFileAsync를 사용합니다.
참고 항목
모델을 로드하는 추가 방법에 대한 자세한 내용은 모델 로드 설명서를 검토하세요.
- 다음 코드를
IrisModel.cs
파일에 추가합니다.
public async Task Initialize()
{
// Load and create the model and session
var modelFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Assets//Network.onnx"));
_learning_model = await LearningModel.LoadFromStorageFileAsync(modelFile);
_session = new LearningModelSession(_learning_model);
}
모델 입력 텐서 정의
이제 모델 요구 사항에 따라 올바른 입력을 정의합니다. 이전 파트에서 구축한 네트워크 모델에는 네 개의 입력 값이 있습니다. 모든 입력 값은 꽃받침 길이(cm), 꽃받침 너비(cm), 꽃잎 길이(cm), 꽃잎 너비(cm) 등 붓꽃의 네 가지 특징의 크기를 나타냅니다. 이 입력을 기반으로 모델은 해당 매개 변수에 가장 적합한 붓꽃 종류를 반환합니다. 입력 값의 크기를 유효한 논리 값으로 제한해야 합니다. 이 자습서에서는 다음을 사용합니다.
- 꽃받침 길이 - 1cm~100cm
- 꽃받침 너비 - 1cm~8cm
- 꽃잎 길이 - 0.5cm~10cm
- 꽃잎 너비 - 0.1cm~5cm
- 다음 코드를
IrisModel.cs
파일에 추가합니다.
private float _sepal_length = 1.0f;
public float Sepal_Length
{
get
{
return _sepal_length;
}
set
{
// validate range [1,10]
if (value >= 1 && value <= 10)
{
_sepal_length = value;
}
}
}
private float _sepal_width = 1.0f;
public float Sepal_Width
{
get
{
return _sepal_width;
}
set
{
// validate range [1, 8]
if (value >= 1 && value <= 8)
{
_sepal_width = value;
}
}
}
private float _petal_length = 0.5f;
public float Petal_Length
{
get
{
return _petal_length;
}
set
{
// validate range [0.5, 10]
if (value >= 0.5 && value <= 10)
{
_petal_length = value;
}
}
}
private float _petal_width = 0.1f;
public float Petal_Width
{
get
{
return _petal_width;
}
set
{
// validate range [0.1, 5]
if (value >= 0.1 && value <= 5)
{
_petal_width = value;
}
}
}
Windows ML API는 ONNX 모델에서 지원하는 네 가지 설명 클래스(텐서, 시퀀스, 맵 및 이미지)의 입력 값을 허용합니다. 이 경우, 모델에는 float32[batch_size,4] 모양의 32비트 텐서 부동 개체가 필요합니다. 일괄 처리 크기가 1이므로 입력 텐서 셰이프는 [1x4]입니다.
텐서 입력을 만들려면 TensorFloat 클래스를 사용합니다.
TensorFloat
클래스는 Windows.AI.MachineLearning
네임스페이스의 일부이며, 32비트 부동 소수점 값의 텐서인 32비트 부동 텐서 개체를 정의하는 데 사용됩니다. 이 클래스는 텐서를 빌드하기 위한 몇 가지 유용한 메서드를 포함합니다. 귀하의 경우 CreateFromArray 메서드를 사용하여 모델에 필요한 정확한 크기로 텐서 입력을 빌드합니다. 평가 메서드 내에 해당 호출을 추가하겠습니다.
모델 바인딩 및 평가
모델 입력 텐서를 정의하고 학습된 모델 및 세션을 인스턴스화했으므로 이제 학습된 기계 학습 모델을 바인딩하고 평가하는 메서드를 만들어야 합니다.
이 메서드는 기계 학습 앱의 핵심 부분입니다. 여기에는 입력 값의 텐서화와 모델 입력의 바인딩이 포함됩니다. 나중에 애플리케이션 코드에서 이 모델을 사용하여 모델을 평가합니다.
입력과 출력을 바인딩하려면 LearningModelBinding
클래스를 사용합니다. 기계 학습 모델에는 모델 내외부로 정보를 전달하는 입력 및 출력 기능이 있습니다. 필요한 기능은 Windows ML API에서 지원해야 합니다. LearningModelBinding
클래스는 값을 명명된 입력 및 출력 기능에 바인딩하기 위해 LearningModelSession
에 적용됩니다.
LearningModelBinding
클래스에는 이름이 지정된 기능에 값을 바인딩하는 데 사용할 수 있는 몇 가지 미리 정의된 메서드가 있습니다. 여기에서 Bind
메서드를 사용하여 값을 모델에 바인딩합니다.
모델을 평가하고 모델에서 결과를 받으려면 LearningModelSession
에서 관련 사전 정의 평가 메서드(이 경우 Evaluate
메서드)를 호출합니다. 이 방법은 LearningModelBinding
클래스에서 제공하는 기능 값을 사용하여 기계 학습 모델을 평가하여 필요한 기능을 제공합니다.
참고 항목
모델을 실행하는 다른 평가 메서드에 대한 자세한 내용은 LearningModelSession 클래스 설명서를 검토하여 LearningModelSession에서 구현할 수 있는 메서드를 확인하세요.
결과 추출 및 표시
모델은 텐서 부동 출력으로 텐서 형식의 예측 값을 반환합니다. 이제 모델 출력을 추출하고 올바른 결과를 표시해야 합니다. 이렇게 하려면 서술형 출력에서 GetAsVectorView()
함수를 실행하여 텐서 형식을 벡터로 변환합니다.
모델은 각각 하나의 특정 붓꽃 종류를 나타내는 세 가지 확률 값을 반환합니다. 확률이 가장 높은 레이블을 반환해야 합니다.
- 다음 코드를
IrisModel.cs
파일에 추가합니다.
internal String Evaluate()
{
// input tensor shape is [1x4]
long[] shape = new long[2];
shape[0] = 1;
shape[1] = 4;
// set up the input tensor
float[] input_data = new float[4];
input_data[0] = _sepal_length;
input_data[1] = _sepal_width;
input_data[2] = _petal_length;
input_data[3] = _petal_width;
TensorFloat tensor_float = TensorFloat.CreateFromArray(shape, input_data);
// bind the tensor to "input"
var binding = new LearningModelBinding(_session);
binding.Bind("input", tensor_float);
// evaluate
var results = _session.Evaluate(binding, "");
// get the results
TensorFloat prediction = (TensorFloat)results.Outputs.First().Value;
var prediction_data = prediction.GetAsVectorView();
// find the highest predicted value
int max_index = 0;
float max_value = 0;
for (int i = 0; i < prediction_data.Count; i++)
{
var val = prediction_data.ElementAt(i);
if (val > max_value)
{
max_value = val;
max_index = i;
}
}
// return the label corresponding to the highest predicted value
return _labels.ElementAt(max_index);
}
이제 코드의 기계 학습 부분을 완료했습니다. 이제 모델을 Windows 애플리케이션과 쉽게 통합할 수 있습니다. 이 자습서의 마지막 부분에서는 이미 만든 메서드를 사용하여 모델을 테스트하기 위한 기본 Windows GUI 및 제어 코드를 제공했습니다.
애플리케이션 GUI 만들기
앱에 대한 GUI 앱 코드를 만들려면
MainPage.xaml
코드 파일을 두 번 클릭하고 GUI에 대해 미리 정의된 템플릿을 엽니다.아래 코드를
“Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" " Height="939">
줄 아래에 있는MainPage.xaml
에 복사하여 붙여넣습니다.
<Grid Margin="30,30,30,30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock x:Name="title" HorizontalAlignment="Left" Text="Data Analysis App - Windows ML" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="32" TextDecorations="Underline" FontWeight="Bold"/>
<TextBlock x:Name="subtitle" HorizontalAlignment="Left" Text="Provide the input :" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="20" Grid.Row="1" FontWeight="Bold"/>
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="sepal_length" Text="sepal length in mm [range of 10 - 100]:" VerticalAlignment="Center"/>
<TextBlock x:Name="sepal_width" Text="sepal width in mm [range of 10 - 80]:" VerticalAlignment="Center" Grid.Row="1"/>
<TextBlock x:Name="petal_length" Text="petal length in mm [range of 5 - 100]:" VerticalAlignment="Center" Grid.Row="2"/>
<TextBlock x:Name="petal_width" Text="sepal width in mm [range of 1 - 50]:" VerticalAlignment="Center" Grid.Row="3"/>
<Slider x:Name="sepal_length_input" Minimum="10" Maximum="100" Orientation="Horizontal" Grid.Column="1" Width="200" ValueChanged="sepal_length_input_ValueChanged"/>
<Slider x:Name="sepal_width_input" Minimum="10" Maximum="80" Orientation="Horizontal" Grid.Row="1" Grid.Column="1" Width="200" ValueChanged="sepal_width_input_ValueChanged"/>
<Slider x:Name="petal_length_input" Minimum="5" Maximum="100" Orientation="Horizontal" Grid.Row="2" Grid.Column="1" Width="200" ValueChanged="petal_length_input_ValueChanged"/>
<Slider x:Name="petal_width_input" Minimum="1" Maximum="50" Orientation="Horizontal" Grid.Row="3" Grid.Column="1" Width="200" ValueChanged="petal_width_input_ValueChanged"/>
</Grid>
<TextBlock x:Name="output" Text="Output:" FontSize="20" FontWeight="Bold" Grid.Row="3"/>
<Grid Grid.Row="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="output_subtitle" Text="Based on the information provided, the Iris type is:"/>
<TextBlock x:Name="model_output" Text="Model output" FontStyle="Italic" Grid.Column="1" Margin="10,0,0,0"/>
</Grid>
</Grid>
애플리케이션 컨트롤 만들기
애플리케이션 제어 코드 MainPage.xaml.cs
에는 앱을 실행하는 기본 메서드와 모델을 실행하고 출력을 실행하는 여러 단계가 포함됩니다.
- 이 자습서에서 이전에 만든
IrisModel
클래스의 새 개체를 인스턴스화합니다. - 모델의 이전 파트에서 빌드한
Evaluate()
메서드를 호출합니다. 이 방법은 꽃받침 길이, 꽃받침 너비, 꽃잎 길이 및 꽃잎 너비의 각 입력 매개 변수에 하나씩 네 번 적용됩니다.
앱은 기계 학습 예측 알고리즘을 기반으로 결과를 표시합니다.
- 애플리케이션 제어 코드를 만들려면
MainPage.xaml.cs
코드 파일을 두 번 클릭하고 다음 코드를 추가합니다.
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace Iris_Data_Analysis
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
private IrisModel _iris_model;
public MainPage()
{
this.InitializeComponent();
_iris_model = new IrisModel();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
_iris_model.Initialize();
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}
private void sepal_length_input_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
if (_iris_model != null)
{
_iris_model.Sepal_Length = (float)sepal_length_input.Value / 10.0f;
model_output.Text = _iris_model.Evaluate();
}
}
private void sepal_width_input_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
if (_iris_model != null)
{
_iris_model.Sepal_Width = (float)sepal_width_input.Value / 10.0f;
model_output.Text = _iris_model.Evaluate();
}
}
private void petal_length_input_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
if (_iris_model != null)
{
_iris_model.Petal_Length = (float)petal_length_input.Value / 10.0f;
model_output.Text = _iris_model.Evaluate();
}
}
private void petal_width_input_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
if (_iris_model != null)
{
_iris_model.Petal_Width = (float)petal_width_input.Value / 10.0f;
model_output.Text = _iris_model.Evaluate();
}
}
}
}
응용 프로그램 시작
이제 애플리케이션을 실행하고 결과를 볼 준비가 되었습니다.
개발자 모드를 사용하도록 설정하고, Visual Studio에서 애플리케이션을 테스트합니다. 위쪽 도구 모음의 드롭다운 메뉴가 Debug
로 설정되어 있는지 확인합니다. 디바이스가 64비트인 경우 솔루션 플랫폼을 x64로 변경하거나 32비트인 경우 x86으로 변경하여 로컬 컴퓨터에서 프로젝트를 실행합니다.
앱 GUI에는 필수 매개 변수의 입력을 변경하기 위한 네 개의 슬라이더가 포함되어 있습니다. 입력이 변경되면 예측 알고리즘을 기반으로 새 출력이 생성됩니다. 출력은 입력 슬라이더 아래에 표시됩니다.
꽃받침 길이 = 40mm, 꽃받침 너비 = 50, 꽃잎 길이 = 75, 꽃잎 너비 = 15의 입력이 지정되면 앱에서 버시컬러 붓꽃(Iris-versicolor) 종류의 입력이 생성된 것을 볼 수 있습니다!
요약
모델 만들기에서 성공적인 실행에 이르기까지 첫 번째 Windows Machine Learning 앱을 만들었습니다.
추가 리소스
이 자습서에서 언급한 항목에 대한 자세한 내용은 다음 리소스를 참조하세요.
- Windows ML 도구: Windows ML 대시보드 , WinMLRunner 및 mglen Windows ML 코드 생성기와 같은 도구에 대해 자세히 알아봅니다.
- ONNX 모델: ONNX 형식에 대해 자세히 알아봅니다.
- Windows ML 성능 및 메모리: Windows ML을 사용하여 앱 성능을 관리하는 방법에 대해 자세히 알아봅니다.
- Windows Machine Learning API 참조: Windows ML API의 세 가지 영역에 대해 자세히 알아봅니다.