자습서: ML .NET에서 다중 클래스 분류를 사용하여 지원 문제 분류

이 샘플 자습서에서는 ML.NET을 사용하여 Visual Studio에서 C#을 사용하는 .NET Core 콘솔 애플리케이션을 통해 GitHub 문제를 분류하고 영역 레이블을 예측하는 모델을 학습하는 방법에 대해 설명합니다.

이 자습서에서는 다음과 같은 작업을 수행하는 방법을 살펴봅니다.

  • 데이터 준비
  • 데이터 변환
  • 모델 학습
  • 모델 평가
  • 학습된 모델을 통해 예측
  • 로드된 모델을 통해 배포 및 예측

dotnet/samples 리포지토리에서 이 자습서의 소스 코드를 찾을 수 있습니다.

사전 요구 사항

콘솔 애플리케이션 만들기

프로젝트 만들기

  1. "GitHubIssueClassification"이라는 C# 콘솔 애플리케이션을 만듭니다. 다음을 선택합니다.

  2. 사용할 프레임워크로 .NET 7을 선택합니다. 만들기를 선택합니다.

  3. 프로젝트에서 Data 디렉터리를 만들어 데이터 집합 파일을 저장합니다.

    솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가>새 폴더를 선택합니다. "데이터"를 입력하고 Enter 키를 누릅니다.

  4. 프로젝트에서 Models 디렉터리를 만들어 모델을 저장합니다.

    솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가>새 폴더를 선택합니다. "모델"을 입력하고 Enter 키를 누릅니다.

  5. Microsoft.ML NuGet 패키지를 설치합니다.

    참고

    이 샘플에서는 별도로 지정하지 않은 한 언급된 NuGet 패키지의 최신 안정화 버전을 사용합니다.

    솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 NuGet 패키지 관리를 선택합니다. "nuget.org"를 패키지 소스로 선택하고, [찾아보기] 탭을 선택하고, Microsoft.ML을 검색하고 설치 단추를 선택합니다. 변경 내용 미리 보기 대화 상자에서 확인 단추를 선택한 다음, 나열된 패키지의 사용 조건에 동의하는 경우 라이선스 승인 대화 상자에서 동의함 단추를 선택합니다.

데이터 준비

  1. issues_train.tsvissues_test.tsv 데이터 세트를 다운로드하고 이전에 만든 데이터 폴더에 저장합니다. 첫 번째 데이터 세트는 기계 학습 모델을 교육하고 두 번째 데이터 세트는 모델이 얼마나 정확한지 평가하는 데 사용할 수 있습니다.

  2. 솔루션 탐색기 각 *.tsv 파일을 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다. 고급 아래에서 출력 디렉터리에 복사 값을 변경된 내용만 복사로 변경합니다.

클래스 만들기 및 경로 정의

Program.cs 파일 맨 위에 다음 추가 using 문을 추가합니다.

using Microsoft.ML;
using GitHubIssueClassification;

최근에 다운로드한 파일의 경로와 MLContext,DataViewPredictionEngine의 글로벌 변수가 포함될 세 개의 글로벌 필드를 만듭니다.

  • _trainDataPath에는 모델을 학습시키는 데 사용되는 데이터 세트의 경로가 포함됩니다.
  • _testDataPath에는 모델을 평가하는 데 사용되는 데이터 세트의 경로가 포함됩니다.
  • _modelPath에는 학습된 모델이 저장되는 경로가 포함됩니다.
  • _mlContext는 처리 컨텍스트를 제공하는 MLContext입니다.
  • _trainingDataView는 학습 데이터 세트를 처리하는 데 사용되는 IDataView입니다.
  • _predEngine은 단일 예측에 사용되는 PredictionEngine<TSrc,TDst>입니다.

using 문 바로 아래에 다음 코드를 추가하여 해당 경로와 다른 변수를 지정합니다.

