【Python/AWS】第3回 AmazonComprehendを使ってテキストデータを感情分析する【データ分析】

# 1. はじめに

本記事は【Python/AWS】の第3回として前回に引き続き、
AWSのサービスを利用した一連のデータ分析の続きとなります。

**<font color="blue">▼前回の記事はこちら▼</font>**

https://qiita.com/kawanago_py/items/aabbe6c6d129c915f2ad

私自身、AWSのサービスを触るのは初めてだったので、
細かい説明など不足する点はあるかと思いますが、
大まかな流れをこちらで解説していきたいと思います。

本分析の全体像は以下のようになります。
![AWSアーキテクチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512226/2b7e4c24-cb1e-b6b8-16af-d8fb89ea55c5.png)
全体の分析目的は以前の分析から継続/発展して、
**<font color="red">「Splatoon3」におけるコンテンツのユーザー満足度調査</font>** です。

収集したデータから項目ごとに感情分析を行い、
ポジティブ/ネガティブの値を可視化することが最終目的です。

**<font color="blue">▼以前の記事はこちら▼</font>**

https://qiita.com/kawanago_py/items/38fbf30c3e1d1580c76c

## 1-1. 本記事の概要と目標

今回のテーマは **<font color="red">「Comprehendの利用」</font>** ということで、
本分析の要である感情分析を担うパートの仕様確認編です。

今回と次回の2記事にて、<font color="red">"Glue"</font>と<font color="red">"Comprehend"</font>を利用した
大規模なデータの整形と精査を行っていきます。

今回と次回で作成するパートのイメージはこのような形です。
![Glueアーキテクチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512226/018db07f-bdbf-b8ef-e51f-160d09701737.png)
使用するサービスとそれぞれの役割は以下の通りです。
**Amazon S3： 様々な形式のデータを保管できるストレージ
Amazon Comprehend： テキストから洞察を見つける自然言語処理サービス
AWS Glue： データの検出/結合を簡単に行えるサーバーレスデータ統合サービス**
※AWS Glueは次回扱います

