AQ Tech Blog

Amazon Comprehendで飲食店の口コミを感情分析

作成者: shohei.ikeguchi|2024年10月18日

 

はじめに

クラウドインテグレーション部の池口です。

本記事ではAmazon Comprehendを使用して、S3に保存された複数のテキストファイルの内容について感情分析を行う方法について記載します。
詳細は後述しますが、例として架空のレストランに対する口コミを分析していきます。

Amazon Comprehend とは

Amazon Comprehend は、AWSが提供する自然言語処理(NLP)サービスで、テキストデータから意味や関係性を自動的に抽出・解析することを可能にするツールです。
このサービスは、機械学習モデルを使用して、ユーザーが提供するテキストの中から「感情分析」「エンティティ認識」「トピックモデリング」等を行うことが可能です。

詳細はAmazon Comprehend の特徴をご確認ください。

感情分析 とは

感情分析(Sentiment Analysis)は、テキストデータからその感情的な傾向を自動的に識別する機能です。
顧客フィードバックやレビュー等を分析し、ビジネスインサイトを得ることができます。

詳細は感情分析とは何ですか?をご確認ください。

検証

今回の検証の概要を以下に記載します。

 

シチュエーション

今回の検証では架空の飲食店「アジアンレストランAQ」の口コミをAmazon Comprehendにて感情分析を行います。
計4件の口コミの内3件は良い評価、1件は悪い評価の口コミとして、 以下の4つの文章をそれぞれテキストファイルでS3に保存しています。

■レビュー1
先日「アジアンレストランAQ」に初めて訪れました。
メニューはどれも本格的で、特にトムヤムクンとパッタイが絶品でした!
ピリッと辛いけれど、深みのあるスープに感動。
スタッフも親切で、おすすめメニューを丁寧に教えてくれました。
アジアの雰囲気に浸りながら食事ができて、大満足です。また絶対に来たいです。

■レビュー2
アジアンレストランAQは、インドネシア、タイ、ベトナムなど、様々な国の料理が楽しめるのが魅力です。
家族で行きましたが、辛さの調整もしてくれて子供も喜んで食べていました。
店内のインテリアもアジアンテイストでおしゃれで、まるで旅行に来た気分に。
デザートのマンゴースティッキーライスもとても美味しかったです!

■レビュー3
友達とランチで利用しました。
セットメニューがとても充実していて、値段以上の満足感です。
グリーンカレーを注文したのですが、程よい辛さとココナッツミルクの甘みが絶妙でした。
スタッフのサービスも気持ちよく、料理が出てくるスピードも速くてびっくり。
また次回は夜のディナータイムに行って、他のメニューも試してみたいです。

■レビュー4
友人の勧めで「アジアンレストランAQ」に行きましたが、正直がっかりしました。
料理は全体的に塩辛すぎて、本来のアジア料理の繊細な風味が感じられませんでした。
特にグリーンカレーは辛さが強すぎて、味のバランスが崩れているように感じました。
また、週末で混雑していたのは理解できますが、料理が出てくるまでかなり時間がかかり、スタッフも忙しそうでサービスも行き届いていませんでした。 期待していただけに残念です。

S3内の上記のテキストファイルをAmazon Comprehendを使用して感情分析を行います。
Amazon Comprehendに直接テキストを入力して分析を行うことも可能ですが、
今回はS3内の複数のテキストファイルに対して感情分析を行うため、
Lambdaを使用して各ファイルの感情分析を行い、分析結果を1つのファイルにまとめてS3に格納します。

 

構成図

検証の構成図は以下になります。
Lambdaは手動で実行します。
また、口コミのテキストファイルと感情分析結果は同一のS3バケット内でフォルダを分けて格納します。

サービス設定

S3

inputフォルダには口コミのテキストファイルを4つ格納します。
outputフォルダには感情分析結果が格納されるため、空のフォルダとして作成しておきます。
バケット名は「ikeguchi-test-bucket-01」を使用します。

 

 