string _appPath = Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) ?? ".";
string _trainDataPath = Path.Combine(_appPath, "..", "..", "..", "Data", "issues_train.tsv");
string _testDataPath = Path.Combine(_appPath, "..", "..", "..", "Data", "issues_test.tsv");
string _modelPath = Path.Combine(_appPath, "..", "..", "..", "Models", "model.zip");

MLContext _mlContext;
PredictionEngine<GitHubIssue, IssuePrediction> _predEngine;
ITransformer _trainedModel;
IDataView _trainingDataView;

입력 데이터 및 예측에 대한 일부 클래스를 만듭니다. 새 클래스를 프로젝트에 추가합니다.

  1. 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가>새 항목을 선택합니다.

  2. 새 항목 추가 대화 상자에서 클래스를 선택하고 이름 필드를 GitHubIssueData.cs로 변경합니다. 그런 다음, 추가 단추를 선택합니다.

    GitHubIssueData.cs 파일이 코드 편집기에서 열립니다. 다음 using 문을 GitHubIssueData.cs의 맨 위에 추가합니다.

using Microsoft.ML.Data;

기존 클래스 정의를 제거하고 두 개의 클래스 GitHubIssueIssuePrediction이 있는 다음 코드를 GitHubIssueData.cs 파일에 추가합니다.

public class GitHubIssue
{
    [LoadColumn(0)]
    public string? ID { get; set; }
    [LoadColumn(1)]
    public string? Area { get; set; }
    [LoadColumn(2)]
    public required string Title { get; set; }
    [LoadColumn(3)]
    public required string Description { get; set; }
}

public class IssuePrediction
{
    [ColumnName("PredictedLabel")]
    public string? Area;
}

label은 예측할 열입니다. 식별된 Features는 레이블 예측을 위해 모델에 제공하는 입력입니다.

LoadColumnAttribute를 사용하여 데이터 세트에서 원본 열의 인덱스를 지정합니다.

GitHubIssue는 다음 입력 데이터 세트 클래스이며 다음 String 필드를 포함합니다.

  • 첫 번째 열 ID(GitHub 문제 ID)
  • 두 번째 열 Area(학습 예측)
  • 세 번째 열 Title(GitHub 문제 제목)은 Area 예측에 사용되는 첫 번째 feature입니다.
  • 네 번째 열은 를 예측하는 데 사용되는 두 번째 featureDescription 입니다.Area

IssuePrediction은 모델이 학습된 후 예측에 사용되는 클래스입니다. 여기에는 단일 string(Area) 및 PredictedLabelColumnName 특성이 포함됩니다. PredictedLabel은 예측 및 평가 중에 사용됩니다. 평가를 위해 학습 데이터가 있는 입력, 예측 값 및 모델이 사용됩니다.

모든 ML.NET 작업은 MLContext 클래스에서 시작됩니다. mlContext를 초기화하면 모델 생성 워크플로 개체 간에 공유할 수 있는 새 ML.NET 환경이 생성됩니다. 개념적으로 Entity FrameworkDBContext와 유사합니다.

변수 초기화

여러 학습에서 _mlContext 반복 가능/결정적 결과를 위해 임의 시드(seed: 0)를 사용하여 의 MLContext 새 instance 사용하여 전역 변수를 초기화합니다. Console.WriteLine("Hello World!") 줄을 다음 코드로 바꿉니다.

_mlContext = new MLContext(seed: 0);

데이터 로드

ML.NET은 숫자 또는 텍스트 표 형식 데이터를 설명하는 효율적인 방법으로 IDataView 인터페이스를 유연하게 사용합니다. IDataView는 텍스트 파일을 또는 실시간으로 로드할 수 있습니다(예: SQL 데이터베이스 또는 로그 파일).

파이프라인에 _trainingDataView 사용하기 위해 전역 변수를 초기화하고 로드하려면 초기화 후 mlContext 다음 코드를 추가합니다.

_trainingDataView = _mlContext.Data.LoadFromTextFile<GitHubIssue>(_trainDataPath,hasHeader: true);