なお本記事ではAWSの登録方法や初期設定、
S3のサービス詳細はほとんど取り上げていません。
必要に応じて[前回の記事](https://qiita.com/kawanago_py/items/aabbe6c6d129c915f2ad#2-amazon-s3%E3%81%AE%E6%BA%96%E5%82%99 "【Python/AWS】第1回 LambdaとOpenWeatherMapで天気予報を自動ツイートする【データ分析】")、または以下を参考にして下さい。

https://aws.amazon.com

https://pages.awscloud.com

## 1-2. 全体の流れ

自動実行の順番、流れとしては以下の通りです。
**１．Glueのトリガーによる朝10時に実行
２．S3からJSONファイルをCSVとして読み込む
３．ツイートを感情分析して値を追加(←今回扱う内容)
４．新しいデータフレームをCSVとしてS3に出力**

今回は感情分析のパートにフォーカスして解説します。

# 2. Comprehendについて
## 2-1. 感情分析とは

まずは感情分析について簡単に説明します。

感情分析とは与えられた文章の持つ意見について、
**<font color="red">ポジティブ/ネガティブ/ニュートラルのいずれか</font>** を
判断する機械学習の技術を指します。

よくある例としてはECサイトのレビューや
SNSの投稿を分析したマーケティングなどが有名です。

**<font color="blue">▼感情分析に関する参考記事▼</font>**

https://qiita.com/toshiyuki_tsutsui/items/604f92dbe6e20a18a17e

## 2-2. Comprehendの利用

Comprehendは上記で説明した感情分析をWEB上で
簡単に利用できるようにした素晴らしいサービスです。

利用はとても簡単なのでぜひ一度触ってみて下さい。
以下のページからWEBアプリを利用できます。

https://ap-northeast-1.console.aws.amazon.com/comprehend/home?region=ap-northeast-1#welcome

上記のリンクに飛ぶとこのような画面になります。
**<font color="orange">[Launch Amazon Comprehend]</font>** に移動します。
![comprehend_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512226/7f2b4b02-8c55-deb0-05b4-72f0d4574cfc.png)
メニューの **<font color="orange">[Real-time analysis]</font>** を選択します。
![comprehend_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512226/3a3248a6-ed0c-99e2-2f57-7e8517b2497c.png)
**input text** にテキストを入力し **<font color="orange">[Analyze]</font>** を押します。
![comprehend_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512226/fce808a7-7edb-dd1b-ba07-01ffc068ae59.png)
**<font color="orange">[Sentiment]</font>** を選ぶと各分類の確信度が表示されます。
画像の例だとしっかり **<font color="red">"Positive"</font>** に分類されています。
![comprehend_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512226/3f8640d1-8e4b-ed1c-6cd7-9fc71fd10370.png)
特に感情の偏りが見られない場合には **<font color="red">"Neutral"</font>** に、
ネガ/ポジの両方が含まれる場合には **<font color="red">"Mixed"</font>** に分類されます。

**<font color="blue">▼Comprehendの公式紹介▼</font>**

https://docs.aws.amazon.com/ja_jp/comprehend/latest/dg/what-is.html

# 3. 実装
今回はローカル環境でComprehendを使用してみます。
対象のテキストはツイートデータではなく、
自分で定義したテキストのリストを利用していきます。

ツイートを使う場合は **<font color="skyblue">「#hashtag」</font>** のようなテキストを含むため、
必要に応じて事前にテキストクレンジングを行います。

## 3-1. テキストの準備
``` text.py
text_list = ["このゲームのストーリーはとても緻密で感動できる物語です",
             "グラフィックはとても荒く、キャラも魅力的ではありません",
             "昔このゲームに似たような作品をプレイしたことがあります",
             "戦闘中のBGMは好きですが、エンディングは残念な曲でした"]
```
今回は自身で手書きして準備しました。

上から<font color="red">"Positive"</font>, <font color="red">"Negative"</font>, <font color="red">"Neutral"</font>, <font color="red">"Mixed"</font>の順で
それぞれ分類されるようなイメージで書いています。

## 3-2. レスポンス取得
``` comprehend.py
comprehend = boto3.client("comprehend", "ap-northeast-1",
                          aws_access_key_id='*自分のid*',
                          aws_secret_access_key='*自分のsecret*')

response = comprehend.detect_sentiment(Text=text_list[0], LanguageCode="ja")
```
前回までに扱った **"s3"** などと同様にローカル環境では、
`boto3.client("service", "region", "key_id", "secret_key")`
以上4つの引数を与える必要があります。

ご自身の **"aws_access_key_id"** が未確認の方は
[前回の記事](https://qiita.com/kawanago_py/items/aabbe6c6d129c915f2ad#3-3-%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E7%92%B0%E5%A2%83%E3%81%8B%E3%82%89%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89 "【Python/AWS】第2回 LambdaとS3を利用してデータ取得を自動化する【データ分析】")からご確認をお願い致します。

そして`comprehend.detect_sentiment()`の引数に
`text_list[0]`を渡すだけで簡単に感情分析が完了します。
まずは先頭の文章を一つだけ渡しています。

**<font color="blue">▼comprehendのドキュメント▼</font>**

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/comprehend.html

## 3-3. responseの確認

結果として受け取ったresponseの中身を確認します。

``` respose.py
response
{'Sentiment': 'POSITIVE',
 'SentimentScore': {'Positive': 0.9992745518684387,
  'Negative': 5.8402565628057346e-05,
  'Neutral': 0.0006568512762896717,
  'Mixed': 1.0179862329096068e-05},
 'ResponseMetadata': {'RequestId': '03c3c31a-8e8a-4c9d-906a-a1cf934139f8',
  'HTTPStatusCode': 200,
  'HTTPHeaders': {'x-amzn-requestid': '03c3c31a-8e8a-4c9d-906a-a1cf934139f8',
   'content-type': 'application/x-amz-json-1.1',
   'content-length': '167',
   'date': 'Thu, 13 Oct 2022 04:40:38 GMT'},
  'RetryAttempts': 0}}
```
`"Sentiment"`：最も確信度の高い感情判別
`"SentimentScore"`：各判別の確信度

上から5行を見るだけで渡した文章の分析結果が
一目で分かるようになっています。

表記の問題で一瞬迷いますが、
結果は`"Positive":0.992...`となっており
**Positive**に分類されていることが分かります。

``` response_2.py
response["Sentiment"]                    #"POSITIVE"
response["SentimentScore"]["Positive"]   #0.9992745518684387
response["SentimentScore"]["Negative"]   #5.8402565628057346e-05
response["SentimentScore"]["Neutral"]    #0.0006568512762896717
response["SentimentScore"]["Mixed"]      #1.0179862329096068e-05
```
上記のようにすれば各要素を取り出せます。

``` for_list.py
res_list = [comprehend.detect_sentiment(Text=t, LanguageCode="ja") for t in text_list]
res_list[0]
```
複数の文章を含むリストに適用する場合は
上記のようにfor文でresponseを受けとったのちに、
`res_list[0]`のようにして各要素を確認できます。

``` result.py
for txt,res in zip(text_list, res_list):
    print("「{}」".format(txt))
    print("\tPos:{}, Neg:{}, Neu:{}, Mix:{}".format(round(res["SentimentScore"]["Positive"], 5),
                                                    round(res["SentimentScore"]["Negative"], 5), 
                                                    round(res["SentimentScore"]["Neutral"], 5),
                                                    round(res["SentimentScore"]["Mixed"], 5)))
""" 上記の結果
「このゲームのストーリーはとても緻密で感動できる物語です」
	Pos:0.99927, Neg:6e-05, Neu:0.00066, Mix:1e-05
「グラフィックはとても荒く、キャラも魅力的ではありません」
	Pos:6e-05, Neg:0.99974, Neu:8e-05, Mix:0.00012
「昔このゲームに似たような作品をプレイしたことがあります」
	Pos:0.13936, Neg:0.00556, Neu:0.8548, Mix:0.00029
「戦闘中のBGMは好きですが、エンディングは残念な曲でした」
	Pos:4e-05, Neg:0.00013, Neu:2e-05, Mix:0.99982
"""
```
他の文書も想定通りの分類になっており、
各分類の確信度もとても高い結果となりました。

# 4. 所感と今後の展望
## 4-1. 所感
AWSが提供する機械学習サービスの利用は今回が
初めてだったのですが、その簡単さに感動しました。

自身で感情分析をするさいには形態素解析などの
前処理から含めるとそれなりの工数がかかる作業です。

それが前述のコードのみで簡単に終わることに
驚きと同時に、素直に感動しておりました。

## 4-2. 今後の展望

今回挙動を確認したComprehendの機能を使って、
次回はGlueにコードを組み込む作業を行います。

またAWSの機械学習サービスには他にも、
**"物体検知", "レコメンド", "音声転記"** など
多様な機能があるため、それも利用してみたいです。

**<font color="blue">▼AWSの機械学習サービス資料▼</font>**

https://pages.awscloud.com/rs/112-TZM-766/images/C2-04.pdf

## 4-3. さいごに

本記事を読んで頂いてありがとうございました。
コメントや質問、お気軽に宜しくお願い致します。

# 次回の記事

https://qiita.com/kawanago_py/items/f2dd2da9b7c3618a5146

# その他の参考ページ

https://aws.amazon.com/jp/summits/tokyo-osaka-2019-report/

https://xp-cloud.jp/blog/2021/09/06/12183/