Lambda

続いてLambdaを設定します。
S3バケットのinputフォルダ内の全てのファイルに対して、
Amazon Comprehendで感情分析を行い、結果をoutputフォルダに保存します。

また、実行完了までに5秒程の時間を要するため、
Lambdaのデフォルトのタイムアウト値「3秒」だとタイムアウトになってしまいました。
今回の検証ではタイムアウト値を「1分」に変更しています。

コードの内容は以下になります。

 

import boto3
import json

def lambda_handler(event, context):
# Amazon ComprehendとS3クライアントを作成
comprehend = boto3.client('comprehend')
s3 = boto3.client('s3')

# 読み込むプレフィックスを指定
bucket_name = 'ikeguchi-test-bucket-01'
input_prefix = 'input/' # 読み込みたいファイルがあるプレフィックス
output_prefix = 'output/' # 結果を保存したいプレフィックス

# プレフィックス内のオブジェクトをリストアップ
response = s3.list_objects_v2(Bucket=bucket_name, Prefix=input_prefix)

if 'Contents' not in response:
return {
'statusCode': 404,
'body': json.dumps('No files found in the specified input prefix.')
}

# 感情分析結果を保存するリスト
sentiment_results = []

# プレフィックス内のすべてのファイルに対して処理を実行
for obj in response['Contents']:
file_key = obj['Key']

# テキストファイルのみ処理
if file_key.endswith('.txt'):
# ファイル内容を取得
s3_object = s3.get_object(Bucket=bucket_name, Key=file_key)
file_content = s3_object['Body'].read().decode('utf-8')

# ファイルの内容を行ごとに分割
texts = file_content.splitlines()

# 各行に対して感情分析を実行
for text in texts:
if text.strip(): # 空行を無視
response = comprehend.detect_sentiment(Text=text, LanguageCode='ja')
sentiment_results.append({
'file': file_key,
'text': text,
'sentiment': response['Sentiment'],
'sentiment_score': response['SentimentScore']
})

# 感情分析結果をS3に保存
result_file_name = 'sentiment-analysis-results.json'

# 文字化け対策
json_data = json.dumps(sentiment_results, ensure_ascii=False, indent=4)

s3.put_object(
Body=json_data.encode('utf-8'), # UTF-8でエンコード
Bucket=bucket_name,
Key=f'{output_prefix}{result_file_name}'
)

return {
'statusCode': 200,
'body': json.dumps(f'Sentiment analysis results saved to s3://{bucket_name}/{output_prefix}{result_file_name}')
}

 

