チュートリアル: ML.NET で事前トレーニング済みの TensorFlow モデルを使用して映画レビューのセンチメントを分析する
このチュートリアルでは、事前トレーニング済みの TensorFlow モデルを使用して、Web サイトのセンチメントを分類する方法について示します。 センチメントの 2 項分類子は、Visual Studio を使用して開発された C# コンソール アプリケーションです。
このチュートリアルで使用される TensorFlow モデルは、IMDB データベースの映画レビューを使用してトレーニングされました。 アプリケーションの開発が完了すると、映画レビューのテキストを入力できるようになり、レビューに肯定的または否定的なセンチメントが含まれるかどうかがアプリケーションによって通知されます。
このチュートリアルでは、次の作業を行う方法について説明します。
- 事前トレーニング済みの TensorFlow モデルを読み込む
- Web サイトのコメント テキストをモデルに適したフィーチャーに変換する
- モデルを使用して予測する
このチュートリアルのソース コードは dotnet/samples リポジトリで確認できます。
必須コンポーネント
- .NET デスクトップ開発ワークロードがインストールされた Visual Studio 2022。
セットアップ
アプリケーションを作成する
"TextClassificationTF" という名前の C# コンソール アプリケーションを作成します。 [次へ] をクリックします。
使用するフレームワークとして [.NET 6] を選択します。 [作成] ボタンをクリックします。
データ セット ファイルを保存するために、プロジェクトに Data という名前のディレクトリを作成します。
Microsoft.ML NuGet パッケージをインストールします。
注意
このサンプルでは、特に明記されていない限り、記載されている最新の安定バージョンの NuGet パッケージを使用します。
ソリューション エクスプローラーで、プロジェクトを右クリックし、 [NuGet パッケージの管理] を選択します。 パッケージ ソースとして "nuget.org" を選択してから、 [参照] タブを選択します。Microsoft.ML を検索し、目的のパッケージを選択して、 [インストール] ボタンを選択します。 選択したパッケージのライセンス条項に同意してインストールを続行します。 Microsoft.ML.TensorFlow、Microsoft.ML.SampleUtils、および SciSharp.TensorFlow.Redist に対して、これらの手順を繰り返します。
TensorFlow モデルをプロジェクトに追加する
Note
このチュートリアルのモデルは、dotnet/machinelearning-testdata GitHub リポジトリにあります。 このモデルは TensorFlow SavedModel 形式です。
sentiment_model ZIP ファイルをダウンロードして解凍します。
ZIP ファイルには次のものが含まれています。
saved_model.pb
: TensorFlow モデルそのもの。 このモデルは、IMDB レビューの文字列内のテキストを表すフィーチャーの固定長 (サイズ 600) の整数配列を受け取り、合計が 1 になる 2 つの確率を出力します。これは、入力レビューに肯定的センチメントが含まれる確率と、入力レビューに否定的センチメントが含まれる確率です。imdb_word_index.csv
: 個々の単語から整数値へのマッピング。 マッピングは、TensorFlow モデル用に入力機能を作成するために使用されます。
最深部の
sentiment_model
ディレクトリの内容を TextClassificationTF プロジェクトのsentiment_model
ディレクトリにコピーします。 次の画像に示すように、このディレクトリには、このチュートリアルに必要なモデルと追加のサポート ファイルが含まれています。ソリューション エクスプローラーで、
sentiment_model
ディレクトリとサブディレクトリ内の各ファイルを右クリックし、 [プロパティ] を選択します。 [詳細設定] で、 [出力ディレクトリにコピー] の値を [新しい場合はコピーする] に変更します。
using ステートメントとグローバル変数を追加する
次に示す追加の
using
ステートメントを Program.cs ファイルの先頭に追加します。using Microsoft.ML; using Microsoft.ML.Data; using Microsoft.ML.Transforms;
保存されたモデルのファイル パスを保持するために、using ステートメントの直後にグローバル変数を作成します。
string _modelPath = Path.Combine(Environment.CurrentDirectory, "sentiment_model");
_modelPath
は、トレーニング済みモデルのファイル パスです。
データのモデル化
映画レビューは自由形式のテキストです。 アプリケーションでは、テキストがさまざまな個別のステージでモデルによって想定される入力形式に変換されます。
最初にテキストを別々の単語に分割し、指定されたマッピング ファイルを使用して各単語を整数のエンコードにマップします。 この変換の結果、文章内の単語数に応じた長さの可変長の整数配列になります。
プロパティ | [値] | 種類 |
---|---|---|
ReviewText | この映画は本当に良い | string |
VariableLengthFeatures | 14、22、9、66、78、... | int[] |
可変長フィーチャーの配列は、固定長が 600 に変更されます。 これは、TensorFlow モデルで想定される長さです。
プロパティ | [値] | 種類 |
---|---|---|
ReviewText | この映画は本当に良い | string |
VariableLengthFeatures | 14、22、9、66、78、... | int[] |
フィーチャー | 14、22、9、66、78、... | int[600] |
Program.cs ファイルの下部に入力データのクラスを作成します。
/// <summary> /// Class to hold original sentiment data. /// </summary> public class MovieReview { public string? ReviewText { get; set; } }
入力データ クラス (
MovieReview
) には、ユーザー コメント (ReviewText
) 用のstring
があります。次の
MovieReview
クラスの後に、可変長フィーチャー用のクラスを作成します。/// <summary> /// Class to hold the variable length feature vector. Used to define the /// column names used as input to the custom mapping action. /// </summary> public class VariableLength { /// <summary> /// This is a variable length vector designated by VectorType attribute. /// Variable length vectors are produced by applying operations such as 'TokenizeWords' on strings /// resulting in vectors of tokens of variable lengths. /// </summary> [VectorType] public int[]? VariableLengthFeatures { get; set; } }
VariableLengthFeatures
プロパティには、ベクターとして指定する VectorType 属性が含まれます。 ベクター要素はすべて同じ型である必要があります。 列が多いデータ セットでは、複数の列を 1 つのベクターとして読み込むことで、データ変換を適用するときのデータ パスの数が減少します。このクラスは、
ResizeFeatures
アクションで使用されます。 プロパティの名前 (この場合は 1 つのみ) を使用して、カスタム マッピング アクションへの入力として使用できる DataView 内の列を示します。次の
VariableLength
クラスの後に、固定長フィーチャー用のクラスを作成します。/// <summary> /// Class to hold the fixed length feature vector. Used to define the /// column names used as output from the custom mapping action, /// </summary> public class FixedLength { /// <summary> /// This is a fixed length vector designated by VectorType attribute. /// </summary> [VectorType(Config.FeatureLength)] public int[]? Features { get; set; } }
このクラスは、
ResizeFeatures
アクションで使用されます。 プロパティの名前 (この場合は 1 つのみ) を使用して、カスタム マッピング アクションへの出力として使用できる DataView 内の列を示します。プロパティ
Features
の名前は、TensorFlow モデルによって決定されることに注意してください。 このプロパティ名は変更できません。次の
FixedLength
クラスの後に、予測用のクラスを作成します。/// <summary> /// Class to contain the output values from the transformation. /// </summary> public class MovieReviewSentimentPrediction { [VectorType(2)] public float[]? Prediction { get; set; } }
MovieReviewSentimentPrediction
はモデルのトレーニング後に使用される予測クラスです。MovieReviewSentimentPrediction
には、1 つのfloat
配列 (Prediction
) とVectorType
属性が含まれます。特徴ベクトルの長さなどの構成値を保持する別のクラスを作成します。
static class Config { public const int FeatureLength = 600; }
MLContext、検索ディクショナリ、フィーチャーのサイズを変更するアクションを作成する
MLContext クラスは、すべての ML.NET 操作の始点です。 mlContext
を初期化することで、モデル作成ワークフローのオブジェクト間で共有できる新しい ML.NET 環境が作成されます。 これは Entity Framework における DBContext
と概念的には同じです。
Console.WriteLine("Hello World!")
の行を、mlContext 変数を宣言して初期化する次のコードに置き換えます。MLContext mlContext = new MLContext();
次の表に示すように、
LoadFromTextFile
メソッドを使用して単語を整数としてエンコードするディクショナリを作成し、ファイルからマッピング データを読み込みます。単語 インデックス 子供向け 362 必要 181 不適切 355 効果 302 感覚 547 次のコードを追加して、検索マップを作成します。
var lookupMap = mlContext.Data.LoadFromTextFile(Path.Combine(_modelPath, "imdb_word_index.csv"), columns: new[] { new TextLoader.Column("Words", DataKind.String, 0), new TextLoader.Column("Ids", DataKind.Int32, 1), }, separatorChar: ',' );
Action
を追加して、可変長単語の整数配列のサイズを固定サイズの整数配列に変更します。次のコード行を使用します。Action<VariableLength, FixedLength> ResizeFeaturesAction = (s, f) => { var features = s.VariableLengthFeatures; Array.Resize(ref features, Config.FeatureLength); f.Features = features; };
事前トレーニング済みの TensorFlow モデルを読み込む
TensorFlow モデルを読み込むためのコードを追加します。
TensorFlowModel tensorFlowModel = mlContext.Model.LoadTensorFlowModel(_modelPath);
モデルが読み込まれたら、その入力および出力スキーマを抽出できます。 スキーマは、参考および学習の目的のためにのみ表示されます。 最終的なアプリケーションを機能させるためには、このコードは必要ありません。
DataViewSchema schema = tensorFlowModel.GetModelSchema(); Console.WriteLine(" =============== TensorFlow Model Schema =============== "); var featuresType = (VectorDataViewType)schema["Features"].Type; Console.WriteLine($"Name: Features, Type: {featuresType.ItemType.RawType}, Size: ({featuresType.Dimensions[0]})"); var predictionType = (VectorDataViewType)schema["Prediction/Softmax"].Type; Console.WriteLine($"Name: Prediction/Softmax, Type: {predictionType.ItemType.RawType}, Size: ({predictionType.Dimensions[0]})");
入力スキーマは、整数でエンコードされた単語の固定長配列です。 出力スキーマは、レビューのセンチメントが否定的であるか、肯定的であるかを示す、確率の float 型配列です。 肯定的な確率は否定的なセンチメントの確率の補数であるため、これらの値の合計は 1 になります。
ML.NET パイプラインを作成する
パイプラインを作成し、TokenizeIntoWords 変換を使用して入力テキストを単語に分割し、次のコード行としてテキストを単語に分割します。
IEstimator<ITransformer> pipeline = // Split the text into individual words mlContext.Transforms.Text.TokenizeIntoWords("TokenizedWords", "ReviewText")
TokenizeIntoWords 変換では、スペースを使用してテキストまたは文字列を単語に解析します。 これにより、新しい列が作成され、ユーザー定義の区切り記号に基づいて各入力文字列を部分文字列のベクターに分割します。
上記で宣言した参照テーブルを使用して、単語を整数エンコードにマップします。
// Map each word to an integer value. The array of integer makes up the input features. .Append(mlContext.Transforms.Conversion.MapValue("VariableLengthFeatures", lookupMap, lookupMap.Schema["Words"], lookupMap.Schema["Ids"], "TokenizedWords"))
可変長の整数エンコーディングのサイズを、モデルで必要とされる固定長に変更します。
// Resize variable length vector to fixed length vector. .Append(mlContext.Transforms.CustomMapping(ResizeFeaturesAction, "Resize"))
読み込まれた TensorFlow モデルで入力を分類します。
// Passes the data to TensorFlow for scoring .Append(tensorFlowModel.ScoreTensorFlowModel("Prediction/Softmax", "Features"))
TensorFlow モデルの出力は
Prediction/Softmax
と呼ばれます。 この名前Prediction/Softmax
は、TensorFlow モデルによって決定されることに注意してください。 この名前は変更できません。出力予測用に新しい列を作成します。
// Retrieves the 'Prediction' from TensorFlow and copies to a column .Append(mlContext.Transforms.CopyColumns("Prediction", "Prediction/Softmax"));
Prediction/Softmax
列を C# クラスPrediction
のプロパティとして使用できる名前を持つ列にコピーする必要があります。/
文字は、C# プロパティ名では使用できません。
パイプラインから ML.NET モデルを作成する
パイプラインからモデルを作成するためのコードを追加します。
// Create an executable model from the estimator pipeline IDataView dataView = mlContext.Data.LoadFromEnumerable(new List<MovieReview>()); ITransformer model = pipeline.Fit(dataView);
ML.NET モデルは、
Fit
メソッドを呼び出すことによって、パイプラインのエスティメーターのチェーンから作成されます。 この場合、TensorFlow モデルは既に以前トレーニングされているため、モデルを作成するためのデータを調整することはありません。Fit
メソッドの要件を満たすために、空のデータ ビュー オブジェクトを提供します。
モデルを使用して予測する
MovieReview
クラスの上にPredictSentiment
メソッドを追加します。void PredictSentiment(MLContext mlContext, ITransformer model) { }
次のコードを追加して、
PredictionEngine
をPredictSentiment()
メソッドの 1 行目として作成します。var engine = mlContext.Model.CreatePredictionEngine<MovieReview, MovieReviewSentimentPrediction>(model);
PredictionEngine は、データの 1 つのインスタンスに対して予測を実行できる便利な API です。
PredictionEngine
はスレッド セーフではありません。 シングル スレッド環境またはプロトタイプ環境で使用できます。 運用環境でパフォーマンスとスレッド セーフを向上させるには、PredictionEnginePool
サービスを使用します。これにより、アプリケーション全体で使用するできるPredictionEngine
オブジェクトのObjectPool
が作成されます。 ASP.NET Core Web API でPredictionEnginePool
を使用する方法については、こちらのガイドを参照してください。注意
PredictionEnginePool
サービスの拡張機能は、現在プレビュー段階です。コメントを追加して、
Predict()
メソッドでトレーニングされたモデルの予測をテストします。これにはMovieReview
のインスタンスを作成します。var review = new MovieReview() { ReviewText = "this film is really good" };
PredictSentiment()
メソッドに次のコード行を追加することで、テスト コメント データをPrediction Engine
に渡します。var sentimentPrediction = engine.Predict(review);
Predict() 関数では、データの単一行に対して予測を行います。
プロパティ [値] 種類 予測 [0.5459937, 0.454006255] float[] 次のコードを使用して、センチメント予測を表示します。
Console.WriteLine($"Number of classes: {sentimentPrediction.Prediction?.Length}"); Console.WriteLine($"Is sentiment/review positive? {(sentimentPrediction.Prediction?[1] > 0.5 ? "Yes." : "No.")}");
Fit()
メソッドを呼び出した後、PredictSentiment
への呼び出しを追加します。PredictSentiment(mlContext, model);
結果
アプリケーションをビルドして実行します。
結果は以下のようになるはずです。 処理中にメッセージが表示されます。 警告または処理メッセージが表示されることがありますが、 わかりやすくするために、これらのメッセージは次の結果から削除してあります。
Number of classes: 2
Is sentiment/review positive ? Yes
おめでとうございます! これで、ML.NET で事前トレーニング済みの TensorFlow
モデルを再利用することにより、メッセージのセンチメントを分類および予測するための機械学習モデルをビルドできました。
このチュートリアルのソース コードは dotnet/samples リポジトリで確認できます。
このチュートリアルでは、次の作業を行う方法を学びました。
- 事前トレーニング済みの TensorFlow モデルを読み込む
- Web サイトのコメント テキストをモデルに適したフィーチャーに変換する
- モデルを使用して予測する
.NET