【C#】ML.NETでレビューに含まれる感情を分析してみた

# 【C#】ML.NETでレビューに含まれる感情を分析してみた

皆さんこんにちは！
ML.NETというフレームワークはご存じでしょうか？C#でもいま話題の機械学習を行うことができるフレームワークで2023年11月27日にver3.0がリリースされたばかりの最新のフレームワークです。

ずっと機械学習に興味があったため今回はこちらのページを参考にしてレビューに含まれる感情を分析してみます。

https://dotnet.microsoft.com/ja-jp/learn/ml-dotnet/get-started-tutorial/install

::: note warn
筆者は機械学習初心者です。単語や考え方はなるべく調査して正確な情報を記載するよう心掛けますが、万が一誤りがありましたらご教授いただけますと幸いです。
:::

## ML.NETとは

ML.NETは、.NET開発者向けの機械学習フレームワークで以下のような特徴を持ちます。

- **ネイティブサポート**: .NETアプリケーションから直接利用可能
- **オープンソース**: フリーでクロスプラットフォーム（Windows/Mac/Linux）で利用可能
- **AutoML**: ML.NET Model Builderを使えば、コーディングなしで機械学習モデルを作成できる

ML.NETを使用すると二値分類や回帰、クラスタリングなど様々なケースで機械学習を簡単に実行することができます。


## 環境

- Windows11
- Visual Studio 2022

## Model Builderのインストール

ML.NETにはModel Builderという便利な機能が実装されています。この機能を使用すると機械学習をGUI上で行うことができより直感的にML.NETを活用できるようになります。Model Builderは.NET デスクトップ開発 ワークロードをオプション内に含まれているためインストールしましょう。

まずVisual Studioを起動し画面上部より[ツール]>[ツールと機能を取得]を選択し機能のインストール画面を開きます。

その後「.NET デスクトップ開発」を選択しインストールの詳細から「ML.NET Model Builder」にチェックを[変更]をクリックしてインストールを実施してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783169/5dee851a-6be2-d29e-956b-099bc74bd53f.png)


## プロジェクトの作成

ML.NETを組み込むプロジェクトを作成します。今回はコンソールアプリを選択し、任意の名前で新規作成をしてください。(.NET 8のサポートなどのオプションは初期状態のままで大丈夫です。)

## 機械学習モデルの追加

続いて機械学習を行うモデルをプロジェクトに追加します。

ソリューションエクスプローラーで作成したプロジェクトを選択し右クリックから[追加]>[機械学習モデル]を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783169/41d80e15-0deb-eb48-535f-09242dcead64.png)

新しい項目の追加ウインドウが開かれるので「Machine Learning Model(ML.NET)」を選択し、名前をSentimentModel.mbconfigに変更し追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783169/8a4ee50a-e1f6-6955-0792-ae800ea033ca.png)

::: note
コンソールアプリ以外でも同じ手順で機械学習モデルを追加することができます。
:::

## 学習対象のデータを用意する。

[Sentiment Labelled Sentences データセット](https://archive.ics.uci.edu/ml/machine-learning-databases/00331/sentiment%20labelled%20sentences.zip)学習対象のデータを取得します。zipファイルを解凍するとyelp_labelled.txtというファイルがあるのでそのファイルをプロジェクト内に移動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783169/a6f2402d-4801-b293-3818-8be6c950cf0d.png)

このデータはお店にある飲食店に対するレビューの文章と肯定的なレビューか否定的なレビューかを0 or 1で示した値の2種類のデータから構成されています。

```
Wow... Loved this place.	1
Crust is not good.	0
Not tasty and the texture was just nasty.	0
Stopped by during the late May bank holiday off Rick Steve recommendation and loved it.	1
The selection on the menu was great and so were the prices.	1
Now I am getting angry and I want my damn pho.	0
Honeslty it didn't taste THAT fresh.)	0
The potatoes were like rubber and you could tell they had been made up ahead of time being kept under a warmer.	0
The fries were great too.	1
A great touch.	1
Service was very prompt.	1
Would not go back.	0
The cashier had no care what so ever on what I had to say it still ended up being wayyy overpriced.	0
I tried the Cape Cod ravoli, chicken,with cranberry...mmmm!	1
I was disgusted because I was pretty sure that was human hair.	0
I was shocked because no signs indicate cash only.	0
Highly recommended.	1
Waitress was a little slow in service.	0
This place is not worth your time, let alone Vegas.	0
did not like at all.	0
The Burrittos Blah!	0
```

### モデルの学習

ダウンロードしたデータに対してモデルの学習を行います。

まず初めに先ほど作成したSentimentModel.mbconfigをソリューションエクスプローラー上で選択しModel BuilderのGUIを表示します。表示されてた中から今回は「データ分類」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783169/1d74d99e-5a61-3af5-29ae-ade5cebdfb81.png)

