ChatGPTが解き明かすテキストの心情（ChatGPTで感情分析してみる）

## はじめに
サウナでリラックスしながらChatGPTで何かできないか考え事をしていた際に、「専門知識なしに「感情分析」が簡単にできるのでは:thinking:」とアイデアが浮かびました。
そこで、早速ChatGPTを活用して感情分析に挑戦してみることにしました。

## 準備するもの
・Google Colaboratory（※JupyterLabでも問題ありません）
・OpenAI API
・chABSA-dataset

## 目次
1. [OpenAI APIの利用方法について](#openai-apiの利用方法について)
2. [OpenAI APIのGPTモデルの使い方の調査と検証](#openai-apiのgptモデルの使い方の調査と検証)
3. [ChatGPTで感情分析の試行](#chatgptで感情分析の試行)
4. [chABSA-datasetで検証](#chabsa-datasetで検証)
4. [最後に](#最後に)

### OpenAI APIの利用方法について
今回、OpenAI APIが必要となります。OpenAI APIを使用するには、次の手順に従ってください。

1. OpenAIにアクセスし、開発者向けのアカウントを作成します。[OpenAIのWebサイト](https://openai.com)にアクセスしてください。
2. 開発者アカウントがある場合は、OpenAIのダッシュボードにログインします。
3. ダッシュボードのナビゲーションメニューから、「API key」を選択します。
4. APIキーのページで、「Create new secret key」のボタンをクリックして新しいAPIキーを作成します。APIキーは、ChatGPT APIにアクセスするための認証情報です。
5. APIキーが生成されたら、適切に保管してください。公開されないようにしてください。

なお、OpenAIのAPIの料金は従量課金となっておりますが、「Billing > Usage limits」から月の利用料の上限を設定できるため、設定しておくと安心かと思います。
無料枠がとっくの昔に切れていたため、僕は怖くて設定しました:writing_hand:

### OpenAI APIのGPTモデルの使い方の調査と検証
1. Packageのインストールと設定
    ```python:exp.ipynd（１セル目）
    # パッケージインストール
    !pip install openai
    # パッケージのインポート
    import openai
    # APIキーを設定します
    openai.api_key = '{APIキー}'
    ```
1. 動作検証
    1. GPTにただ質問をして回答を得る
        ```python:exp.ipynd（２セル目）
        #推論を実行
        response = openai.ChatCompletion.create(
          model="gpt-3.5-turbo",
          messages=[
                {"role": "user", "content": "JavaとPythonのそれぞれのメリット・デメリットは何がありますか？"}
            ]
        )
        ```
        ↓出力結果
        ```
        Javaのメリット
        - ポータビリティ: Javaはプラットフォームに依存しないため、どのオペレーティングシステムでも動作します。このため、Javaは異なるシステム間でコードを再利用することができます。
        - 高性能: JavaはJIT（Just-In-Time）コンパイルを使用しており、ランタイムでコードをコンパイルするため、高いパフォーマンスを発揮します。
        - 大規模プロジェクトに適している: Javaのオブジェクト指向プログラミングの特徴から、大規模なプロジェクトに適しています。Javaはクラスの作成が容易で、継承やポリモーフィズムを利用できます。
        
        Javaのデメリット
        - セキュリティ: 以前、Javaはセキュリティ弱点が多いことで知られていました。しかし、最近ではJavaプラットフォームの改善により、セキュリティ問題は減少しています。
        - オーバーヘッド: Javaは高水準の言語であり、実行時に様々な処理を行うため、パフォーマンスが低下する可能性があります。
        
        Pythonのメリット
        - シンプル: Pythonは文法がシンプルで直感的です。初心者でも学びやすいため、プログラミング初心者から上級者まで幅広い層に利用されています。
        - 大きなコミュニティ: Pythonには大きなコミュニティがあり、多くの人々がPythonの開発に貢献しています。そのため、Pythonには多数のライブラリやフレームワークがあり、開発が迅速で容易になります。
        - 大規模プロジェクトにも適している: Pythonはスクリプト言語であり、開発が迅速であると同時に、オブジェクト指向プログラミングもサポートしています。そのため、大規模プロジェクトにも適しています。
        
        Pythonのデメリット
        - パフォーマンス: PythonはJITコンパイルを利用していないので、Javaに比べてパフォーマンスが劣る場合があります。
        - ポータビリティ: PythonはJavaほどポータブルではありません。Pythonが標準でインストールされていないシステムでPythonアプリケーションを実行する場合は、Pythonのインストールが必要です。
        ```
    2. GPTに役割を与えて、その役割に従った回答を得る方法
        ・systemでChatGPTに役割を与えています。
        ・assistantで望ましい回答の例を指定しています。
        ・userが質問内容です。
        
        ```python:exp.ipynd（３セル目）
        # ChatGPTにメッセージを送信する関数を定義します
        response = openai.ChatCompletion.create(
          model="gpt-3.5-turbo",
          messages=[
                {"role": "system", "content": "あなたはプログラマーです。"},
                {"role": "user", "content": "これからプログラミングを始めたいのですが、おすすめの言語はなんですか？"},
                {"role": "assistant", "content": "ChatGPTのようなAIサービスとの相性のよさから、Pythonをお勧めします。"},
                {"role": "user", "content": "JavaとPythonのそれぞれのメリット・デメリットは何がありますか？"}
            ]
        )
        
        #ChatGPTの回答を出力
        response["choices"][0]["message"]["content"]
        ```
        ↓出力
        ```
        JavaとPythonのそれぞれのメリット・デメリットを以下にまとめてみました。
    
        Javaのメリット：
        - 静的型付け言語であり、タイプミスによるエラーを減らすことができます。
        - オブジェクト指向プログラミングが得意です。
        - 可読性が高く、多くの企業で採用されているため、求人が多いです。
        - 大規模なアプリケーションに向いています。
        - プラットフォームに依存しないため、多くのOSで動作します。
    
        Javaのデメリット：
        - シンタックスが複雑で、学習曲線が急です。
        - メモリ管理に関する知識やスキルが必要です。
        - コンパイル時間が長く、開発が遅いことがあります。
    
        Pythonのメリット：
        - シンプルかつ読みやすいコードを書くことができます。
        - 動的型付け言語であり、柔軟にプログラミングできます。
        - 大規模なアプリケーションにも向いており、データサイエンスやAI分野でも広く使われています。
        - ライブラリが豊富で、開発コストを減らすことができます。
    
        Pythonのデメリット：
        - 静的型付け言語に比べて、エラーがコンパイル時ではなく実行時に発生することがあるため、デバッグが難しいことがあります。
        - 内部処理が遅いため、高速なアプリケーション開発に向いていません。
        - Python 2.x と Python 3.x という2つの主要なバージョンがあり、互換性の問題があることがあります。
        ```

        役割の割り当ての有無で大きく回答結果が変わりましたが、役割の設定がよくないですね:sweat_smile:
        ここをこだわりだすと話がそれるので・・・とりあえず、動作確認の検証は問題なく完了です:v:

### ChatGPTで感情分析の試行
前項での「GPTに役割を与えて、その役割に従った回答を得る方法」を活用して、感情分析する役割を与えて、質問した文章の「感情」を以下の指標で数値化してみる。
・ポジティブな言動の場合、「1」
・ネガティブな言動の場合、「-1」
・どちらでもない場合、「0」

役割は下記のように与えました。
`あなたは感情分析サービスです。userから送信された文章の感情がポジティブなら「1」ネガティブなら「-1」どちらでもないなら「0」と回答してください`

```python:exp.ipynd（４セル目）
# ChatGPTにメッセージを送信する関数を定義します
response = openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
        {"role": "system", "content": "あなたは感情分析サービスです。userから送信された文章の感情がポジティブなら「1」ネガティブなら「-1」どちらでもないなら「0」と回答してください"},
        {"role": "user", "content": "今日はいいことがったから、明日もいい日になるはず"},
        {"role": "assistant", "content": "1"},
        {"role": "user", "content": "先日に運動中に怪我をしてしまった"}
    ]
)

#ChatGPTの回答を出力
response["choices"][0]["message"]["content"]
```
↓出力
```
'-1'
```

「先日に運動中に怪我をしてしまった」は一般的にはネガティブな状態だと思いますので、いい感じではないでしょうか:v:

### chABSA-datasetで検証

やや検証不足気味ですが、前項までの検証で感情分析が可能なことがわかりましたので、早速精度を評価してみたいと思います！

今回は下記記事で紹介されているオープンソースのデータセットを利用して感情分析システムを試してみます。
・[TIS、機械学習で感情解析を行うためのデータセット「chABSA-dataset」を無償公開](https://www.tis.co.jp/news/2018/tis_news/20180410_1.html)

日本語のデータセットは大変重宝します。とてもありがいです:bow_tone1:
（TwitterAPI使って検証する前提で記事を書き始めましたが、TwitterAPIを個人で使うにはお高い・・・）

なお、探索的データ解析（EDA）については事前に済ませており、本記事の観点から逸れるためデータセットの解説は省きます。

#### データの前処理

1. chABSA-datasetの取得
    ```python:exp.ipynd（５セル目）
    # chABSA-datasetをインストール
    !wget https://s3-ap-northeast-1.amazonaws.com/dev.tech-sketch.jp/chakki/public/chABSA-dataset.zip
    !unzip chABSA-dataset.zip 
    ```
2. データ構造の確認
    ```python:exp.ipynd（６セル目）
    import json
    with open("/content/chABSA-dataset/e00008_ann.json","br") as f:
        data = json.load(f)
    
    data["sentences"][0]
    ```
    ↓出力
    ``` 
    {'sentence_id': 0,
     'sentence': '当連結会計年度におけるわが国経済は、政府の経済政策や日銀の金融緩和策により、企業業績、雇用・所得環境は改善し、景気も緩やかな回復基調のうちに推移いたしましたが、中国をはじめとするアジア新興国経済の減速懸念や、英国の欧州連合（ＥＵ）離脱決定、米国新政権への移行など、引き続き先行きは不透明な状況となっております',
     'opinions': [{'target': 'わが国経済',
       'category': 'NULL#general',
       'polarity': 'neutral',
       'from': 11,
       'to': 16},
      {'target': '企業業績',
       'category': 'NULL#general',
       'polarity': 'positive',
       'from': 38,
       'to': 42},
      {'target': '雇用',
       'category': 'NULL#general',
       'polarity': 'positive',
       'from': 43,
       'to': 45},
      {'target': '所得環境',
       'category': 'NULL#general',
       'polarity': 'positive',
       'from': 46,
       'to': 50},
      {'target': '景気',
       'category': 'NULL#general',
       'polarity': 'positive',
       'from': 55,
       'to': 57}]}
    ```
3. データの前処理
    データの前処理のロジックはデータ構造の「sentence」の感情を分析し、polarityの多数決を使用してPositiveとNegativeを正解ラベルと定義します。
    ```python:exp.ipynd（７セル目）
    # 検証用のデータセット
    inferences = []
    labels = []
    
    for sentences in data['sentences']:
        # 推論データ
        sentence = sentences['sentence']
      
        # 多数決で感情を決定する
        polarity_vote = 0
        majority_polarity = None
        for opinion in sentences['opinions']:
          polarity = opinion['polarity']
          if polarity == 'positive':
            polarity_vote += 1
          else:
            polarity_vote -= 1
    
        if polarity_vote > 0:
          majority_polarity = '1'  # Positive
        elif polarity_vote == 0:
          majority_polarity = '0'  # どちらもない
        else:
          majority_polarity = '-1'  # Negative
        
        inferences.append(sentence)
        labels.append(majority_polarity)
    ```
    ```python:exp.ipynd（８セル目）
    inferences[1]
    ```
    ↓出力
    ```
    当社グループを取り巻く環境は、実質賃金が伸び悩むなか、
    消費者の皆様の生活防衛意識の高まりや節約志向により、個人消費は本格的な改善には至らず、
    また少子高齢化、人口減少による社会構造の変化、
    雇用改善に伴う労働コストの上昇、企業間競争の激化など、引き続き厳しい状況となりました
    ```
    ```python:exp.ipynd（９セル目）
    labels[1]
    ```
    ↓出力
    ```
    -1
    ```

    「厳しい状況」や「実質賃金が伸び悩む」などネガティブなワードが多い文面のものが「negative」であるため、正解ラベルのデータとしては問題はなさそうですかね。

#### 推論
ここで、ChatGPTにテキストの心情を解き明かして、テキストの思いをさらしてもらおうと思う。
ただ、推論するテキストが報告書のような情報となってしまったので、役割を下記のように変更します:bow_tone1:

`あなたは企業の評論家です。userから送信された情報がポジティブな状況なら「1」ネガティブな状況なら「-1」判断不可能なら「0」と回答してください`

```python:exp.ipynd（１０セル目）
def predict(inference_word):

  # ChatGPTにメッセージを送AS信する関数を定義します
  response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
          {"role": "system", "content": "あなたは企業の評論家です。userから送信された情報がポジティブな状況なら「1」ネガティブな状況なら「-1」判断不可能なら「0」と回答してください"},
          {"role": "user", "content": "当社グループを取り巻く環境は、実質賃金が伸び悩むなか、消費者の皆様の生活防衛意識の高まりや節約志向により、個人消費は本格的な改善には至らず、また少子高齢化、人口減少による社会構造の変化、雇用改善に伴う労働コストの上昇、企業間競争の激化など、引き続き厳しい状況となりました"},
          {"role": "assistant", "content": "-1"},
          {"role": "user", "content": inference_word}
      ]
  )

  #ChatGPTの回答を出力
  return response["choices"][0]["message"]["content"]
```

```python:exp.ipynd（１１セル目）
predicts = []
for inference_word in inferences:
  predicts.append(predict(inference_word))
```

#### 後処理（推論結果の確認）

```python:exp.ipynd（１１セル目）
# データフレームの作成
df = pd.DataFrame({'label': labels, 'predict': predicts, 'inference': inferences})
df
```

|index|正解ラベル|GPT推論|推論データ|
|---|---|---|---|
|0|1|0|当連結会計年度におけるわが国経済は、政府の経済政策や日銀の金融緩和策により、企業業績、雇用・所得環境は改善し、景気も緩やかな回復基調のうちに推移いたしましたが、中国をはじめとするアジア新興国経済の減速懸念や、英国の欧州連合（ＥＵ）離脱決定、米国新政権への移行など、引き続き先行きは不透明な状況となっております|
|1|-1|-1|当社グループを取り巻く環境は、実質賃金が伸び悩むなか、消費者の皆様の生活防衛意識の高まりや節約志向により、個人消費は本格的な改善には至らず、また少子高齢化、人口減少による社会構造の変化、雇用改善に伴う労働コストの上昇、企業間競争の激化など、引き続き厳しい状況となりました|
|2|0|0|このような環境の中、当社グループはきのこ事業を中心として、健康食材である「きのこ」の研究開発、生産、販売を通して、より多くの皆様へ、おいしさと健康をお届けできるよう事業活動を行ってまいりました|
|3|0|1|また、平成26年に策定いたしました中期経営計画の見直しを行い、市況に左右されない事業ポートフォリオの構築を目指した活動を推進し、おいしくて健康な「きのこ食文化の創造」と「企業の発展」に向け邁進してまいりました|
|4|1|1|以上の結果、当連結会計年度の当社グループの業績は、売上高631億19百万円（前期比3\.5％増）、営業利益34億30百万円（前期比0\.1％増）、経常利益43億79百万円（前期比7\.5％増）、親会社株主に帰属する当期純利益は28億28百万円（前期比8\.9％増）となりました|
|5|1|0 \(回答不可能\)|なお、当連結会計年度の生産量は、ブナピーを含めブナシメジ42,602ｔ（同5\.5％増）、エリンギ19,250ｔ（同0\.2％減）、マイタケ14,281ｔ（同4\.3％増）となりました|
|6|0|回答が必要な内容が提供されていないため、ポジティブな状況「1」、ネガティブな状況「-1」、判断不可能なら「0」のいずれかの回答しかできません。セグメント毎に具体的な情報を提供いただければ、適切な回答を差し上げることができます。|当連結会計年度の各セグメントの概況は次のとおりであります|
|7|0|0（判断不可能）です。具体的な情報がなく、評価ができません。|「国内きのこ事業」|
|8|0|1|生産部門におきましては、衛生管理を徹底し、安定栽培と品質の向上に努めてまいりました|
|9|1|1|平成27年４月の火災により生産を休止していた苫小牧第一きのこセンターが、工場を再建し、平成28年４月27日よりブナシメジの収穫・出荷を再開したことや、カットブナシメジ専用工場として新設した富山きのこセンターが平成28年９月上旬から収穫・出荷を開始したことにより、ブナシメジの生産量は増加いたしました|
|10|1|1|また、改修のため一時生産を休止しておりました広川きのこセンターにおきまして、平成28年９月上旬より霜降りひらたけの収穫・出荷を開始したことなどにより、きのこ全体の生産量は増加いたしました|
|11|0|1|研究部門におきましては、品質管理体制の強化、付加価値の高い新商品の開発およびきのこの薬理効果や機能性の追求に取り組んでまいりました|
|12|0|0|特に、平成27年７月に完成したシイタケ栽培技術研究施設におきまして、シイタケの大量・安定栽培に向けた研究に注力いたしました|
|13|0|1|営業部門におきましては、鮮度に拘った営業活動を行う一方、きのこによる健康と美容価値の創出が消費に結びつくものとして、引き続き「菌活」の提唱を行い、消費の拡大に努めてまいりました|
|14|-1|-1|春から夏にかけましては個人消費の低迷などにより、きのこの価格は厳しい状況で推移いたしました|
|15|1|1|反面、秋から冬にかけましては天候不順などによる野菜価格の高騰により、きのこの価格は堅調に推移いたしました|
|16|1|1|以上の結果、国内きのこ事業全体の売上高は422億96百万円（同3\.1％増）となりました|
|17|0|判断不可能な情報です。具体的にどのような情報を提供していただけますか？|「海外きのこ事業」|
|18|1|1|海外きのこ事業におきましては、各子会社が稼働率を高めたことにより、生産量は増加いたしました|
|19|-1|-1|台湾の現地法人「台灣北斗生技股份有限公司」におきましては、ブランドの構築、企画提案などに力を入れ販売活動を行ってまいりましたが、企業間競争の激化により厳しい状況で推移いたしました|
|20|0|1|米国の現地法人「HOKTO KINOKO COMPANY」におきましては、引き続き非アジア系顧客の開拓に注力し、販売の拡大を目指すとともに、欧州でのマーケティング活動も引き続き行ってまいりました|
|21|0|1|マレーシアの現地法人「HOKTO MALAYSIA SDN\. BHD\.」におきましては、マレーシア国内に限らず、広く東南アジアのマーケットでの販売を展開してまいりました|
|22|0|0|また、当社では新たな販路の開拓を目的として、東南アジア地域の市場調査・情報収集活動を強化するため、平成28年７月にタイ・バンコクに駐在員事務所を開設いたしました|
|23|1|1|以上の結果、海外きのこ事業全体の売上高は45億12百万円（同1\.4％増）となりました|
|24|0|回答するためには、もう少し具体的な情報が必要です。加工品事業に対するフィードバックがポジティブかネガティブか不可能かについては、具体的な評価軸を例示していただけますか？|「加工品事業」|
|25|0|0|加工品事業におきましては、水煮・冷凍などのアイテムやレトルト食品など加工品の販売を行っております|
|26|0|0|その中で新しいアイテムの開発とさらなる市場開拓を行ってまいりました|
|27|0|0|一方、自社きのこを活用した新商品の開発および健康食品・レトルト食品を中心とした販売活動にも注力するとともに、一部商品におきましては通販事業による一般の消費者の皆様への直接販売にも力を入れてまいりました|
|28|1|1|また、子会社の株式会社アーデンにおきましては、ＯＥＭ製品が好調に推移いたしました|
|29|1|1|以上の結果、加工品事業の売上高は70億64百万円（同15\.5％増）となりました|
|30|0|情報が足りないため、回答することはできません。具体的な情報を提供してください。|「化成品事業」|
|31|-1|0|化成品事業におきましては、引き続き厳しい販売環境にありましたが、中核である包装資材部門におきましては、効率化・利益率の改善を図るため営業戦略を見直し、販売強化に注力してまいりました|
|32|0|1|農業資材部門におきましては、資材の提供だけではなく、きめ細やかなサポートを強化してまいりました|
|33|0|1|新規戦略本部におきましては、一昨年より自社製品の販売を一つの柱にすべく営業活動を展開しております|
|34|0|1|新規販路の開拓と既存製品拡販に対応するため製造能力を旧工場の３倍にアップした新工場を長野市豊野に建設し、平成28年９月から稼働を開始いたしました|
|35|-1|-1|以上の結果、化成品事業の売上高は92億45百万円（同1\.7％減）となりました|

#### 検証纏め
お気づきかもしれませんが、データセットの仕様に合わせて、「感情」ではなくなってしまっています。
ただ、GPTを使用した分析の結果を見ると、満足できる結果になっているのではないかと思います。
正解ラベルは私のロジックが雑すぎて参考になりませんので、表中の文章と推論結果を見比べて皆様も考察してみてください:bow_tone1:

数値での結果を要求しているにも関わらず、判断等の理由を説明してくるケースは非常に親切ですが、エンジニアの視点ではやや厄介な面もあるかもしれません:sweat_smile:
このような想定しない応答に対するハンドリングがGPTを使うポイントであり、ノウハウにもなってくるのかなと思いました。

また、従来手法での感情分析も軽くさわったことがありますが、テキストの前処理が大変だったと記憶してます。
本手法はテキストには一切手を入れていないので、とても簡単にできている点はメリットかと思います。

## 最後に
使い道の一案ですが...

先日、スクラムマスター研修を受けてきて、学びの一つに幸福指標という指標がありました。

とはいえ、実際に精神状態が幸せでも、不幸でも問わず、
「あなたは幸せですか？」と問われてたら僕は「うーんまあまあかな」とあいまいに答えると思います。

近年、テレワークが増え、部下の表情が見えずに何を考えているかわからない等でお困りの方、
chatGPTに部下のTeamsやSlackのやり取りを分析してもらって、ポジティブかネガティブか傾向をとってみてはいかがでしょうか？意外な側面が見えてくるかもしれません。

つまり、TeamsやSlackのやり取りから、幸福指標の自動測定なんかできたら面白そうだなと思います。

また、推論自体は、役割の設定をこだわったり等の簡単な改善で精度も格段に上がると考えています。
最近、プロンプトエンジニアという職種が注目を集めているようです。
この職種がまさに役割の設定をこだわる人たちのようで、実はかなり専門的で奥が深い分野なのかもしれません:thinking:

もし本記事が目に留まった方は「いいね」や「コメント」いただると幸いです:bow_tone1: