BERTによる、歌詞に基づくMr.Childrenの曲の分類に挑戦!【Part①】

in-ear headphones plugged in black Sony Walkman on vinyl record

Mr.Childrenの曲を20曲取り上げ、BERTを利用して、歌詞に基づいた分類を実行してみました。

目次

はじめに

BERT(Bidirectional Encoder Representations from Transformers)というモデルをご存知でしょうか?BERTは、Googleが開発した自然言語処理のための深層学習モデルです。これは、高度な言語理解タスクを実行するために開発され、文章の要約、文書分類、質問応答、言語翻訳など、様々なところで応用されています。

本記事では、BERTを用いて、歌詞に基づいたMr.Childrenの曲の分類を試してみようと思います。

対象とするのは、次の20曲です。

「365日」「しるし」「終わりなき旅」「Sign」「GIFT」「名もなき詩」「Tomorrow never knows」「HERO」「エソラ」「innocent world」「くるみ」「抱きしめたい」「旅立ちの唄」「君が好き」「シーソーゲーム ~勇敢な恋の歌~」「祈り ~涙の軌道」「youthful days」「掌」「Marshmallow day」

分類は次の手順で行います。

  1. 歌詞(文字列)を数値化
  2. 数値化したベクトルをクラスター分析(K平均法)

準備

はじめに、諸々のダウンロードを済ませます。

読み込むcsvファイルには、1列目に「曲名」、2列目に「歌詞」の情報が入っています。

!pip install japanize_matplotlib
!pip install fugashi
!pip install ipadic

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.manifold import TSNE
from transformers import BertJapaneseTokenizer, BertModel
from sklearn.cluster import KMeans

df= pd.read_csv("Mr.Children.csv")
df= df.iloc[1:20]#今回は歌詞閲覧ランキング上位20個を対象とします

次に、BERTの日本語モデルをダウンロードします。

# BERTの日本語モデル、tokenizer、modelのダウンロード 
BERT_model_jp = 'cl-tohoku/bert-base-japanese-whole-word-masking' 
tokenizer = BertJapaneseTokenizer.from_pretrained(BERT_model_jp) 
model = BertModel.from_pretrained(BERT_model_jp)

データフレームの中身は下の画像のようになっています。

これで準備完了です。

 

歌詞を数値化

早速、歌詞を数値データに変換したいと思います。文字列を数値に変換する役割を担うのが、先ほどインストールした、BERTモデルです。

#歌詞のベクトル化
max_length = 256
sentence_vec= []

for i in range(len(df)):
lines = df.iloc[i, 1].splitlines()
text = '\n'.join(lines)
encoding = tokenizer(
text,
max_length=max_length,
padding='max_length',
truncation=True,
return_tensors='pt'
)
with torch.no_grad():
output = model(**encoding)
last_hidden_state = output.last_hidden_state
attention_mask = encoding['attention_mask']
normalized_hidden_state = (last_hidden_state * attention_mask.unsqueeze(-1)).sum(1) / attention_mask.sum(1, keepdim=True)

sentence_vec.append(normalized_hidden_state.numpy())

#リストの形式を変更
sentence_vectors = np.vstack(sentence_vectors)

最後の、sentence_vectorsの次元は、

sentence_vectors.shape

1曲の歌詞が、768次元の数値ベクトルに変換されており、それが20曲分並んだものが、sentence_vectorsに格納されています。ここまでで、歌詞(文字)の情報を数値に変換することができました。

歌詞に基づいて、曲をグループ分け

今回は、K平均法という手法を用いてクラスタリングを行います。K平均法の実行は、次の2行のコードで行うことができます。モデルを作る際に、グループの数(n_clustersの部分)を解析者が選ぶ必要がありますが、今回は4つとしました。

kmeans = KMeans(n_clusters=4, random_state=22) 
kmeans.fit(sentence_vectors)

最後に、K平均法によるクラスタリングの結果を見てみます。

from collections import defaultdict #クラスターごとに所属するデータポイントの行をまとめる辞書を作成 
cluster_dict = defaultdict(list) 

#各データポイントをクラスターごとに分類 
for i, label in enumerate(kmeans.labels_): cluster_dict[label].append(df.iloc[i]) 
sorted_clusters = sorted(cluster_dict.keys()) 

#各クラスターに所属するクラスターを表示 
for cluster in sorted_clusters: 
   print(f"クラスター {cluster} に所属する曲名:") 
   for data_point in cluster_dict[cluster]: 
       print(data_point.iloc[0]) 
   print(" ")

結果発表!

先ほどのクラスタリングの結果、次のようにグループ分けされました。

  • クラスター0: 「しるし」「終わりなき旅」「名もなき詩」「くるみ」「抱きしめたい」「旅立ちの唄」「君が好き」「シーソーゲーム ~勇敢な恋の歌~」「祈り ~涙の軌道」「掌」
  • クラスター 1 : 「365日」「Sign」「Tomorrow never knows」「innocent world」「youthful days」 「Marshmallow day」
  • クラスター 2 :「エソラ」
  • クラスター3:「HANABI」「GIFT」「HERO」

最後に

クラスター分析によって、歌詞に基づいて曲を、4つのグループに分類をすることができました。

しかしながら、ここで、重要な過失に気がつきました。「筆者は、今回扱った20曲のMr.Childrenの歌詞、全部把握できていません。」そのため、クラスター分析の結果が、非常に良いのか、ある程度良いのか、今ひとつなのか、はっきりしたことは言えません…。

BERTを用いることで、文章データを数値データに変換することができました。文章のままだと扱いにくいデータも、数値データに変換することで、色々な分析が可能になります。今回扱ったK平均法以外にもクラスタリング手法はありますし、次元削減など他の方法を試しても面白そうです。

最後まで、読んでいただきありがとうございました!

CTA
  • URLをコピーしました!
  • URLをコピーしました!
この記事を書いた人
目次