続いてトレーニング環境を選択します。今回はローカルしか選択できないため何もせず「次の手順」を選択してください。シナリオによってはAzureやGPUが使用できるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783169/cd5d560b-765f-cfe4-4c8f-20d6083cff12.png)

次に学習対象のデータを選択します。「ファイル(csv,tsv,txt)」にチェックを入れて「参照」から先ほど用意したyelp_labelled.txtを選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783169/dd20ff8d-9e3b-a2f3-92d7-7c6abaebdde5.png)

うまく選択できれば「予想する列(ラベル)」と「データのプレビュー」が表示されるため「予想する列(ラベル)」にcol1を選択し「次の手順へ」をクリックしてください。

ここで選択したのは、モデルに予想させたい値(アウトプット)です。今回はレビューに含まれる感情を分析したいためcol1が対象になります。

データの読み込みまで完了したので実際に機械学習を実施します。「トレーニングする時間」を60に変更し「トレーニングの開始」を選択してください。

トレーニングが開始されると下記のようになるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783169/4236f17a-03f0-e260-18e8-7958f3c00c7e.png)

トレーニングが完了したらつづいて、モデルがどれくらい学習できているか評価を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783169/2097ea23-9942-8045-7ac4-36f0639f9d08.png)

モデルの評価画面では以下の情報を確認できます。
- マクロ精度：モデルの精度を表す。0.0~1.0の範囲で表示され高いほうが精度がよい
- モデル：トレーニングに使用したモデル
- 独自のモデルを試す：実際に値を与えてモデルの出力を見ることができます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783169/938b3755-3399-14fd-3ab4-0afc7ce5a720.png)

もしモデルの出来が気に食わない場合はトレーニングタブより再トレーニングが可能です。

## モデルを使用してアプリを作成

トレーニングしたモデルを使用して実際にコンソールアプリを作成します。
作成したコードは以下です。

```C#
using ConsoleApp1;// 作成したプロジェクト名

// 分析対象のデータ設定
var sampleData = new SentimentModel.ModelInput()
{
    Col0 = "This restaurant was wonderful."
};

// 分析の実行
var result = SentimentModel.Predict(sampleData);

// 結果の出力
var sentiment = result.PredictedLabel == 1 ? "Positive" : "Negative";
Console.WriteLine($"Text: {sampleData.Col0}\nSentiment: {sentiment}");
```

### 解説

トレーニングしたモデルは`SentimentModel`クラスを用いて使用していきます。定義が`namespace プロジェクト名`の名前空間に定義されているため`using`の追加が必要です。

コードの説明に入るとまず初めに`SentimentModel.ModelInput()`を用いてモデルに分析対象のレビューを与えています。次に`SentimentModel.Predict()`メソッドにそのデータを渡し分析を実行しています。

分析した結果が`result.PredictedLabel`内に格納されているので結果を判定し出力を行っています。
実際に出力してみましたが文章の感情を分析して判定していることを確認しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783169/8f6e5e37-80b7-7f31-b9bd-468e3e061290.png)

### うまくいかないケース

こちらのアプリでいろいろ遊んでいたところ、誤った分析をしたケースにも遭遇しました。現時点では百発百中の精度とはいかないようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3783169/b98fb2ea-405e-d663-1ca5-aa05327be33e.png)

原因についてはいろいろな可能性が考えられます(純粋に与えた英語が自然じゃなかったとか。。。)。自分の実力不足でうまく解決ができなかったため今後の課題としていきます。

## 最後に

今回はML.NETの最初のチュートリアルを実施して、レビューに含まれる感情を分析してみました。Model Builderを使用することで簡単に学習を行うことが可能であり、なおかつコンソールアプリ以外にも様々なアプリに組み込むことができるため、かなり強力なツールだと思いました！

今後も継続して学習を進めていきたいです:relaxed:

この記事で皆様のコーディングライフの助けになれれば幸いです！
ではまた次の記事で！！