【自然言語処理】Microsoft Azure Text Analyticsで日本語テキストの分析【Python】

こんにちは。今日は、Microsoft AzureのText Analyticsサービスを使って日本語の感情分析を行ってみたいと思います。グローバルのクラウドサービスで、日本語に対応したテキスト分析サービスって結構珍しい気がしたので、どれくらい使えるものなのか、確認してみたいと思った次第です。

それでは早速まいります!

Microsoft Azure Text Analyticsで分析できること

Text Analyticsを利用すると、以下のことができるようになります。以下で、それぞれの機能についてもう少し詳細に確認していきます。

  • センチメント分析(感情分析)/意見マイニング
  • オピニオンマイニング
  • 言語検出
  • キーフレーズの抽出
  • 名前付きエンティティの認識

また、日本語に対応しているかどうかは、タスクによって異なります。以下のサイトから確認するようにしてください。例えば、2020年10月時点では、感情分析、キーフレーズの抽出、言語検出などは、日本語に対応していますが、オピニオン分析はプレビュー機能で英語のみに対応しているようです。

https://docs.microsoft.com/ja-jp/azure/cognitive-services/text-analytics/language-support?tabs=sentiment-analysis

ここからは、Text Analyticsを利用するまでの手順の流れに沿って解説していきます。

Microsoft Azureアカウントの取得

このステップは割愛します。

Text Analyticsリソースの作成

続いて、Text Analyticsリソースを作成します。Text Analyticsリソースは、「リソースの作成」から、「Text Analytics」で検索すると出てきます。

リソースの作成にあたって特別な設定は特に不要です。下記のような設定のみです。

リソースの作成が完了したら、「キーとエンドポイント」ブレードから、キーとエンドポイントの情報を確認します。この2つの情報が、Text Analytics APIを利用する際に必要な情報となります。

PythonでText Analytics APIを使ってみる

ここからの手順は、公式ページで紹介されているサンプルコードに基づいています。また、実行環境として、Azure Machine Learning StudioのJupyter Labを利用しています。

また、言語はPythonです。

https://docs.microsoft.com/ja-jp/azure/cognitive-services/text-analytics/quickstarts/text-analytics-sdk?tabs=version-3&pivots=programming-language-python

認証

Text Analytics APIを利用するには、はじめに認証が必要です。

key = "xxx"
endpoint = "xxx"

from azure.ai.textanalytics import TextAnalyticsClient
from azure.core.credentials import AzureKeyCredential

def authenticate_client():
    ta_credential = AzureKeyCredential(key)
    text_analytics_client = TextAnalyticsClient(
            endpoint=endpoint, 
            credential=ta_credential)
    return text_analytics_client

client = authenticate_client()

認証が終わったら、いよいよ個別のAPIを試してみます。

感情分析

まずは感情分析です。下の関数で呼び出している、analyze_sentiment関数が、Text Analyticsのメソッドです。language=”ja”と指定することで日本語の感情分析が可能になります。

def sentiment_analysis_example(client):

    documents = ["今日の昼食は美味しかった。昨日の夕食は美味しくなかった。一昨日の朝食はおいしかった。"]
    response = client.analyze_sentiment(documents=documents,language="ja")[0]
    print("Document Sentiment: {}".format(response.sentiment))
    print("Overall scores: positive={0:.2f}; neutral={1:.2f}; negative={2:.2f} \n".format(
        response.confidence_scores.positive,
        response.confidence_scores.neutral,
        response.confidence_scores.negative,
    ))
    for idx, sentence in enumerate(response.sentences):
        print("Sentence: {}".format(sentence.text))
        print("Sentence {} sentiment: {}".format(idx+1, sentence.sentiment))
        print("Sentence score:\nPositive={0:.2f}\nNeutral={1:.2f}\nNegative={2:.2f}\n".format(
            sentence.confidence_scores.positive,
            sentence.confidence_scores.neutral,
            sentence.confidence_scores.negative,
        ))
          
sentiment_analysis_example(client)

結果はこんな感じです。文章全体の感情スコアと、各文章の感情スコアが得られました。「美味しくなかった」を含む文がneutralとなっている点はちょっと気になりますが、とはいえNegativeスコアは高めに出ており、全体的には感覚から大きくずれたものではなさそうです。

このメソッドから取得できる情報について、もう少し確認しておこうと思います。

documents = ["今日の昼食は美味しかった。昨日の夕食は美味しくなかった。一昨日の朝食はおいしかった。"]
response = client.analyze_sentiment(documents=documents,language="ja")[0]

この戻りはlistになります。中身をみてみると、

  • 全体のスコア
  • 各文章のスコア

が返ってきていることがわかります。

今回、この感情スコアの妥当性についての詳細な比較検証はしていないですが、今後時間を見つけて、このAPIのスコア算出方法に関する仕様や、手元で作成した辞書ベース/Deep Learningベースの感情分析モデルのスコアとの比較を行ってみたいものです。

オピニオンマイニング

オピニオン分析とは、あるトピックに関する主観意見を取りまとめて、賛成・反対やポジティブ・ネガティブに分類して可視化することができます。

こちらは、2020年10月現在英語のみの対応ですが、以下のような分析が可能です。