LoadFromTextFile()은 데이터 스키마를 정의하고 파일에서 읽습니다. 데이터 경로 변수를 가져와서 IDataView를 반환합니다.

LoadFromTextFile() 메서드 호출 아래에 다음 코드를 추가합니다.

var pipeline = ProcessData();

ProcessData 메서드는 다음 작업을 실행합니다.

  • 데이터를 추출하고 변환합니다.
  • 처리 파이프라인을 반환합니다.

다음 코드를 사용하여 Program.cs 파일의 맨 아래에 ProcessData 메서드를 만듭니다.

IEstimator<ITransformer> ProcessData()
{

}

기능 추출 및 데이터 변환

GitHubIssue에 대한 영역 GitHub 레이블을 예측하기 위해 MapValueToKey() 메서드를 사용하여 Area 열을 숫자 키 형식 Label 열로 변환하고(분류 알고리즘에서 허용하는 형식) 새 데이터 세트 열로 추가합니다.

var pipeline = _mlContext.Transforms.Conversion.MapValueToKey(inputColumnName: "Area", outputColumnName: "Label")

다음으로, 텍스트(TitleDescription) 열을 TitleFeaturizedDescriptionFeaturized 각각에서 숫자 벡터로 변환하는 mlContext.Transforms.Text.FeaturizeText를 호출합니다. 다음 코드를 사용하여 두 열에 대한 기능화(featurization)를 파이프라인에 추가합니다.

.Append(_mlContext.Transforms.Text.FeaturizeText(inputColumnName: "Title", outputColumnName: "TitleFeaturized"))
.Append(_mlContext.Transforms.Text.FeaturizeText(inputColumnName: "Description", outputColumnName: "DescriptionFeaturized"))

데이터 준비의 마지막 단계에서는 Concatenate() 메서드를 사용하여 모든 기능 열을 Features 열에 결합합니다. 기본적으로, 학습 알고리즘은 Features 열의 기능만 처리합니다. 다음 코드를 사용하여 이 변환을 파이프라인에 추가합니다.

.Append(_mlContext.Transforms.Concatenate("Features", "TitleFeaturized", "DescriptionFeaturized"))

다음으로, AppendCacheCheckpoint를 추가하여 DataView를 캐시합니다. 따라서 해당 캐시를 사용하여 데이터를 여러 번 반복하면 다음 코드를 사용하는 것처럼 성능이 향상될 수 있습니다.

.AppendCacheCheckpoint(_mlContext);

경고

작거나 중간 규모의 데이터 세트에서는 AppendCacheCheckpoint를 사용하여 학습 시간을 단축하세요. 규모가 매우 큰 데이터 세트를 다룰 때는 사용하지 마세요(AppendCacheCheckpoint()를 제거).

ProcessData 메서드의 끝에 파이프라인을 반환합니다.

return pipeline;

이 단계는 전처리/기능화를 처리합니다. ML.NET에서 사용 가능한 추가 구성 요소를 사용하면 모델에서 더 나은 결과를 얻을 수 있습니다.

모델 빌드 및 학습

ProcessData() 메서드 호출 다음의 코드 줄로 다음 BuildAndTrainModel 메서드 호출을 추가합니다.

var trainingPipeline = BuildAndTrainModel(_trainingDataView, pipeline);

BuildAndTrainModel 메서드는 다음 작업을 실행합니다.

  • 학습 알고리즘 클래스를 만듭니다.
  • 모델을 학습시킵니다.
  • 학습 데이터를 기반으로 영역을 예측합니다.
  • 모델을 반환합니다.

다음 코드를 사용하여 ProcessData() 메서드 선언 바로 뒤에 BuildAndTrainModel 메서드를 만듭니다.

IEstimator<ITransformer> BuildAndTrainModel(IDataView trainingDataView, IEstimator<ITransformer> pipeline)
{

}

분류 작업 정보

