コラム

2021.09.24

【テックコラム】GCPのNatural Language APIでポジネガ分析をしてみた

● はじめに


こんにちは。テクノロジー本部の奥村です。

以前、「API・データ検証奮闘記」コラムでYouTube Data APIを使用してデータをとってくるという内容を紹介していましたが、今回は取得したデータをNatural Language APIを使ってポジネガ分析してみるといった内容を紹介したいと思います。

● Natural Language APIとは?


GCPが提供している、事前学習済みのモデルを使用しテキストの感情分析、エンティティ分析、エンティティ感情分析、コンテンツ分類、構文解析などを行うことができるAIのAPIです。機械学習の知識がなくてもテキストの分析が気軽に行えます。

今回はポジネガ分析なので感情分析の機能を使用します。

参考:https://cloud.google.com/natural-language?hl=ja

● 今回やること


某有名ユーチューバーのある動画のコメント最新100件をvideo idをキーにしてYouTube Data APIで取得し、それをNatural Language APIを使用して、ポジティブ、ネガティブ、ニュートラル、混合の4つに分類したいと思います。

※ニュートラルと混合の違いは、ニュートラルはネガティブ・ポジティブのコメントどちらも含まれていないもの、混合は両方が含まれているものとなります

※使用量に応じてGCPの利用料金がかかりますのでご注意ください

【 前提条件 】

  • GCPのアカウントがあり、課金が有効化されていること
  • GCPのサービスアカウントが作成されておりJSONキーがあること
  • dockerが使える環境があること ※こちらは必須ではないですが今回はdocker上でプログラムを動かすため

【 大まかな手順 】

大まかな手順は下記のとおりです。

  • APIを有効にする
  • 必要なファイルを設置
  • dockerコンテナ起動&実行

● 各手順について


・APIを有効にする

  1. GCPのWEBコンソールから「APIとサービス>ライブラリ」を選択する
  2. 「Cloud Natural Language API」を検索する
  3. 「有効にする」をクリックする

・必要なファイルを設置

必要なファイルは下記の4つです。

  • Dockerfile
  • 環境変数ファイル(.env)
  • 実行ファイル(execute.py)
  • サービスアカウントのJSONファイル(natural_language_api.json)

ディレクトリ構成は下記になります。

~/natural_language_api/
  - Dockerfile
  - execute.py
  - .env
  - .gcp/natural_language_api.json

Dockerfile

FROM python:3.9.1-slim-buster

ENV LANG=C.UTF-8

# Change timezone
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

RUN apt-get update && apt-get install -y \
    vim \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

RUN pip install \
  google-api-python-client==2.0.2 \
  google-cloud-language==2.2.2

WORKDIR /app

COPY ./execute.py ./

CMD ["bash"]

APIで使用するgoogle-api-python-clientモジュールとgoogle-cloud-languageモジュールをインストールしています。

.env

YOUTUBE_API_KEY='YOUR API KEY'
GOOGLE_APPLICATION_CREDENTIALS=/root/.gcp/natural_language_api.json

コンテナ起動時に読み込む環境変数のファイルです。
YOUTUBE_API_KEYには自身のAPIキーを入れてください。

execute.py

import os

from apiclient.discovery import build
from google.cloud import language_v1

YOUTUBE_API_KEY = os.environ['YOUTUBE_API_KEY']


class YouTube(object):
    def __init__(self, developerKey):
        super(YouTube, self).__init__()
        self.instance = build('youtube', 'v3', developerKey=developerKey)

    def fetch_commentThreads(self, videoId, order, nextPageToken=None):
        res = self.instance.commentThreads().list(
            part='snippet',
            maxResults=100,
            videoId=videoId,
            order=order,
            textFormat='plainText',
            pageToken=nextPageToken).execute()

        return res


def execute_cnl_api(text):
    # Instantiates a client
    client = language_v1.LanguageServiceClient()

    # The text to analyze
    document = language_v1.Document(content=text,
                                    type_=language_v1.Document.Type.PLAIN_TEXT)
    encoding_type = language_v1.EncodingType.UTF8

    try:
        response = client.analyze_sentiment(request={
            'document': document,
            'encoding_type': encoding_type
        })
    except Exception as e:
        logger.error(e)
        return False

    return response


def classify_result(result, res):
    score = res.document_sentiment.score
    magnitude = res.document_sentiment.magnitude

    if score >= 0.3:
        result['Positive'] += 1
    elif score <= -0.3:
        result['Negative'] += 1
    else:
        if magnitude >= 3:
            result['Mixed'] += 1
        else:
            result['Neutral'] += 1

    return result


#コメント取得
videoId = 'TW8xxe7_BTE'
youtube = YouTube(YOUTUBE_API_KEY)
res = youtube.fetch_commentThreads(videoId=videoId, order='time')

# コメント毎に感情分析
result = {'Positive': 0, 'Negative': 0, 'Neutral': 0, 'Mixed': 0}
for i in res['items']:
    comment = i['snippet']['topLevelComment']['snippet']['textDisplay']
    print(comment)
    print('-------------------------')
    res = execute_cnl_api(comment)
    print(res.document_sentiment)
    print('=====================================')
    result = classify_result(result, res)

print(result)

YouTube Data APIを使用して動画についたコメントを取得しています。
そのあと取得したコメントそれぞれをNatural Language API で分析しています。

・docker コンテナ起動&実行

dockerイメージを作成

docker image build -t natural_language_api .

dockerコンテナ起動

docker container run -it --env-file=.env -v ~/natural_language_api/.gcp:/root/.gcp natural_language_api bash

プログラム実行

python execute.py

実行結果

メンズ全種類です!?
キッズもレディースもめちゃカワイイよ!??
-------------------------
magnitude: 2.200000047683716
score: 0.699999988079071

=====================================
楽しい~
-------------------------
magnitude: 0.8999999761581421
score: 0.8999999761581421

=====================================
クッションも可愛いけどヒカキンさんも可愛い??
-------------------------
magnitude: 0.8999999761581421
score: 0.8999999761581421

=====================================

こちらは出力結果の一部です。コメントとそれに対する magnitude と score が取得できています。
score と magnitud の解釈の仕方ですが、 score はコメントの全体的な感情を示し、ポジティブであれば1に近く、ネガディブであれば-1に近い値になります。
magnitude はそのコメントに感情的な内容がどのくらい含まれているかを示します。
コメントが長いほど magnitude が大きくなる傾向があるようです。

今回は score が0.3以上でポジティブ、 score が-0.3以下でネガティブ、 score が-0.3~0.3の間で magnitud が3未満の場合ニュートラル、 score が-0.3~0.3の間で magnitud が3以上の場合混合と定義し分析してみました。

その結果、 この動画のコメントのポジティブ、ネガティブ、ニュートラル、混合の割合は以下であると分析できました。

実際のコメントと score を見てみるとまだまだ Natural Language API の日本語解析の精度に改善の余地はありそうですが、複数の動画を比較してポジティブなコメントの多い動画の傾向をつかんだりはできそうです。

{'Positive': 53, 'Negative': 9, 'Neutral': 37, 'Mixed': 0}

※何かしらの理由で YouTube Data API でコメントが1件取得できなかったようなので結果の合計が99件になっています。

● さいごに


このようにNatural Language APIを使用することで機械学習の知識がなくても投稿内容の分析を行うことができます。

気軽に試せるのでぜひやってみてください!

また、こういった分析をしてみたいが自社に専門人材がいない、リソースが足りない等の課題をお持ちの方に、エンジニア領域の支援サービス(Data Engineer Hub)をご提供しています。
お困りごとございましたら是非お気軽にご相談ください。

》サービスの詳細はこちら

本件に関するお問い合わせは下記にて承ります。
株式会社DataCurrent
info@datacurrent.co.jp