ASP.NET Core Web API에 모델 배포

ASP.NET Core Web API를 사용하여 웹에서 미리 학습된 ML.NET 기계 학습 모델을 서비스하는 방법을 살펴봅니다. 웹 API를 통해 모델을 서비스하면 표준 HTTP 메서드를 통한 예측을 사용할 수 있습니다.

필수 조건

ASP.NET Core Web API 프로젝트 만들기

  1. Visual Studio 2022를 시작하고 새 프로젝트 만들기를 선택합니다.

  2. 새 프로젝트 만들기 대화 상자에서 다음을 수행합니다.

    • 검색 상자에 Web API를 입력합니다.
    • ASP.NET Core Web API 템플릿을 선택하고 다음을 선택합니다.
  3. 프로젝트 구성 대화 상자에서 다음을 수행합니다.

    • 프로젝트 이름을 SentimentAnalyticWebAPI로 지정합니다.
    • 다음을 선택합니다.
  4. 추가 정보 대화 상자에서 다음을 수행합니다.

    • 최상위 문 사용 안 함을 선택 취소합니다.
    • 만들기를 실행합니다.
  5. 다음 NuGet 패키지를 설치합니다.

    Visual Studio에서 NuGet 패키지를 설치하는 방법에 대한 자세한 내용은 Visual Studio에서 NuGet 패키지 설치 및 사용 가이드를 참조하세요.

ASP.NET Core Web API 프로젝트에 모델 추가

  1. 미리 빌드된 모델을 SentimentAnalyticWebAPI 프로젝트 디렉터리에 복사합니다.

  2. 모델 파일을 출력 디렉터리에 복사하도록 프로젝트를 구성합니다. 솔루션 탐색기에서:

    • 모델 Zip 파일을 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.
    • 고급 아래에서 출력 디렉터리에 복사 값을 변경된 내용만 복사로 변경합니다.

데이터 모델 만들기

모델 입력 및 출력의 스키마를 정의하려면 일부 클래스를 만들어야 합니다.

참고 항목

입력 및 출력 스키마 클래스의 속성은 모델 학습과 기계 학습 작업(회귀, 분류 등)에 사용되는 데이터 세트 열에 따라 달라집니다.

Program.cs 파일에서:

  1. 다음 using 명령문을 추가합니다.

    using Microsoft.ML.Data;
    using Microsoft.Extensions.ML;
    
  2. 파일 맨 아래에 다음 클래스를 추가합니다.

    모델 입력

    이 모델의 경우 입력에는 사용자 의견을 나타내는 문자열인 단일 속성 SentimentText가 포함되어 있습니다.

    public class ModelInput
    {
        public string SentimentText;
    }
    

    모델 출력

    모델이 입력을 평가하면 Sentiment, Probability, Score의 세 가지 속성을 사용하여 예측을 출력합니다. 이 경우 Sentiment는 사용자 댓글의 예측된 감정이고 ProbabilityScore는 예측에 대한 신뢰도 측정값입니다.

    public class ModelOutput
    {
        [ColumnName("PredictedLabel")]
        public bool Sentiment { get; set; }
    
        public float Probability { get; set; }
    
        public float Score { get; set; }
    }
    

애플리케이션에서 사용하기 위해 PredictionEnginePool 등록

단일 예측을 수행하려면 PredictionEngine을 만들어야 합니다. PredictionEngine는 스레드로부터 안전하지 않습니다. 또한 애플리케이션 내에서 필요한 모든 위치에서 인스턴스를 만들어야 합니다. 애플리케이션이 커지면 이 프로세스를 관리할 수 없게 됩니다. 성능 및 스레드 보안을 개선하려면 종속성 주입과 PredictionEnginePool 서비스를 함께 사용합니다. 이 서비스는 애플리케이션 전체에서 사용할 PredictionEngine 개체의 ObjectPool을 만듭니다.

다음 링크에서는 ASP.NET Core에서 종속성 주입에 대한 자세한 정보를 제공합니다.

다음 코드를 Program.cs 파일에 추가합니다.

builder.Services.AddPredictionEnginePool<ModelInput, ModelOutput>()
    .FromFile(modelName: "SentimentAnalysisModel", filePath: "sentiment_model.zip", watchForChanges: true);

개략적으로 이 코드는 애플리케이션을 수동으로 초기화하지 않고도 애플리케이션에서 요청할 때 나중에 사용할 수 있도록 자동으로 개체 및 서비스를 초기화합니다.

