Amazon Comprehendを使ってS3にアップロードしたテキストを感情分析してみる

スポンサーリンク
ハンズオン
スポンサーリンク

はじめに

AWSのAIサービスを使ったハンズオンです。

商品・製品のレビューやアンケートの評価などで定量的な評価(★などの数値的な評価)はできているが、コメントの詳細までは評価できていない、といったケースは多いのではないでしょうか。

実際、コメントを1件1件確認し分析するのは手間がかかりますし、分析者の基準で評価するため、一定の評価をすることは難しいです。

今回紹介するAmazon ComprehendはテキストをAIで解析してくれるサービスで、コメントなどの自然言語から感情分析やキーフレーズ抽出などをすることができます。

今回はAmazon Comprehendの感情分析を使って、テキストを数値評価してみます。

このハンズオンでは、Amazon Comprehendを使って、S3にアップロードしたテキストファイルを感情分析し、結果を別のS3に格納するサービスを作成していきます。

前提条件

本ハンズオンでは、簡略化のため VPC を使用していません

内部的な通信を利用する場合はS3とComprehendのエンドポイントをVPCに作成してください。

環境構成

本ハンズオンの環境構成は以下の通りです。

料金目安

本ハンズオンの料金目安です。東京リージョン(ap-northeast-1)を利用する想定で計算しています。

サービス名 前提 無料枠
あり
無料枠
なし
S3 4KBのファイルを1日保管 <$0.001 <$0.001
Lambda 3秒の処理を10回実行 $0 <$0.001
Amazon Comprehend 1000文字分の文章を分析 $0 $0.001

無料枠あり/なしに関わらずほぼ無料です。


1. S3バケットの作成

AWS管理コンソールから「S3」の画面を開き、「バケットの作成」を選択します。

感情分析対象のテキストを格納するバケットと感情分析の結果を格納するS3バケットを作成します

※Lambdaと同じリージョンで作成してください。

3. Lambda関数の作成

AWS管理コンソールから「Lambda」の画面を開き、「関数の作成」を選択します。

任意の関数名、ランタイム:Node.js 22.x、アーキテクチャ:x86_64として、関数を作成します。

関数が作成できたら、設定タブを選択してください。一般設定から「編集」を選択します。

基本設定の画面が表示されます。タイムアウト値はデフォルトの3秒のままでもいいですが、分析する文章量によって数値を調整してください。
?
実行ロールにS3バケットとComprehendの実行権限を付与します。「IAMコンソールで****ロールの表示」を選択してください。

ロールの設定画面が表示されます。許可を追加から「インラインポリシーを作成」を選択してください。

ポリシーエディタが表示されます。JSONを選択して以下のポリシーを入力してください。入力後「次へ」を選択します。

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": "s3:GetObject",
			"Resource": "arn:aws:s3:::【感情分析対象のテキストを格納するバケット名】/*"
		},
		{
			"Effect": "Allow",
			"Action": "s3:PutObject",
			"Resource": "arn:aws:s3:::【感情分析の結果を格納するS3バケット名】/*"
		},
		{
			"Effect": "Allow",
			"Action": "comprehend:DetectSentiment",
			"Resource": "*"
		}
	]
}

確認して作成の画面で「ポリシーを作成」を選択します。

Lambdaの画面に戻って環境変数の追加をします。設定タブ>左メニューの「環境変数」を選択し「編集」を選択します。

環境変数を設定します。

キー
REGION リージョン名(ap-northeast-1など)
TARGETBUCKET 【感情分析の結果を格納するS3バケット名】