분류는 데이터를 사용하여 데이터 항목 또는 행의 범주, 형식 또는 클래스를 확인하는 기계 학습 작업으로, 보통은 다음 형식 중 하나입니다.

  • 이진: A 또는 B.
  • 다중 클래스: 단일 모델을 사용하여 예측할 수 있는 여러 범주.

이러한 유형의 문제에는 다중 클래스 분류 학습 알고리즘을 사용합니다. 문제 범주 예측이 단 2개(이진)가 아닌 여러 범주(다중 클래스) 중 하나일 수 있기 때문입니다.

BuildAndTrainModel()의 첫 번째 코드 줄로 다음을 추가하여 데이터 변환 정의에 기계 학습 알고리즘을 추가합니다.

var trainingPipeline = pipeline.Append(_mlContext.MulticlassClassification.Trainers.SdcaMaximumEntropy("Label", "Features"))
        .Append(_mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));

SdcaMaximumEntropy는 다중 클래스 분류 학습 알고리즘입니다. 이것은 pipeline에 추가되고 기록 데이터에서 학습할 기능화된 Title, Description(Features) 및 Label 입력 매개 변수를 수락합니다.

모델 학습

모델을 splitTrainSet 데이터에 맞추고 BuildAndTrainModel() 메서드에서 다음 줄의 코드로 다음 항목을 추가하여 학습된 모델을 반환합니다.

_trainedModel = trainingPipeline.Fit(trainingDataView);

Fit() 메서드는 데이터 세트를 변환하고 학습을 적용하여 모델을 학습합니다.

PredictionEngine은 데이터의 단일 인스턴스를 전달한 다음, 이 단일 데이터 인스턴스에 대한 예측을 수행할 수 있는 편리한 API입니다. 이 항목을 BuildAndTrainModel() 메서드에서 다음 줄로 추가합니다.

_predEngine = _mlContext.Model.CreatePredictionEngine<GitHubIssue, IssuePrediction>(_trainedModel);

학습된 모델을 통해 예측

GitHubIssue의 인스턴스를 만들어 GitHub 문제를 추가하여 Predict 메서드에서 학습된 모델의 예측을 테스트합니다.

GitHubIssue issue = new GitHubIssue() {
    Title = "WebSockets communication is slow in my machine",
    Description = "The WebSockets communication used under the covers by SignalR looks like is going slow in my development machine.."
};

Predict() 함수를 사용하여 단일 데이터 행에 대한 예측을 수행합니다.

var prediction = _predEngine.Predict(issue);

모델 사용: 예측 결과

결과를 공유하고 이에 따라 작업을 수행하기 위해 GitHubIssue 및 해당 Area 레이블 예측을 표시합니다. 다음 Console.WriteLine() 코드를 사용하여 결과 표시를 만듭니다.

Console.WriteLine($"=============== Single Prediction just-trained-model - Result: {prediction.Area} ===============");

평가에 사용하기 위해 학습된 모델 반환

BuildAndTrainModel 메서드의 끝에 모델을 반환합니다.

return trainingPipeline;

모델 평가

이제 모델을 만들고 학습시켰으므로 품질 보증 및 유효성 검사를 위해 다른 데이터 세트를 사용하여 평가해야 합니다. Evaluate 메서드에서는 BuildAndTrainModel에서 만들어진 모델을 전달하여 평가합니다. 다음 코드와 같이 BuildAndTrainModel 바로 뒤에 Evaluate 메서드를 만듭니다.

void Evaluate(DataViewSchema trainingDataViewSchema)
{

}

Evaluate 메서드는 다음 작업을 실행합니다.

  • 테스트 데이터 세트를 로드합니다.
  • 다중 클래스 평가자를 만듭니다.
  • 모델을 평가하고 메트릭을 만듭니다.
  • 메트릭을 표시합니다.

다음 코드를 사용하여 BuildAndTrainModel 메서드 호출 바로 아래에 새 메서드 호출을 추가합니다.

