乃木坂46「monopoly」の歌詞をVertexAIで感情分析してみた
こんにちは、もっちーです。
Webマーケティング会社でエンジニアとして働いています🧑💻
GoogleCloud(GCP)を使った感情分析を試してみたので、その手順や結果などをまとめていこうと思います。
はじめに
VertexAIについて
感情分析に使ったサービスはGCPが提供している「VertexAI」です。
さまざまなAI機能が用意されていて、この中の1つである感情分析の使い道としては
たとえば
- 記事のネガポジ分析(SEO対策)
- SNSマーケティング(顧客層の分析)
- Web広告の見出し・抜粋の改善
などに使えそうですね。
マーケティング会社で働いている自分の立場だと、一般的な開発で使えそうなアイデアは思いつきませんでした。。
VertexAIの準備
それでは早速VertexAIを使っていこうと思います。
感情分析では「Cloud Natural Language API」を有効にする必要があるので、まずはAPIを有効化しました。
公式マニュアル:https://cloud.google.com/natural-language/docs/reference/rest/
2024/4時点ではv2が最新になっているので、特別な理由がない限りはv2を使うことをオススメします。
実行環境としては
- ローカル環境(Docker)
- Google Colaboratory
- GCP Colab Enterprise(今回はこれを使いました)
などの選択肢があります。
さくっと試してみたいのであれば、めんどうな認証処理をスキップできるColab Enterpriseが良いと思います。
実際に自分も使ってみましたが、プログラムを動かすまでに10分もかかりませんでした。
実際にColab Enterpriseを使うときの画面
もしColabEnterprise以外で使いたい場合はGCPプロジェクトとの連携が必要になります。
以下のページを参考にして進めてみてください。
(小声:Googleの解説ページ分かりにくいですよね。。認証関連を分かりやすく解説する記事も書いてみようと考えています)
歌詞データの準備
ここからは実際に歌詞の感情分析を試していきます。
自分は坂道グループが好きなので、以下の3曲を候補にリストアップしました。
- 乃木坂46「monopoly」
- 日向坂46「僕なんか」
- 櫻坂46「何度LOVE SONGの歌詞を読み返しただろう」
歌詞の感情を分析するのが目的なので、できるだけ恋愛系の曲が良いかなという理由で選曲しています(各グループから1曲ずつ)
今回の記事では乃木坂46のmonopolyを分析することにしました。
データの説明
歌詞のデータはそこまで大きくないので、手動でプログラム内に書くことにしました。
全体を段落ごとに分割して、Pythonのリスト形式で変数lyrics
に入れています。
データの前処理
上記の画像では自分の判断で歌詞を分割していますが、プログラムに適切な粒度で分割してもらうべきだと思います。
mecabなどの形態素解析ライブラリを使えば簡単にテキストを分割できるので、さまざまな条件で分割した結果を感情分析して、それぞれの違いを比較するのも面白そうですね。
たとえば今回の場合だと
このペダルを(このペダルを)
立ち漕ぎして(立ち漕ぎして)
というハモリ?の部分もそのまま分析対象にしています。
あとはWooWooやナナナナー系の部分も削るべきですね(乃木坂の歌詞にありがちなフレーズです笑)
感情分析の実行
それでは分析を始めていきましょう。
と言っても、公式サンプルのコードに少し手を加えるだけでOKでした(簡単に動かせるのは最高です)
以下のような少ないコード量で気軽に感情分析の結果をグラフ化できます。
実際に使用したコードも貼っておきます(あまりPythonに慣れてないので不適切な書き方があるかもしれません・・)
感情分析データの取得
from google.cloud import language_v2
import six
def sample_analyze_sentiment(content):
client = language_v2.LanguageServiceClient()
if isinstance(content, six.binary_type):
content = content.decode("utf-8")
type_ = language_v2.Document.Type.PLAIN_TEXT
document = {"type_": type_, "content": content}
response = client.analyze_sentiment(request={"document": document})
sentiment = response.document_sentiment
return {
"content": content,
"score": sentiment.score,
"magnitude": sentiment.magnitude,
}
# グラフ表示用
sentiment_analytices = []
for lyric in lyrics:
sentiment_analytices.append(sample_analyze_sentiment(lyric))
sentiment_analytices
analyze_sentimentメソッドの返り値に入っているscore
とmagnitude
を取り出して、グラフ化するための配列に入れています。
scoreは-1.0~1.0
の範囲で表示されいて
- 1に近いほどポジティブ
- -1に近いほどネガティヴ
という指標になっていました。
magnitudeは感情の揺れ具合を表していて、これは0~1
の値をとります。
score
とmagnitude
の値についてGoogle公式ページの例を貼っておきます。
明らかにポジティブ* "score": 0.8, "magnitude": 3.0
明らかにネガティブ* "score": -0.6, "magnitude": 4.0
ニュートラル "score": 0.1, "magnitude": 0.0
混合 "score": 0.0, "magnitude": 4.0
詳細:https://cloud.google.com/natural-language/docs/basics?hl=ja#interpreting_sentiment_analysis_values
折れ線グラフの表示
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
df = pd.DataFrame(sentiment_analytices)
plt.plot(df['score'])
plt.vlines(x=7, ymin=-1, ymax=1, color='black', linestyle='dotted') # 1番サビ
plt.vlines(x=11, ymin=-1, ymax=1, color='black', linestyle='dotted') # 2番
plt.vlines(x=17, ymin=-1, ymax=1, color='black', linestyle='dotted') # 2番サビ
plt.vlines(x=21, ymin=-1, ymax=1, color='black', linestyle='dotted') # Cメロ
plt.vlines(x=25, ymin=-1, ymax=1, color='black', linestyle='dotted') # 最終サビ
plt.show()
最後にmatplotlibを使ってグラフ化することにしました。
歌詞全体でどのように感情が変化していくか確認したかったので、X軸は歌詞の順番、Y軸はscoreの値をプロットしています。
結果はこちら。
全体的にネガティブ寄りな歌詞であることが分かりました(特にサビ)
scoreの値がマイナスだった部分に注目してみると
- -0.467:今さら気づいても もう遅すぎるね
- -0.679:みんなにやさしい君に腹が立つ
- -0.780:そう勝手に(そう勝手に)
monoployの代表的な歌詞でもあるみんなにやさしい君に腹が立つ
がネガティヴな感情なのは、なかなか納得のいく結果だと思います。
「そう勝手に(そう勝手に)
が一番マイナス・・?」と思ってmaginitudeを調べてみたら、0.837
と大きく揺れていることが分かりました(他の歌詞は~0.01
程度でした)
次にポジティブだった歌詞も見ていきましょう。
- 0.833:だっていつも君がやさしくて
- 0.847:君が好きだ
- 0.953:誰にもやさしい君は素敵だよ
素敵な歌詞ですね(自分の語彙力が低い・・笑)
最後に
最終サビにある感情の起伏が激しい部分。
- 0.953 :誰にもやさしい君は素敵だよ
- -0.518:だけどそれをまだ飲み込めない
素敵な歌詞ですね(2回目)
以上「乃木坂46monoployの歌詞を感情分析してみた」でした。
良い曲なのでぜひ聴いてみてください〜!
Discussion