기계 학습 모델은 정적이지 않습니다. 새 학습 데이터를 사용할 수 있게 되면 모델을 다시 학습하고 다시 배포합니다. 최신 버전의 모델을 애플리케이션으로 가져오는 한 가지 방법은 애플리케이션을 시작하거나 다시 배포하는 것입니다. 그러나 이 경우 애플리케이션 가동 중지 시간이 발생합니다. PredictionEnginePool 서비스는 애플리케이션을 다시 시작하거나 다시 배포하지 않으면서 업데이트된 모델을 다시 로드하는 메커니즘을 제공합니다.

watchForChanges 매개 변수를 true로 설정하면 PredictionEnginePool은 파일 시스템 변경 알림을 수신 대기하고 파일이 변경될 때 이벤트를 발생시키는 FileSystemWatcher를 시작합니다. 그러면 PredictionEnginePool에서 모델을 자동으로 다시 로드하도록 지정할 수 있는 메시지가 표시됩니다.

모델은 modelName 매개 변수로 식별되므로 변경 시, 애플리케이션당 두 개 이상의 모델이 다시 로드될 수 있습니다.

또는 원격으로 저장된 모델을 사용하는 경우 FromUri 메서드를 사용할 수 있습니다. FromUri는 파일 변경 이벤트를 감시하지 않고, 원격 위치에서 변경 내용을 폴링합니다. 폴링 간격의 기본값은 5분입니다. 애플리케이션의 요구 사항에 따라 폴링 간격을 늘리거나 줄일 수 있습니다. 아래 코드 샘플에서 PredictionEnginePool은 1분마다 지정된 URI에 저장된 모델을 폴링합니다.

services.AddPredictionEnginePool<SentimentData, SentimentPrediction>()
  .FromUri(
      modelName: "SentimentAnalysisModel",
      uri:"https://github.com/dotnet/samples/raw/main/machine-learning/models/sentimentanalysis/sentiment_model.zip",
      period: TimeSpan.FromMinutes(1));

맵 예측 엔드포인트

들어오는 HTTP 요청을 처리하려면 엔드포인트를 만듭니다.

/ 엔드포인트를 다음으로 바꿉니다.

var predictionHandler =
    async (PredictionEnginePool<ModelInput, ModelOutput> predictionEnginePool, ModelInput input) =>
        await Task.FromResult(predictionEnginePool.Predict(modelName: "SentimentAnalysisModel", input));

app.MapPost("/predict", predictionHandler);

/predict 엔드포인트는 HTTP POST 요청을 수락하고 예측 엔진 풀을 사용하여 제공된 입력을 사용하여 예측을 반환합니다.

완료되면 Program.cs는 다음과 같아야 합니다.

using Microsoft.ML.Data;
using Microsoft.Extensions.ML;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddPredictionEnginePool<ModelInput, ModelOutput>()
    .FromFile(modelName: "SentimentAnalysisModel", filePath: "sentiment_model.zip", watchForChanges: true);

var app = builder.Build();

var predictionHandler =
    async (PredictionEnginePool<ModelInput, ModelOutput> predictionEnginePool, ModelInput input) =>
        await Task.FromResult(predictionEnginePool.Predict(modelName: "SentimentAnalysisModel", input));

app.MapPost("/predict", predictionHandler);

app.Run();

public class ModelInput
{
    public string SentimentText;
}

public class ModelOutput
{
    [ColumnName("PredictedLabel")]
    public bool Sentiment { get; set; }

    public float Probability { get; set; }

    public float Score { get; set; }
}

로컬로 Web API 테스트

이제 모든 것이 설정되면 애플리케이션을 테스트할 수 있습니다.

  1. 애플리케이션을 실행합니다.

  2. PowerShell을 열고 PORT가 애플리케이션이 수신 대기 중인 포트인 경우 다음 코드를 입력합니다.

    Invoke-RestMethod "https://localhost:<PORT>/predict" -Method Post -Body (@{SentimentText="This was a very bad steak"} | ConvertTo-Json) -ContentType "application/json"
    

    성공하면 출력이 아래 텍스트와 같이 표시됩니다.

    sentiment probability score
    --------- ----------- -----
    False         0.5     0
    

축하합니다! ASP.NET Core Web API를 사용하여 인터넷을 통해 예측을 수행하도록 모델을 제공했습니다.

다음 단계