ASP.NET Core Web API でのモデルのデプロイ

ASP.NET Core Web API を使用して、事前トレーニング済みの ML.NET 機械学習モデルを Web 上に提供する方法について説明します。 Web API 経由でモデルを提供すると、標準の HTTP メソッドによる予測が可能になります。

必須コンポーネント

ASP.NET Core Web API プロジェクトを作成する

  1. Visual Studio 2022 を開始し、 [新しいプロジェクトの作成] を選択します。

  2. [新しいプロジェクトの作成] ダイアログで次を行います。

    • 検索ボックスに、Web API と入力します。
    • [ASP.NET Core Web API] テンプレートを選択し、 [次へ] を選択します。
  3. [新しいプロジェクトの構成] ダイアログで、次のようにします。

    • プロジェクトの名前を SentimentAnalysisWebAPI にします。
    • [次へ] を選択します。
  4. [追加情報] ダイアログで、次を行います。

    • [最上位レベルのステートメントを使用しない] をオフにします。
    • [作成] を選択します
  5. 次の NuGet パッケージをインストールします。

    Visual Studio での NuGet パッケージのインストールの詳細については、Visual Studio での NuGet パッケージのインストールと使用に関するガイドを参照してください。

モデルを ASP.NET Core Web API プロジェクトに追加する

  1. 事前構築済みのモデルを SentimentAnalysisWebAPI プロジェクト ディレクトリにコピーします。

  2. モデル ファイルが出力ディレクトリにコピーされるようにプロジェクトを構成します。 ソリューション エクスプローラーで、次の手順を実行します。

    • モデルの zip ファイルを右クリックし、[プロパティ] を選択します。
    • [詳細設定] で、[出力ディレクトリにコピー] の値を [新しい場合はコピーする] に変更します。

データモデルを作成する

モデルの入出力のスキーマを定義するには、いくつかのクラスを作成する必要があります。

注意

入出力スキーマ クラスのプロパティは、モデルのトレーニングに使用されるデータセット列と機械学習タスク (回帰、分類など) によって異なります。

Program.cs ファイルで、次の手順を実行します。

  1. 次の using ステートメントを追加します。

    using Microsoft.ML.Data;
    using Microsoft.Extensions.ML;
    
  2. ファイルの下部に次のクラスを追加します。

    モデルの入力

    このモデルについては、入力にユーザー コメントを表す文字列である 1 つのプロパティ SentimentText が含まれています。

    public class ModelInput
    {
        public string SentimentText;
    }
    

    モデルの出力

    モデルで入力が評価されると、SentimentProbabilityScore という 3 つのプロパティが備わった予測が出力されます。 この場合、Sentiment はユーザー コメントの予測センチメントであり、ProbabilityScore は予測の信頼度の尺度です。

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

アプリケーションで使用する PredictionEnginePool を登録する

1 つの予測を作成するには、PredictionEngine を作成する必要があります。 PredictionEngine はスレッド セーフではありません。 さらに、アプリケーション内で必要なすべての場所にそのインスタンスを作成する必要があります。 アプリケーションの規模が拡大すると、このプロセスが管理不能になる可能性があります。 パフォーマンスとスレッド セーフを向上させるには、依存性の挿入と PredictionEnginePool サービスを組み合わせて使用します。これにより、アプリケーション全体で使用する PredictionEngine オブジェクトの ObjectPool が作成されます。

ASP.NET Core での依存関係の挿入については、リンク先で提供されている詳しい情報を確認してください。

Program.cs ファイルに次のコードを追加します。

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

大まかに言えば、オブジェクトとサービスがアプリケーションによって要求されたときに、このコードでは、後で使用できるように手動ではなく自動的に初期化が実行されます。

機械学習モデルは静的ではありません。 新しいトレーニング データが使用可能になると、モデルの再トレーニングと再展開が行われます。 ご自分のアプリケーションで、モデルの最新バージョンが使用されるようにする 1 つの方法に、アプリケーションの再起動または再展開があります。 ただし、これによってアプリケーションのダウンタイムが発生します。 PredictionEnginePool サービスには、アプリケーションを再起動したり、再展開せずに、更新されたモデルを再度読み込むメカニズムが用意されています。

watchForChanges パラメーターを true に設定すると、PredictionEnginePool では、ファイル システムの変更通知をリッスンし、ファイルに変更があったときにイベントを発生させる FileSystemWatcher が開始されます。 これにより、モデルを自動的に再度読み込む PredictionEnginePool のプロンプトが表示されます。

モデルは modelName パラメーターによって識別されるため、変更時にアプリケーションごとに複数のモデルを再度読み込むことができます。

ヒント

また、リモートに格納されているモデルを操作するときは FromUri メソッドを使用できます。 FromUri では、ファイルの変更イベントを監視するのではなく、リモートの場所の変更をポーリングします。 ポーリング間隔は既定で 5 分に設定されています。 アプリケーションの要件に基づいてポーリング間隔を増減することができます。 次のコード サンプルでは、PredictionEnginePool は、指定された URI に格納されているモデルを 1 分ごとにポーリングします。

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 を使用して、インターネット経由で予測を実行するモデルを正常に提供できました。

次の手順