Evaluate(_trainingDataView.Schema);

앞의 학습 데이터 세트에서처럼 Evaluate 메서드에 다음 코드를 추가하여 테스트 데이트 세트를 로드합니다.

var testDataView = _mlContext.Data.LoadFromTextFile<GitHubIssue>(_testDataPath,hasHeader: true);

Evaluate() 메서드는 지정된 데이터 세트를 사용하여 모델에 대한 품질 메트릭을 계산합니다. 다중 클래스 분류 평가자가 계산한 전체 메트릭을 포함하는 MulticlassClassificationMetrics 개체를 반환합니다. 모델의 품질을 확인하기 위해 메트릭을 표시하려면 먼저 해당 메트릭을 가져와야 합니다. 기계 학습 _trainedModel 글로벌 변수(ITransformer)의 Transform() 메서드를 사용하여 기능을 입력하고 예측을 반환합니다. Evaluate 메서드에 아래 코드를 다음 줄로 추가합니다.

var testMetrics = _mlContext.MulticlassClassification.Evaluate(_trainedModel.Transform(testDataView));

다중 클래스 분류에 대한 다음 메트릭이 계산됩니다.

  • 마이크로 정확도 - 모든 샘플 클래스 쌍은 정확도 메트릭에 동일하게 기여합니다. 마이크로 정확도를 가능한 한 1에 가깝게 합니다.

  • 매크로 정확도 - 모든 클래스 정확도 메트릭에 동일하게 기여합니다. 소수 클래스는 큰 클래스와 같은 가중치를 부여받습니다. 매크로 정확도를 가능한 한 1에 가깝게 합니다.

  • 로그 손실 - 로그 손실을 참조하세요. 로그 손실을 가능한 한 0에 가깝게 합니다.

  • 로그 손실 감소 - [-inf, 1.00]의 범위입니다. 여기서 1.00은 완벽한 예측이고 0은 평균 예측을 나타냅니다. 로그 손실 감소를 가능한 한 1에 가깝게 합니다.

모델 유효성 검사에 대한 메트릭 표시

다음 코드를 사용하여 메트릭을 표시하고, 결과를 공유한 다음, 작업을 수행합니다.

Console.WriteLine($"*************************************************************************************************************");
Console.WriteLine($"*       Metrics for Multi-class Classification model - Test Data     ");
Console.WriteLine($"*------------------------------------------------------------------------------------------------------------");
Console.WriteLine($"*       MicroAccuracy:    {testMetrics.MicroAccuracy:0.###}");
Console.WriteLine($"*       MacroAccuracy:    {testMetrics.MacroAccuracy:0.###}");
Console.WriteLine($"*       LogLoss:          {testMetrics.LogLoss:#.###}");
Console.WriteLine($"*       LogLossReduction: {testMetrics.LogLossReduction:#.###}");
Console.WriteLine($"*************************************************************************************************************");

모델을 파일에 저장

모델이 만족스러운 경우 나중에 또는 다른 애플리케이션에서 예측을 수행하기 위해 모델을 파일에 저장합니다. Evaluate 메서드에 다음 코드를 추가합니다.

SaveModelAsFile(_mlContext, trainingDataViewSchema, _trainedModel);

Evaluate 메서드 아래 SaveModelAsFile 메서드를 만듭니다.

void SaveModelAsFile(MLContext mlContext,DataViewSchema trainingDataViewSchema, ITransformer model)
{

}

SaveModelAsFile 메서드에 다음 코드를 추가합니다. 이 코드에서는 Save 메서드를 사용하여 학습된 모델을 직렬화하고 zip 파일로 저장합니다.

mlContext.Model.Save(model, trainingDataViewSchema, _modelPath);

모델을 통해 배포 및 예측

다음 코드를 사용하여 Evaluate 메서드 호출 바로 아래에 새 메서드 호출을 추가합니다.

PredictIssue();