以下のソースを反映し、「index.mjs」を「index.js」に名前を変えてください。

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.handler = void 0;
const client_s3_1 = require("@aws-sdk/client-s3");
const client_comprehend_1 = require("@aws-sdk/client-comprehend");
const s3Client = new client_s3_1.S3Client({ region: process.env.REGION });
const comprehendClient = new client_comprehend_1.ComprehendClient({ region: process.env.REGION });
// S3の読み取り用ヘルパー関数
const streamToString = async (stream) => {
    const chunks = [];
    for await (const chunk of stream) {
        chunks.push(chunk);
    }
    return Buffer.concat(chunks).toString('utf-8');
};
// Lambdaハンドラー
const handler = async (event) => {
    try {
        // イベントからバケット名とオブジェクトキーを取得
        const sourceBucket = event.Records[0].s3.bucket.name;
        const sourceKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
        // S3からテキストファイルを取得
        const getObjectParams = { Bucket: sourceBucket, Key: sourceKey };
        const getObjectCommand = new client_s3_1.GetObjectCommand(getObjectParams);
        const s3Response = await s3Client.send(getObjectCommand);
        const fileContent = await streamToString(s3Response.Body);
        console.log('Original Content:', fileContent);
        // Amazon Comprehendで感情分析を実行
        const comprehendParam = {
            Text: fileContent,
            LanguageCode: "ja", // 日本語の場合は "ja"
        };
        const comprehendCommand = new client_comprehend_1.DetectSentimentCommand(comprehendParam);
        const sentiment = await comprehendClient.send(comprehendCommand);
        console.log("Sentiment analysis result:", sentiment);
        // 新しいS3バケットにアップロード
        const targetBucket = process.env.TARGETBUCKET; // 変換後のファイルを保存するバケット名
        const targetKey = `results/${sourceKey.replace(".txt", "")}_sentiment.json`;
        // 分析結果をJSON形式でS3に保存
        const putObjectParams = {
            Bucket: targetBucket,
            Key: targetKey,
            Body: JSON.stringify(sentiment, null, 2),
            ContentType: "application/json",
        };
        const putObjectCommand = new client_s3_1.PutObjectCommand(putObjectParams);
        await s3Client.send(putObjectCommand);
        console.log(`Sentiment analysis file uploaded to ${targetBucket}/${targetKey}`);
    }
    catch (error) {
        console.error('Error processing S3 event:', error);
        throw error;
    }
};
exports.handler = handler;

反映と名前の変更が完了したら、「Deploy」を選択します。

S3のアップロードをトリガーとする設定を追加します。「トリガーを追加」を選択します。

トリガーの設定でS3を選択し、バケットは【感情分析対象のテキストを格納するバケット名】を入力してください。イベントタイプは「PUT」、サフィックスは「.txt」を入力して「追加」を選択します。

3. 動作確認

私が最近買ってよかったものと悪かったものの感想をテキストで作成し、S3にアップロードして結果を確認してみます。(PRを含みます。)


よかったもの①:昇降式のPCデスク

一般的に売っている机は体に合わず、首・肩・背中が痛くなってしまいます。昇降式の机であれば高さ調整ができ、自分の体にあった高さに調整できます。丸1日机の前に座っていても体が痛くなることはなくとても快適です。気分転換で高さを上げて、立って仕事をすることもできます。


よかったもの②:ELECOM マウス EX-G

握るというより手を置いているだけといったイメージで、使っていてとても楽なマウスです。PC切り替えボタンがあり、複数端末を持っている人にとっても簡単に切り替え可能です。


よかったもの③:ふるさと納税 無洗米

ふるさと納税をしないと損!そんな感覚をお持ちではないでしょうか?とはいえ何を買ったらいいか分からない、特にほしいものがない、そんな方におすすめな商品です。お米は毎日消費しますし、都度都度買いに行くのは重いし手間です。ふるさと納税で毎月お米を配送してくれるので、買いに行く手間もなくなりますし、節税にもなります。


悪かったもの①:業務用スーパーで買ったロールキャベツ

業務用スーパーは安く買えてすごくお得ですが、この前かったロールキャベツは肉感がなく茹でたキャベツを食べているようでした。もう少しお肉のボリュームを増やしてもらえると嬉しいです。


