第7回 テキストの感情認識

一覧に戻る

第7回 テキストの感情認識

今回のテーマはテキストの感情認識です。テキストの感情認識とはテキストデータを読み込み、そのテキストに書かれている喜怒哀楽などの感情を分析する技術です。

今回の実装のソースコードはこちらからダウンロードできます。

目次

解説動画

概要

  • 実装内容
    • Microsoft AzureのText Analyticsを使用して、文章のネガポジ判定(文章がネガティブなのか、ポジティブなのか、またはどちらでもないのかを判定する)を行います。
  • 実装環境
    • Google Colaboratoryを使用します。Google Colaboratoryに関する説明はこちらをご覧ください。
  • サンプルデータ
    • こちらからダウンロードしてください。

Text Analytics

今回使用するクラウドAPIはMicrosoft AzureのText Analyticsです。
Text Analyticsは文章から固有表現を抽出したり、感情の分析を行うことができる、テキスト分析用のAPIです。

利用にはAzureのリソースを作成する必要があります。リソースはこちらから作成できます。(事前にAzureの無料アカウントを作成する必要があります。)

入力

テキスト感情認識を行いたい文章を次のようなJSON形式でHTTP通信のリクエストボディに与えます。

documents = {
    'documents': [
        {
            'id': '1',
            'language': 'ja',
            'text': 'いろはにほへと、ちりぬるを。わかよたれそ、つねならむ。'
        },
        {
            'id': '2',
            'language': 'ja',
            'text': 'うゐのおくやま、けふこえて。あさきゆめみし、ゑひもせす。'
        }
    ]
}
キー値の型内容
id文字列文章の識別番号
language文字列解析対象の言語。【例】’ja’:日本語、’en’:英語
text文字列解析対象の文章

出力

  • 文章全体の感情認識結果と文章中の個々の文の感情認識結果をスコア(0~1)とラベルで返す
    • スコアは、ネガティブ、ニュートラル、ポジティブの3種類について出され、それぞれの値は0~1。合計で1
    • ラベルは、ネガティブ、ニュートラル、ポジティブ、混合



APIリファレンス:
https://westcentralus.dev.cognitive.microsoft.com/docs/services/TextAnalytics-v3-1/operations/Sentiment

実装

ファイルのアップロード

認識用のファイルをGoogle Colaboratoryにアップロードします。ファイルのアップロード方法についてはこちらをご覧ください。

ライブラリのインポート

必要なライブラリをインポートします。

from pprint import pprint   # JSONを整形して表示するために使用

import pandas as pd         # データを表形式で扱うために使用
import requests             # HTTP通信に使用

Azureの接続設定

サブスクリプションキーとエンドポイントURLを定義します。サブスクリプションキーは各自で設定した値を使用してください。サブスクリプションキーとエンドポイントURLの説明は以下になります。

項目内容
サブスクリプションキーAPIを使用するためのキー
エンドポイントURLリクエストの送信先URL
subscription_key = 'XXXXX'
endpoint_url = 'https://aiseminar-4th-text.cognitiveservices.azure.com/text/analytics/v3.1/sentiment'

入力用テキストの準備

入力用のテキストを準備します。テキストファイルを読み込み、ファイルの改行コードを除去して1行の文にします。

# ファイル読み込み
with open('sample_sentences.txt', 'r', encoding='CP932') as f:
    sentences = f.readlines()

# 改行コードを削除
sentences = [sentence.replace('\n', '') for sentence in sentences]

# 各文を1行に連結
sentences_joined = ''.join(sentences)
sentences_joined
本書は機械学習について入門者にも分かりやすく書かれた良書だと思います。特に最近話題の深層学習に関する記述が豊富であり、理論だけでなく実装する際の勘所も載っていて、とても参考になります。しかしながら随所に誤記があるのが残念です。早期に改訂版が出ることを期待します。それを除けば、とてもおすすめの一冊だと思います。

HTTPリクエストの設定

ここでHTTPリクエストのヘッダとボディの内容を定義します。リクエストはJSONで送信するので、ヘッダのContent-Typeはapplication/jsonとします。Ocp-Apim-Subscription-Keyにはサブスクリプションキーの値を入れます。また、ボディのdocumentsには各ドキュメントの情報(テキストのID、言語、テキスト)を入れます。

# リクエストヘッダ
headers = {'Content-Type': 'application/json',
           'Ocp-Apim-Subscription-Key': subscription_key}

# リクエストボディ
documents_json = {'documents': [
    {
        'id': '1',
        'language': 'ja',
        'text': sentences_joined
    }
]}
pprint(documents_json)
{'documents': [{'id': '1', 'language': 'ja', 'text': '本書は機械学習について入門者にも分かりやすく書かれた良書だと思います。特に最近話題の深層学習に関する記述が豊富であり、理論だけでなく実装する際の勘所も載っていて、とても参考になります。しかしながら随所に誤記があるのが残念です。早期に改訂版が出ることを期待します。それを除けば、とてもおすすめの一冊だと思います。'}]}

