AIによる感情分析　アンケート編

# 目次
[1.はじめに](#1-はじめに)
[2.パイプラインを使った感情分析](#2-パイプラインを使った感情分析)
[3.トークナイザーを使った感情分析](#3-トークナイザーを使った感情分析)
[4.おわりに](#4-おわりに)

# 1. はじめに
**Chat-GPT**、本当にスゴイですね。

Chat-GPTのGPTは「Generative Pre-trained **Transformer**」の略です。Chat-GPTを形成する中核技術が、**Transformer**です。

Transformerで有名なのは、**Hugging Face**という企業で、時価総額は20億ドルを超える**ユニコーン企業**です。

Hugging Faceは、Transformerを中心としたニューラルネットワークアーキテクチャを中心に活動しています。Transformerは、自然言語の理解や生成タスクにおいて優れた性能を発揮するアーキテクチャで、BERT、GPT、T5などの有名なモデルがこのアーキテクチャを基にしています。

Hugging Faceは、Transformerを簡単に利用できるようにするためのソフトウェアライブラリやAPIを提供し、機械学習エンジニア、研究者、開発者がこれらのモデルを効果的に利用できるようにしています。また、プリトレーニング済みのモデルを提供し、ファインチューニングによって特定のNLPタスクに適合させることができます。

**<INS>今回は、AIの代表的技術であるTransformerを使って、アンケートの感情分析を行ってみたいと思います。</INS>**

**<INS>アンケートの自由記載欄に、意見を書いてもらって、ポジティブな意見なのか、ネガティブな意見なのか、ヒトが判断するのではなく、AIに数値で、客観的に判断してもらおう、という試みになります。</INS>**

# 2. パイプラインを使った感情分析

パイプラインは、特定のNLPタスク（テキスト分類、質問応答、テキスト生成など）を実行するための高レベルな抽象化を提供します。これにより、モデルの選択やトークン化などの詳細な手順を意識せずに、タスクを簡単に実行できます。パイプラインは、モデルの選択、トークナイザーの適切な使用、結果の後処理などを内部的に処理します。

パイプラインは特定のタスクを指定して初期化し、その後、与えられたテキストに対してタスクを実行するためのメソッドを呼び出すだけで簡単に使用できます。

ということで、もし、英文の感情分析をするのであれば、モデルを使用せず、以下のコードだけでOKです。

```python
pip install transformers
from transformers import pipeline

# 感情分析のためのパイプラインをロード
classifier = pipeline('sentiment-analysis')

# 分析したい英文を指定
text = "I love this product! It's amazing."

# 感情分析を実行
result = classifier(text)

# 結果を出力
print(result)
```

結果は、正しく、
**[{'label': 'POSITIVE', 'score': 0.9998866319656372}]**
と、出力されます。

<INS>ただし、モデルを指定しないと、日本語では正しく感情分析できませんので、ご注意ください。</INS>

日本語で感情分析します。
まずは、ダミーでアンケート結果を作って、csvファイルにします。

```python
import pandas as pd

# アンケート結果をリストに格納
responses = [
    "製品の品質は素晴らしいです。特にデザインが気に入りました。使いやすさも抜群です。",
    "製品は普通です。期待通りの性能で、特に良い点や悪い点はありませんでした。",
    "製品は期待外れでした。機能が不安定で、操作性も悪いです。購入を後悔しています。"
]

# リストをDataFrameに変換
df = pd.DataFrame({'回答': responses})

# CSVファイルに保存
df.to_csv('アンケート結果.csv', index=False, encoding='utf-8-sig')
```

それでは、いよいよ、感情分析を行います。
後ほど、詳しく説明しますので、まずは、コードを示します。

```python
pip install transformers
from transformers import pipeline
import pandas as pd

# パイプラインを作成
classifier = pipeline("sentiment-analysis", model="nlptown/bert-base-multilingual-uncased-sentiment")

# CSVファイルを読み込む
csv_file = 'アンケート結果.csv'
df = pd.read_csv(csv_file)

# 感情分析を実行
emotions = []
for text in df['回答']:
    results = classifier(text)
    predicted_emotion = results[0]['label']
    highest_prob = results[0]['score']
    emotions.append((predicted_emotion, highest_prob))

# 結果をDataFrameに追加
df['感情'] = [emotion[0] for emotion in emotions]
df['確率'] = [emotion[1] for emotion in emotions]

# 結果を出力
df
```

このコードは、Hugging Face Transformersライブラリを使用して、テキストデータに対する感情分析を実行し、結果をDataFrameに追加する処理を行っています。

以下は、コードのステップごとの詳細な説明です：

1. `pip install transformers`: まず、`transformers`ライブラリをインストールします。これはHugging Face Transformersライブラリを含んでいます。

2. `from transformers import pipeline`: Transformersライブラリから、パイプラインをインポートします。このパイプラインは、感情分析タスクを実行するために使用されます。

3. `classifier = pipeline("sentiment-analysis", model="nlptown/bert-base-multilingual-uncased-sentiment")`: "sentiment-analysis"タスク用のパイプラインを作成し、`nlptown/bert-base-multilingual-uncased-sentiment`というモデルを指定して初期化します。このモデルは、多言語対応の感情分析に適した事前学習済みのBERTモデルです。

4. `csv_file = 'アンケート結果.csv'`: 感情分析を行う対象となるテキストデータが含まれたCSVファイルのファイル名を指定します。

5. `df = pd.read_csv(csv_file)`: pandasライブラリを使用して、指定されたCSVファイルを読み込み、データをDataFrameに格納します。

6. `emotions = []`: 感情分析の結果を格納するための空のリストを作成します。

7. `for text in df['回答']:`: DataFrame内の各行に対してループを開始し、"回答"列に含まれるテキストデータを取得します。

8. `results = classifier(text)`: パイプラインを使用して、各テキストに対する感情分析を実行します。結果は感情ラベルとその確率を含むリストとして取得されます。

9. `predicted_emotion = results[0]['label']`および`highest_prob = results[0]['score']`: 各結果から、予測された感情ラベルとその確率を取得します。

10. `emotions.append((predicted_emotion, highest_prob))`: 予測された感情ラベルと確率を`emotions`リストに追加します。

11. `df['感情'] = [emotion[0] for emotion in emotions]`および`df['確率'] = [emotion[1] for emotion in emotions]`: 予測された感情ラベルと確率をDataFrameに新しい列として追加します。

12. `df`: 最終的に更新されたDataFrameを出力します。このDataFrameには、元のデータに感情分析の結果が追加されています。

このコードを実行することで、CSVファイル内のテキストデータに対する感情分析が行われ、その結果がデータフレームに追加されます。感情分析の結果は、各テキストの感情ラベルと確率として示されます。

出力結果は、以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76072/4c0ad9d0-7b47-cdac-47aa-43d2950a37f9.png)

**３つを比較して見て下さい。**

**１番目と２番目は、共に肯定的な評価ですが、肯定的である確率が異なっており、１番目の方が、確率が高くなっています。アンケート結果を見ても、１番目と２番目では、ニュアンスが違いますね。１番目は5 starsである確率も相応に高いと思われます。**

**一方、３番目は、否定的な評価になっています。**

パイプラインを使って、評価指標は指定していませんので、このモデルの場合、デフォルトでは、星が５つ（Very Positive）から１つ（Very Negative）で評価されるようです。

# 3. トークナイザーを使った感情分析

トークナイザーは、テキストデータをモデルの入力として使用できる形式に変換する役割を果たします。具体的には、テキストを単語やサブワード（トークン）に分割し、それらを数値化（トークンIDに変換）します。

トークナイザーは、テキストの前処理とトークン化を行うためのインターフェースを提供します。Pythonコード内でトークナイザーを初期化し、テキストをトークン化したり、モデルへの入力データを準備したりするのに使用されます。トークナイザーは個々のテキスト処理ステップを制御するための柔軟性があります。

```python
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch
import pandas as pd

# モデルの読み込み
model_name = "nlptown/bert-base-multilingual-uncased-sentiment"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name)

# CSVファイルを読み込む
csv_file = 'アンケート結果.csv'
df = pd.read_csv(csv_file)

# 感情分析の結果を格納するリスト
emotion_results = []

# 各回答に対して感情分析を実行
for text in df['回答']:
    # テキストの前処理とトークン化
    inputs = tokenizer(text, return_tensors="pt", padding=True, truncation=True)

    # モデルに入力データを渡して感情分析を実行
    outputs = model(**inputs)
    probs = outputs.logits.softmax(dim=1)[0]

    # 感情ラベルと確率を取得
    emotion_labels = ['very negative', 'negative', 'neutral', 'positive', 'very positive']
    results = [(label.replace('LABEL_', '').replace('_', ' ').capitalize(), prob.item()) for label, prob in zip(emotion_labels, probs)]

    # 最も高い確率である結果を取得
    predicted_emotion, highest_prob = max(results, key=lambda x: x[1])

    # 結果をリストに追加
    emotion_results.append((predicted_emotion, highest_prob))

# 感情分析の結果をDataFrameに追加
df['感情'] = [result[0] for result in emotion_results]
df['確率'] = [result[1] for result in emotion_results]

# 結果を出力
df
```

このコードは、Hugging Face Transformersライブラリを使用して、テキストデータに対する感情分析を実行し、結果をDataFrameに追加する処理を行っています。

以下は、コードのステップごとの詳細な説明です：

1. `from transformers import AutoTokenizer, AutoModelForSequenceClassification, torch, pandas as pd`: Transformersライブラリから必要なモジュールとライブラリをインポートします。

2. `model_name = "nlptown/bert-base-multilingual-uncased-sentiment"`: 使用する感情分析モデルの名前を指定します。このモデルは、多言語対応の感情分析に適したBERTモデルです。

3. `tokenizer = AutoTokenizer.from_pretrained(model_name)`: モデル用のトークナイザを読み込みます。トークナイザは、テキストデータをモデルの入力形式に変換する役割を果たします。

4. `model = AutoModelForSequenceClassification.from_pretrained(model_name)`: 感情分析モデルを読み込みます。このモデルは、感情分類タスクに事前にトレーニングされたものです。

5. `csv_file = 'アンケート結果.csv'`: 感情分析を行う対象となるテキストデータが含まれたCSVファイルのファイル名を指定します。

6. `df = pd.read_csv(csv_file)`: pandasライブラリを使用して、指定されたCSVファイルを読み込み、データをDataFrameに格納します。

7. `emotion_results = []`: 感情分析の結果を格納するための空のリストを作成します。

8. `for text in df['回答']:`: DataFrame内の各行に対してループを開始し、"回答"列に含まれるテキストデータを取得します。

9. テキストの前処理とトークン化: テキストデータをモデルの入力に適した形式に変換します。トークナイザを使用してテキストをトークンに分割し、モデルに適切なフォーマットでデータを提供します。

10. `outputs = model(**inputs)`: モデルに入力データを渡して感情分析を実行します。結果は`outputs`に格納されます。

11. `probs = outputs.logits.softmax(dim=1)[0]`: モデルの出力を確率分布に変換します。具体的には、ソフトマックス関数を適用して確率値を計算します。

12. 感情ラベルと確率を取得: モデルの出力から、感情ラベルとその確率を取得します。感情ラベルは「very negative」から「very positive」までの5つのクラスで表され、確率は各クラスに対する予測確率です。

13. 最も高い確率である結果を取得: 予測された感情ラベルとその確率が最も高い結果を選択します。

14. 結果をリストに追加: 感情分析の結果を`emotion_results`リストに追加します。

15. `df['感情'] = [result[0] for result in emotion_results]`および`df['確率'] = [result[1] for result in emotion_results]`: 予測された感情ラベルと確率をDataFrameに新しい列として追加します。

16. `df`: 最終的に更新されたDataFrameを出力します。このDataFrameには、元のデータに感情分析の結果が追加されています。

このコードを実行することで、CSVファイル内のテキストデータに対する感情分析が行われ、その結果がデータフレームに追加されます。感情分析の結果は、各テキストの感情ラベルと確率として示されます。

出力結果は、以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76072/cfc9c335-4086-f107-3bc3-e9cbb082c7e6.png)

**先ほどと同じモデルを使っていますので、結果は先ほどと同様です。**

**今回は、感情ラベルを「very negative」から「very positive」までの5つのクラスで指定しましたので、その指定にそったラベルが付けられています。**

<INS>上記でも分かる通り、**パイプライン**は利用の簡便性に重きを置いた手法です。
一方、**トークナイザー**は細かなカスタマイズを入れるのに適した手法です。</INS>

# 4. おわりに
いかがだったでしょうか？
**Transformerを使って、アンケートの感情分析、ネガポジ分析ができました。**

**肯定的な意見か、否定的な意見か、もちろん、読めば分かりますが、しっかり、数値で、客観的に示すことができるのは、素晴らしいことだと思います。**

<INS>昔の囲碁や将棋のTV番組では、どちらが有利か不利か、解説の人が説明していましたが、それって、**感覚**で、**あやふや**ですよね。今はAIの評価値が、ちゃんと出ていて、状況判断が素人にも分かりやすいです。あの大天才の**藤井聡太**さんですら、AIの評価値を参考にしているくらいですから、信頼度に問題はないものと思います。</INS>

<INS>そんな、AIの力を利用して、アンケートの結果も、適切に活用できれば、大きな武器です。多言語に対応したモデルを使えば、日本語、英語、その他の言葉も、横一線で評価できると思います。</INS>

**ぜひとも、AIの力を活用してみてください。**

## 参考

2017年に**Google**が論文**Attention Is All You Need**で発表した深層学習モデルが、単数形のTransformerです。

一方、**Hugging Face**が開発した機械学習のためのライブラリは、複数形のTransformer**s**です。
GPT-2やBERTなど、いろんなTransformerを含むライブラリだからだと思います。

分かりにくいですね（笑）