GCPのNatural Language APIを使ってみた

こんにちは!エス・エム・エス エンジニアの柿埜です。
私が所属するチームは、社内データ活用の基盤の構築を担っています。
蓄積してきたテキストデータの利用に関して、感情分析(ポジティブ・ネガティブの分析) をしてはどうか、という話があがりました。
弊社サービスのデータ基盤構築には、GCP(Google Cloud Platform)を採用しています。
そのGCPに「Natural Language API」というサービスがあるので、それを使ってみようではないかという運びになり、どういうものかを試してみました。
今回の記事では、その際に分かったNatural Language APIの使用方法、試してみた結果を紹介します。

Natural Language APIとは?

「Natural Language API」はGCPの「Cloud Natural Language」シリーズのひとつです。
「Cloud Natural Language」には、

  • AutoML Natural Language
  • Natural Language API

という2つの代表的なサービスがあります。
前者は機械学習モデルを独自に学習させることができるもので、後者はすでに学習済みのモデルを使用するお手軽なものになっています。

 

Natural Language APIでなにができる?

Natural Language APIには下記の機能が備わっています。

  • 感情分析(文章のポジティブ・ネガティブの判定)
  • エンティティ分析(単語の分析。名詞の種類・単語の重要度等)
  • エンティティ感情分析(単語のポジティブ・ネガティブの判定)
  • 構文解析(形態素間の関連、係り受けを分析)
  • コンテンツの分類(文章のジャンルを分析)

AutoML Natural Languageに比べるとお手軽なサービスではあるのですが、多くのことができますね。
今回は「感情分析」と「エンティティ感情分析」をpythonで実装してみます。

 

環境構築

GCPのプロジェクトでAPIを有効にする

APIを使用するプロジェクトに移動し、メニューから
「APIとサービス」-> 「APIとサービスの有効化」->「Cloud Natural Language API」で検索
という順で進みます。
以下の表示が出たら「有効にする」をクリックします。

Natural Language API用サービスアカウントの設定

「IAMと管理」-> 「サービスアカウント」-> 「サービスアカウントを作成」
と進み、以下のような設定でサービスアカウント(…★)を作成します。

項目 内容
サービスアカウント名 demo-natural-language-api ※サンプル
サービスアカウントの説明 Natural Language APIデモ用 ※サンプル
このサービスアカウントにプロジェクトのアクセスを許可する 設定しない
ユーザーにこのサービスアカウントへのアクセスを許可  設定しない

 

次に、このサービスアカウントに権限を付与しましょう。
「IAMと管理」-> 「IAM」
と進み、
★のサービスアカウント名@プロジェクト名.iam.gserviceaccount.com」の編集画面から
AutoML管理者」というロールを付与します。
※公式ドキュメントには「オーナー」に設定すると書いてありますが、より権限の範囲が狭い「AutoML管理者」でもAPIが動くことを確認済みです。

次に、サービスアカウントのキーを作成します。

「IAMと管理」-> 「サービスアカウント」
と進み、
★のサービスアカウント名@プロジェクト名.iam.gserviceaccount.com」の右のメニューから「鍵を作成」を選択します。
形式をJSONにして鍵を作成し、自動でローカルにダウンロードされるのを待ちましょう。

最後に、ローカルの設定です。
ダウンロードした鍵のJSONファイルのパスを通します。

# Macの場合
export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/example.json"

ライブラリのインストールも行いましょう。

pip install --upgrade google-cloud-language

環境構築は以上です。さっそくAPIを呼び出してみましょう。

 

感情分析

以下のようにAPIをコールすると

 

from google.cloud import language_v1
client = language_v1.LanguageServiceClient()

document = {"content": "今日はいい天気だな。ランニング日和だ。", "type_": "PLAIN_TEXT"}
response = client.analyze_sentiment(request = {"document": document})

以下のようなレスポンスを得ることが出来ます。

document_sentiment {
  magnitude: 0.6000000238418579
  score: 0.30000001192092896
}
language: "ja"
sentences {
  text {
    content: "\344\273\212\346\227\245\343\201\257\343\201\204\343\201\204\345\244\251\346\260\227\343\201\240\343\201\252\343\200\202"
  }
  sentiment {
    magnitude: 0.5
    score: 0.5
  }
}
sentences {
...
}