def sentiment_analysis_with_opinion_mining_example(client):

    documents = [
        "The food and service were unacceptable, but the concierge were nice",
        "The rooms were beautiful but dirty. The AC was good and quiet, but the elevator was broken"
    ]

    result = client.analyze_sentiment(documents, show_opinion_mining=True)
    doc_result = [doc for doc in result if not doc.is_error]

    positive_reviews = [doc for doc in doc_result if doc.sentiment == "positive"]
    negative_reviews = [doc for doc in doc_result if doc.sentiment == "negative"]

    positive_mined_opinions = []
    mixed_mined_opinions = []
    negative_mined_opinions = []

    for document in doc_result:
        print("Document Sentiment: {}".format(document.sentiment))
        print("Overall scores: positive={0:.2f}; neutral={1:.2f}; negative={2:.2f} \n".format(
            document.confidence_scores.positive,
            document.confidence_scores.neutral,
            document.confidence_scores.negative,
        ))
        for sentence in document.sentences:
            print("Sentence: {}".format(sentence.text))
            print("Sentence sentiment: {}".format(sentence.sentiment))
            print("Sentence score:\nPositive={0:.2f}\nNeutral={1:.2f}\nNegative={2:.2f}\n".format(
                sentence.confidence_scores.positive,
                sentence.confidence_scores.neutral,
                sentence.confidence_scores.negative,
            ))
            for mined_opinion in sentence.mined_opinions:
                aspect = mined_opinion.aspect
                print("......'{}' aspect '{}'".format(aspect.sentiment, aspect.text))
                for opinion in mined_opinion.opinions:
                    print("......'{}' opinion '{}'".format(opinion.sentiment, opinion.text))
        print("\n")
          
sentiment_analysis_with_opinion_mining_example(client)

文章全体でのNegative/Positiveと、それぞれに判定された各単語を可視化することができます。面白い・・

言語検出

def language_detection_example(client):
    try:
        documents = ["なんでやねん"]
        response = client.detect_language(documents = documents, country_hint = 'us')[0]
        print("Language: ", response.primary_language.name)

    except Exception as err:
        print("Encountered exception. {}".format(err))
language_detection_example(client)

実行結果:

Language:  Japanese

名前付きエンティティの認識

こちらは、

def entity_recognition_example(client):

    try:
        documents = ["I went to travel with my family by car last week."]
        result = client.recognize_entities(documents = documents)[0]

        print("Named Entities:\n")
        for entity in result.entities:
            print("\tText: \t", entity.text, "\tCategory: \t", entity.category, "\tSubCategory: \t", entity.subcategory,
                    "\n\tConfidence Score: \t", round(entity.confidence_score, 2), "\tOffset: \t", entity.offset, "\n")

    except Exception as err:
        print("Encountered exception. {}".format(err))
entity_recognition_example(client)

実行結果:

Named Entities:

	Text: 	 car 	Category: 	 Product 	SubCategory: 	 None 
	Confidence Score: 	 0.78 	Offset: 	 35 

	Text: 	 last week 	Category: 	 DateTime 	SubCategory: 	 DateRange 
	Confidence Score: 	 0.8 	Offset: 	 39 

CarはProduct、last weekはDateTimeと認識されました!

一方で、同じ英語を日本語で分析にかけてみると・・・

def entity_recognition_example(client):

    try:
        documents = ["先週末は家族と車で旅行に出かけた。"]
        result = client.recognize_entities(documents = documents,language="ja")[0]

        print("Named Entities:\n")
        for entity in result.entities:
            print("\tText: \t", entity.text, "\tCategory: \t", entity.category, "\tSubCategory: \t", entity.subcategory,
                    "\n\tConfidence Score: \t", round(entity.confidence_score, 2), "\tOffset: \t", entity.offset, "\n")

    except Exception as err:
        print("Encountered exception. {}".format(err))
entity_recognition_example(client)

実行結果:

Named Entities:

何も検出されませんでした・・。(日本語のエンティティ検出性能は、もしかするとまだ高くないのかもしれない・・)

キーフレーズの抽出

最後に、キーフレーズの抽出です。ちょっとこのタスクは勉強不足で仕組みに関する理解がなく、コードを流してみるだけですが・・

def key_phrase_extraction_example(client):

    try:
        documents = ["今日は、朝ご飯を食べた後、公園に散歩に出かけた。天気が良くとても気持ちよかった。"]

        response = client.extract_key_phrases(documents = documents,language="ja")[0]

        if not response.is_error:
            print("\tKey Phrases:")
            for phrase in response.key_phrases:
                print("\t\t", phrase)
        else:
            print(response.id, response.error)

    except Exception as err:
        print("Encountered exception. {}".format(err))
        
key_phrase_extraction_example(client)

実行結果:

Key Phrases:
		 公園
		 天気
		 気持ち
		 散歩

以上、Azure Text Analysisサービスで日本語のテキスト分析を試してみました。

AWSやGCPの同様のテキスト分析サービスでできること、日本語対応有無についても調べてみて、比較をしてみたいと思いました。

また、自分のブログでは、SNS (Twitter)のテキストデータ抽出や、手動でのテキストマイニング(極性辞書を使う方法)についても試してみていますので、ご興味があればご覧ください!

本日も最後までご覧いただきありがとうございました!

おしまい

この記事を気に入っていただけたらシェアをお願いします!

ABOUT US

Yuu113
初めまして。Yuu113と申します。 兵庫県出身、東京でシステムエンジニアをしております。現在は主にデータ分析、機械学習を活用してビジネスモデリングに取り組んでいます。日々学んだことや経験したことを整理していきたいと思い、ブログを始めました。旅行、カメラ、IT技術、江戸文化が大好きですので、これらについても記事にしていきたいと思っています。