다음 코드를 사용하여 Evaluate 메서드 바로 뒤에 (또한 SaveModelAsFile 메서드 바로 앞에) PredictIssue 메서드를 만듭니다.

void PredictIssue()
{

}

PredictIssue 메서드는 다음 작업을 실행합니다.

  • 저장된 모델 로드
  • 테스트 데이터의 단일 문제를 만듭니다.
  • 테스트 데이터를 기반으로 영역을 예측합니다.
  • 보고를 위해 테스트 데이터 및 예측을 결합합니다.
  • 예측 결과를 표시합니다.

다음 코드를 PredictIssue 메서드에 추가하여 저장된 모델을 애플리케이션에 로드합니다.

ITransformer loadedModel = _mlContext.Model.Load(_modelPath, out var modelInputSchema);

GitHubIssue의 인스턴스를 만들어 GitHub 문제를 추가하여 Predict 메서드에서 학습된 모델의 예측을 테스트합니다.

GitHubIssue singleIssue = new GitHubIssue() { Title = "Entity Framework crashes", Description = "When connecting to the database, EF is crashing" };

이전에 수행한 것처럼 다음 코드로 PredictionEngine 인스턴스를 만듭니다.

_predEngine = _mlContext.Model.CreatePredictionEngine<GitHubIssue, IssuePrediction>(loadedModel);

PredictionEngine은 데이터의 단일 인스턴스에 대한 예측을 수행할 수 있는 편리한 API입니다. PredictionEngine는 스레드로부터 안전하지 않습니다. 단일 스레드 또는 프로토타입 환경에서 사용할 수 있습니다. 프로덕션 환경에서 성능 및 스레드 보안을 개선하려면 PredictionEnginePool 서비스를 사용합니다. 이 서비스는 애플리케이션 전체에서 사용할 PredictionEngine 개체의 ObjectPool을 만듭니다. ASP.NET Core Web API에서 PredictionEnginePool을 사용하는 방법에 대한 이 가이드를 참조하세요.

참고

PredictionEnginePool 서비스 확장은 현재 미리 보기 상태입니다.

PredictionEngine을 사용하여 예측을 위해 다음 코드를 PredictIssue 메서드에 추가하여 영역 GitHub 레이블을 예측합니다.

var prediction = _predEngine.Predict(singleIssue);

예측에 로드된 모델 사용

문제를 분류하고 이에 따라 조치를 취하기 위해 Area를 표시합니다. 다음 Console.WriteLine() 코드를 사용하여 결과 표시를 만듭니다.

Console.WriteLine($"=============== Single Prediction - Result: {prediction.Area} ===============");

결과

다음과 같은 결과가 나타나야 합니다. 파이프라인이 처리할 때 메시지를 표시합니다. 경고 또는 메시지 처리를 확인할 수 있습니다. 이해하기 쉽도록 이러한 메시지는 다음 결과에서 제거되었습니다.

=============== Single Prediction just-trained-model - Result: area-System.Net ===============
*************************************************************************************************************
*       Metrics for Multi-class Classification model - Test Data
*------------------------------------------------------------------------------------------------------------
*       MicroAccuracy:    0.738
*       MacroAccuracy:    0.668
*       LogLoss:          .919
*       LogLossReduction: .643
*************************************************************************************************************
=============== Single Prediction - Result: area-System.Data ===============

지금까지 이제 GitHub 문제의 영역 레이블을 분류하고 예측하기 위한 기계 학습 모델을 성공적으로 빌드했습니다. dotnet/samples 리포지토리에서 이 자습서의 소스 코드를 찾을 수 있습니다.

다음 단계

본 자습서에서는 다음 작업에 관한 방법을 학습했습니다.

  • 데이터 준비
  • 데이터 변환
  • 모델 학습
  • 모델 평가
  • 학습된 모델을 통해 예측
  • 로드된 모델을 통해 배포 및 예측

다음 자습서로 이동하여 자세히 알아보기