各パラメタの意味はこんな感じです。

  • document_sentiment: 渡された文章全体の情報
  • magnitude: 感情の強さ(0-1)
  • score: ポジティブ・ネガティブの度合い(-1~1で、1に近づくほどポジティブ)
  • language: (リクエストで指定しなかった場合)自動で検出された言語
  • sentences: 「。」て区切った文章ごとの情報
  • text
  • content: 文章の内容
  • begin_offset: 指定したテキスト内の文の開始位置を表す文字オフセット。リクエストで渡した encodingType を使用して計算される。
  • sentiment
  • magnitude: 感情の強さ(0-1)
  • score: ポジティブ・ネガティブの度合い(-1~1で、1に近づくほどポジティブ)
  • sentences

いろいろ試してみた結果

上3つの天気の例では、雲行きが怪しくなるにつれネガティブに傾いていっているのがわかりますね。
下2つは上杉鷹山の名言ですが、「何事も成らぬは人の為さぬなり。」のほうが、「為せば成る、為さねば成らぬ」よりも強い感情が込められていることも読み取っています。

 

エンティティ感情分析

以下のようにAPIをコールすると、

from google.cloud import language_v1
client = language_v1.LanguageServiceClient()

document = {"content": "今日はいい天気だな。ランニング日和だ。", "type_": "PLAIN_TEXT"}
response = client.analyze_entity_sentiment(request = {"document": document})

以下のようなレスポンスを得ることが出来ます。

entities {
  name: "\345\244\251\346\260\227"
  type_: OTHER
  salience: 0.5793389081954956
  mentions {
    text {
      content: "\345\244\251\346\260\227"
      begin_offset: 15
    }
    type_: COMMON
    sentiment {
      magnitude: 0.8999999761581421
      score: 0.8999999761581421
    }
  }
  sentiment {
    magnitude: 0.8999999761581421
    score: 0.8999999761581421
  }
}
entities {
  ...
}
language: "ja"

 

各パラメタの意味はこんな感じです。

  • entities
  • name: 単語
  • type: 単語の種類(種類一覧は公式ドキュメントを御覧ください)
  • salience: 単語の重要度 文章中で検出された単語のsalienceを合計すると1になります。
  • mentions
  • text
  • content: 単語
  • begin_offset: 指定したテキスト内の文の開始位置を表す文字オフセット。リクエストで渡した encodingType を使用して計算される。
  • type: 単語のタイプ
  • sentiment
  • magnitude: 単語の感情の強さ(0-1)
  • score: 単語のポジティブ・ネガティブの度合い(-1~1で、1に近づくほどポジティブ)

 

いろいろ試してみた結果

※今回はscore(ポジティブ・ネガティブ)に焦点を当てて観察するために、文章の順番を変更しています。また、その文章内で検出された単語すべては掲載しておりませんので、特にsalienceの数値をご覧になるときはご注意ください。

こちらは一般的な文章ではなく、弊社が総合職の新人研修の際に使用しているロールプレイの文章を分析してみました。

1,2はどちらも「夜勤」という単語ですが、1はネガ、2はポジになっています。ですが文章を見てみると、2も1と同じくネガティブな文脈(夜勤を希望しない)のようです。

3,5では「C病院」「Bクリニック」という固有名詞が取得できています。一方4,6では「A病院」「Bクリニック」がそれぞれ「病院」「クリニック」になってしまっていますね。同じ単語でも固有名詞として取られる時とそうでない時があるようです…。
typeについても(4)「病院」は「LOCATION」の一方で、(6)「クリニック」は「EVENT」であるのも、謎が深まります。

7,8の「雰囲気」、9,10の「休み」では、文脈に応じたポジネガの判定ができていますね。1,2の「夜勤」では文脈を考慮できていなかったのですが、文脈を考慮できるパターンもあるようです。

scoreの値や検出される単語、typeの判定等、想定通りになるときとそうでないときがあり、まだ少々使いづらい印象ですね。

 

おわりに

今回はNatural Language APIの環境構築、感情分析とエンティティ感情分析について紹介しました。
感情分析は想定する結果を返すことが多く、実用化に向けて方法を考えていけそうです。一方、エンティティ感情分析では想定しない結果を返すこともあり、実用化以前の精度の検証にもう少し時間をかけてみようと思います。

弊社では「Cloud Natural Language」シリーズ以外にもたくさんのGCPサービスを使用しています。
興味のある方はこちらの記事もご覧ください!↓

Pocket
LINEで送る