悪かったもの②:iCleverのマウス

複数のPCを切り替えて利用できるマウスがほしかったので購入しましたが、突然カーソルが飛ぶことがあり、カーソルを見失うことが多々ありました。安くて高機能ではありますが、マウスとして使えないので、おすすめしません。


【感情分析対象のテキストを格納するバケット名】のバケットにこちらのテキストファイルをアップロードします。

しばらくすると、【感情分析の結果を格納するS3バケット名】のバケットのresult配下にファイルが生成されます。

内容を確認します。
json形式で出力されます。

例)よかったもの①:昇降式のPCデスクの解析結果

{
    "$metadata": {
        "httpStatusCode": 200,
        "requestId": "8a13abe5-cdba-4440-ab3c-92cf25026e30",
        "attempts": 1,
        "totalRetryDelay": 0
    },
    "Sentiment": "POSITIVE",
    "SentimentScore": {
        "Mixed": 0.00002504355325072538,
        "Negative": 0.00016921793576329947,
        "Neutral": 0.001096930238418281,
        "Positive": 0.9987088441848755
    }
}

例)悪かったもの①:業務用スーパーで買ったロールキャベツの解析結果

{
    "$metadata": {
        "httpStatusCode": 200,
        "requestId": "3471d0db-ed1b-4341-9729-a7b14c308665",
        "attempts": 1,
        "totalRetryDelay": 0
    },
    "Sentiment": "MIXED",
    "SentimentScore": {
        "Mixed": 0.8242824673652649,
        "Negative": 0.05673226714134216,
        "Neutral": 0.001565534621477127,
        "Positive": 0.1174197569489479
    }
}

各パラメタの意味は以下になります。

  • 肯定(Positive) : テキストは全体的にポジティブを表しています。
  • 否定(Negative) : テキストは全体的なネガティブを表しています。
  • 混合(Mixed) : テキストはポジティブとネガティブの両方を表現します。
  • 中立(Neutral) : テキストは肯定的または否定的を表していません。

「Sentiment」が全体のテキストを読み取った結果になります。

結果を表にまとめると以下になります。

商品 肯定
(Positive)
否定
(Negative)
混合
(Mixed)
中立
(Neutral)
総合評価
(Sentiment)
よかったもの①:昇降式のPCデスク 0.99871 0.00016 0.00003 0.00110 POSITIVE
よかったもの②:ELECOM マウス EX-G 0.99953 0.00004 0.00003 0.00040 POSITIVE
よかったもの③:ふるさと納税 無洗米 0.99238 0.00262 0.00291 0.00209 POSITIVE
悪かったもの①:業務用スーパーで買ったロールキャベツ 0.11741 0.05673 0.82428 0.00157 MIXED
悪かったもの②:iCleverのマウス 0.00017 0.35842 0.64120 0.00020 MIXED

あえてコメントにポジティブな文章、ネガティブな文章を入れてみましたが、よかったものについては肯定的な評価をしてくれています。

面白い結果となったのは、悪かったものが混合(いい面も悪い面もある)の評価になったことです。「業務用スーパーで買ったロールキャベツ」は安いという面がポジティブに評価され、「iCleverのマウス」は安くて高機能がポジティブに働いたようです。ただ「iCleverのマウス」はおすすめしないといった表現がネガティブに働き否定の数値の値が高くなっていることもわかります。

まとめ

このハンズオンではテキストを解析できるAmazon Comprehendを使ってみました。

このハンズオンを応用することで、以下が可能です。

  • 商品のレビューやアンケートの集計などのコメントを肯定的か否定的か簡単に評価でき、分類作業が簡単にできるようになる
  • コールセンターなどの音声をリアルタイムで分析し、否定的な値が高くなったら別の有識者にエスカレーションする

ぜひ応用してみてください。

以下AWSのAIサービス関連のおすすめ書籍です。

 

 

タイトルとURLをコピーしました