また、IAMロールで以下の権限を付与します。
・inputフォルダに対してのList/Get
・outputフォルダに対してのPut
・Amazon Comprehendに対して感情分析を実行
今回の検証でロールに設定したポリシーは以下になります。

 

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::ikeguchi-test-bucket-01",
"arn:aws:s3:::ikeguchi-test-bucket-01/input/*"
]
},
{
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::ikeguchi-test-bucket-01/output/*"
]
},
{
"Effect": "Allow",
"Action": [
"comprehend:DetectSentiment"
],
"Resource": "*"
}
]
}

 

結果確認

Lambdaを手動で実行した結果がS3バケットのoutputフォルダに格納されているか確認します。
想定通り「sentiment-analysis-results.json」というファイルが作成されています。 

 

 

次にファイルの内容を確認します。

 

[
{
"file": "input/review1.txt",
"text": "先日「アジアンレストランAQ」に初めて訪れました。メニューはどれも本格的で、特にトムヤムクンとパッタイが絶品でした!ピリッと辛いけれど、深みのあるスープに感動。スタッフも親切で、おすすめメニューを丁寧に教えてくれました。アジアの雰囲気に浸りながら食事ができて、大満足です。また絶対に来たいです。",
"sentiment": "POSITIVE",
"sentiment_score": {
"Positive": 0.9998327493667603,
"Negative": 1.6875443179742433e-05,
"Neutral": 0.0001371667458442971,
"Mixed": 1.3137219866621308e-05
}
},
{
"file": "input/review2.txt",
"text": "アジアンレストランAQは、インドネシア、タイ、ベトナムなど、様々な国の料理が楽しめるのが魅力です。家族で行きましたが、辛さの調整もしてくれて子供も喜んで食べていました。店内のインテリアもアジアンテイストでおしゃれで、まるで旅行に来た気分に。デザートのマンゴースティッキーライスもとても美味しかったです!",
"sentiment": "POSITIVE",
"sentiment_score": {
"Positive": 0.9991946816444397,
"Negative": 1.5041106053104158e-05,
"Neutral": 0.0007850348483771086,
"Mixed": 5.2885520744894166e-06
}
},
{
"file": "input/review3.txt",
"text": "友達とランチで利用しました。セットメニューがとても充実していて、値段以上の満足感です。グリーンカレーを注文したのですが、程よい辛さとココナッツミルクの甘みが絶妙でした。スタッフのサービスも気持ちよく、料理が出てくるスピードも速くてびっくり。また次回は夜のディナータイムに行って、他のメニューも試してみたいです。",
"sentiment": "POSITIVE",
"sentiment_score": {
"Positive": 0.9998639822006226,
"Negative": 3.727452349266969e-05,
"Neutral": 3.8582755223615095e-05,
"Mixed": 6.005866453051567e-05
}
},
{
"file": "input/review4.txt",
"text": "友人の勧めで「アジアンレストランAQ」に行きましたが、正直がっかりしました。料理は全体的に塩辛すぎて、本来のアジア料理の繊細な風味が感じられませんでした。特にグリーンカレーは辛さが強すぎて、味のバランスが崩れているように感じました。また、週末で混雑していたのは理解できますが、料理が出てくるまでかなり時間がかかり、スタッフも忙しそうでサービスも行き届いていませんでした。期待していただけに残念です。",
"sentiment": "NEGATIVE",
"sentiment_score": {
"Positive": 4.969825022271834e-05,
"Negative": 0.9998505115509033,
"Neutral": 4.8490815970581025e-05,
"Mixed": 5.122588845551945e-05
}
}
]

 

各テキストに対して感情分析結果が記載されています。
各項目の概要を以下に記載します。

 

項目 説明
file 対象のファイル
text 実際に分析されたテキストの内容
sentiment Amazon Comprehendによる感情分析の結果
※分析したテキストが「POSITIVE(ポジティブ)」「NEGATIVE(ネガティブ)」「NEUTRAL(中立)」、あるいは「MIXED(混合)」のどれかに分類されます。
sentiment_score 感情ごとのスコア
※それぞれの感情の確率を0〜1の範囲で表しており、合計するとほぼ1になります。
Positive ポジティブな感情の度合い
Negative ネガティブな感情の度合い
Neutral 中立的な感情の度合い
Mixed 混合した感情の度合い

 

review1.txtの結果を例にすると、Positiveのスコアが1に近いことが分かります。
よってsentimentの項目もPositiveとして判定されています。

Negative、Mixedが1を超えているように見えるかもしれませんが、 指数表記となっているため、
数値的には非常に小さなものとなります。

指数表記については指数表記(Wikipedia)をご確認ください。

まとめ

今回はAmazon Comprehendを使用して感情分析を行いました。
私自身はAWS Certified Machine Learning - Specialtyの試験対策等でたまに目にする程度で、
実際に業務で活用した経験は無かったのですが、プログラミングやAIの知識が豊富でなくても
比較的容易に感情分析を行うことができて、フワッとしていた知識が具体化できたと感じました。

今回は単純に感情分析を行うまでをゴールとしましたが、
次回の記事では他のAWSサービスを使用して、分析結果の視認性を向上させる仕組みを試してみようと思いますので、
そちらも楽しみにお待ちください!