リクエストの送信

リクエストの送信をrequests.postメソッドで行います。引数にはエンドポイントのURLと先ほど設定したリクエストヘッダ、リクエストボディが入ります。

response = requests.post(endpoint_url, headers=headers, json=documents_json)

レスポンスの確認

レスポンスの値を変数responseに格納したので、値を確認します。まず、ステータスコードを見て、リクエストが成功しているかを確認します。

response.status_code
200

ステータスコードは200なので、リクエストは成功です。出力の結果を見てみます。

sentiments = response.json()
pprint(sentiments)
{'documents': [{'confidenceScores': {'negative': 0.27, 'neutral': 0.06, 'positive': 0.67}, 'id': '1', 'sentences': [{'confidenceScores': {'negative': 0.01, 'neutral': 0.03, 'positive': 0.96}, 'length': 35, 'offset': 0, 'sentiment': 'positive', 'text': '本書は機械学習について入門者にも分かりやすく書かれた良書だと思います。'}, {'confidenceScores': {'negative': 0.02, 'neutral': 0.08, 'positive': 0.9}, 'length': 57, 'offset': 35, 'sentiment': 'positive', 'text': '特に最近話題の深層学習に関する記述が豊富であり、理論だけでなく実装する際の勘所も載っていて、とても参考になります。'}, {'confidenceScores': {'negative': 0.99, 'neutral': 0.0, 'positive': 0.01}, 'length': 21, 'offset': 92, 'sentiment': 'negative', 'text': 'しかしながら随所に誤記があるのが残念です。'}, {'confidenceScores': {'negative': 0.06, 'neutral': 0.68, 'positive': 0.27}, 'length': 18, 'offset': 113, 'sentiment': 'neutral', 'text': '早期に改訂版が出ることを期待します。'}, {'confidenceScores': {'negative': 0.06, 'neutral': 0.11, 'positive': 0.83}, 'length': 24, 'offset': 131, 'sentiment': 'positive', 'text': 'それを除けば、とてもおすすめの一冊だと思います。'}], 'sentiment': 'mixed', 'warnings': []}], 'errors': [], 'modelVersion': '2021-10-01'}

レスポンスの値もJSON形式になっています。読みやすいように出力結果を整形します。

出力結果の整形

JSONから各感情のスコアとラベルを取り出します。レスポンスのスコアとラベルは文章全体のものと各文章ごとのものがあります。まず、文章全体の方を取り出します。

# 感情スコアを取得
document_scores = sentiments['documents'][0]['confidenceScores']
negative = document_scores['negative']
neutral = document_scores['neutral']
positive = document_scores['positive']

# 感情ラベルを取得
sentiment = sentiments['documents'][0]['sentiment']

# 感情スコアと感情ラベルを表示
print(f'negative={negative}, neutral={neutral}, positive={positive}, sentiment={sentiment}')
negative=0.27, neutral=0.06, positive=0.67, sentiment=mixed

文章全体ではpositiveが一番高く、0.67でした。また、ラベルはmixedでpostiveとnegativeの混合であることが分かりました。

次に各文章ごとのスコアとラベルを取得してpandasにより表形式にします。

# 空のデータフレームを生成
df = pd.DataFrame(index=[], columns=['sentence', 'negative', 'neutral', 'positive', 'sentiment'])

# レスポンスの中身をループ
for i in range(len(sentiments['documents'][0]['sentences'])):
    # 各感情スコアを取得
    scores = sentiments['documents'][0]['sentences'][i]['confidenceScores']
    negative = scores['negative']
    neutral = scores['neutral']
    positive = scores['positive']

    # 感情ラベルを取得
    sentiment = sentiments['documents'][0]['sentences'][i]['sentiment']

    # データフレームに追加
    df = df.append(pd.Series([sentences[i], negative, neutral, positive, sentiment], index=df.columns), ignore_index=True)
df
 sentencenegativeneutralpositivesentiment
0本書は機械学習について入門者にも分かりやすく書かれた良書だと思います。0.010.030.96positive
1特に最近話題の深層学習に関する記述が豊富であり、理論だけでなく実装する際の勘所も載っていて、…0.020.080.9positive
2しかしながら随所に誤記があるのが残念です。0.9900.01negative
3早期に改訂版が出ることを期待します。0.060.680.27neutral
4それを除けば、とてもおすすめの一冊だと思います。0.060.110.83positive

肯定的な文はpositiveが高く、否定的な文はnegativeが高くなっていることが分かります。また肯定でも否定でもないような表現はneutralが一番高くなっており、判別できていることが分かります。


今回はこれで以上になります。次回のテーマは意図理解・チャットボットの予定です。

最後までお読みいただきありがとうございました。それでは引き続き次回もよろしくお願いいたします。


一覧に戻る