sleep furiously

自然言語処理をやる

J-POP 歌詞で自然言語処理 - 混合ユニグラムモデル -

私は言語が好きです。言語は様々な人間活動の根幹をなす要素であり、深遠なる人間の知性や心理へののぞき窓でもあるからです。

私は計算機が好きです。指先一つでスケールの大小関わらず様々なものを成し遂げてしまうその汎用性。人類に発明の中で2番目に偉大だと思います。ちなみに1番目は「文字」です

私は音楽が好きです。趣味です。

好きなもの × 好きなもの × 好きなもの、ということで勉強がてら歌詞データで自然言語処理をしてみようじゃないか、というのが個人的なモチベーションです。

概要 (TL;DR)

  • 20万曲を超えるJ-POP歌詞をスクレイピング
  • トピックモデルの一種である混合ユニグラムモデルを適用
  • モデルが自動的に発見してくれたトピック(ジャンル)の歌詞を眺めて楽しもう

データの入手(スクレイピング

J-Lyric.net から歌詞を入手します。

歌詞はふつう著作権保護されているため、そんな勝手にスクレイピングして大丈夫なの?と気になる方もいらっしゃるかもしれません。結論から言えば大丈夫です。

日本の法律では、情報解析のためにデータを複製することをを著作権者の同意なく行うことを認めています(参考)。サイト側でスクレイピングを禁止する旨が明示されている場合はこの限りではありませんが、 j-lyric.net の利用規約にはそれにあたる文面がありませんでしたので、安心してデータを入手していきたいと思います。

今回、分析の対象にする歌詞は全 J-POP 歌詞ですのでスクレイピングにはかなりの時間がかかります。サイトのサーバーに過度な負荷をかけないように気をつけつつ、数日かけてゆっくりデータを集めました。最終的に、アーティスト数:15,946、曲数:230,388 のデータが集まりました。中々のデータ量で、料理のしがいがありそうです。

混合ユニグラムモデル

こういうトピック(ジャンル)の文書ってこういう単語よく使うよね〜 という気持ちを数理的にモデリングしたものです。例えば、新聞記事を訓練データとして与えると、「この記事とこの記事は同じトピック…これとあれはまた別のトピック…」と機械が勝手に学習してくれます。

ユニグラムモデルは、ある単語がどのくらい現れやすいかという観点でトピックをモデル化します。文やフレーズまで踏み込まず、単純に一つずつの単語の出現だけを考えるので、ユニ(uni: 一つ) + グラム(gram: 単語、文字)です。例えば、政治ニュースの記事だったら「国会、法案、内閣」といった単語が現れやすいのに対して、芸能ニュースの記事 の記事であれば「公開、出演、ライブ」などの単語を多くみることになりそうです。この感覚を、トピックは単語の確率分布を持つ、という形でモデル化します。

以下、数理的な定式化です。数式が出てきますが、ざっくりお気持ちを理解してもらうための注釈付きです。興味がない方は実験のセクションまで飛ばしてください。

混合ユニグラムモデルは2種類のパラメータからなります。トピック分布の \theta と各トピックの単語分布 \phi です。それぞれのトピックがどのくらい現れやすいかを表しているのが \phi 、そしてそのトピック内でそれぞれの単語がどのくらい使われやすいかを表しているのが \theta というわけですね。

f:id:ryo0634:20190408013553j:plain
混合ユニグラムモデルのパラメータ \theta\phi

このモデル内では、文書集合 D は以下のように生成されていると考えます。

  1. トピック z\theta からサンプリングして決定する。
  2. トピックの単語分布 \phi_z から、文書 w_d を生成する。

このとき、文書 w_d が生成される確率は以下の式で表されます。文書の生成確率は単に、単語の生成確率の積としてモデル化されています。それを各トピックごとに、トピックの確率をかけて足し合わせます。

f:id:ryo0634:20190408010558j:plain
文書の w_d 生成確率

それでは訓練データとなる D 個の文書があったときに、その尤度を最大化するような パラメータ \theta, \phi を求めましょう。文書集合の対数尤度は以下のようになります。

f:id:ryo0634:20190408010913j:plain
訓練データに対する対数尤度

この式を最大化しようと思って、L\theta, \phi について微分してもうまくいきません。\log の中に \sum の和があり、これがやっかいなのです。そこで EM アルゴリズムを使って最尤推定をします。

まず、潜在変数 q_{dk} を導入します。q_{dk} は文書 d がトピック k に属する確率で負担率と呼ばれます。\frac{q_{dk}}{q_{dk}}=1L にかけると、

$$ \begin{align} L = \sum_{d=1}^{D} \log \sum_{k=1}^{K} q_{dk} \frac{p(z_d=k|\theta) p(w_d|\phi_k)}{q_{dk}} \end{align} $$

となります。 ここでイェンゼンの不等式を用いて L の下限を求めます。 イェンゼンの不等式は凸関数について成り立つ不等式で、直感的には以下のように理解できます。

f:id:ryo0634:20190408013916j:plain
イェンゼンの不等式

上の図から、赤い点は青い点の常に上にあることが分かると思います。今回は f(x) = \log(x) として、L にイェンゼンの不等式を適用しましょう。

$$ \begin{align} L & = \sum_{d=1}^{D} \log \sum_{k=1}^{K} q_{dk} \frac{p(z_d=k|\theta) p(w_d|\phi_k)}{q_{dk}} \\ & \geq \sum_{d=1}^{D} \sum_{k=1}^{K} q_{dk} \log \frac{p(z_d=k|\theta) p(w_d|\phi_k)}{q_{dk}} \end{align} $$

これで無事に \sum\log の外に出すことが出来ました。最高です。この求まった下限を F としましょう。これで負担率 q_{dk} を固定したとき、下限 F を解析的に解くことが出来ます。下限 F を最大化すれば、元々最大化したかった L も大きくしていくことが出来ます。

F の最大化には、E ステップと M ステップを収束するまで繰り返します。

E ステップ

パラメータを固定して、q_{dk} についての F極値ラグランジュの未定乗数法を用いて導出すると、以下のようになります。

f:id:ryo0634:20190408014939j:plain
負担率の計算 (E step)

意味を考えてみると、トピックが k になったときの文書の生成確率の比でもって確率にした値になっています。q_{dk} は文書 d がトピック k を持つ確率なので、直感的にも妥当です。

M ステップ

M ステップでは負担率を固定して、下限 F が最大になるようにパラメータを更新します。負担率と同様にラグランジュの未定乗数法を使います。結果のみ示します。

f:id:ryo0634:20190408015030j:plain
パラメータ \theta の推定 (M step)

f:id:ryo0634:20190408015051j:plain
パラメータ \phi の推定 (M step)

モデルの説明は以上です。

実験

混合ユニグラムモデルを python で実装して、スクレイピングした歌詞コーパスで学習させます。1曲の歌詞を1文書として、文書数 D = 230,388、トピック数は K = 100 で学習させました。

語彙に関しては、歌詞を KyTea形態素解析し、['名詞', '形容詞', '形状詞', '動詞', '代名詞', '副詞'] に当てはまる品詞を持つ単語のみを残しました。歌詞の内容にあまり関わりのない'助詞'(「が」、「て」)などを取り除くためです。 また、普遍的すぎる単語やごく一部の曲にしか出てこない単語を取り除くために、半分以上の歌詞に現れる単語と、現れる文書数が5個以下の単語を取り除きました。結果、V = 47,428 の語彙が残りました。

それでは、どのようなトピックが学習されたのか、生成確率が高いものから見てみましょう。それぞれのトピックで生成確率の高い上位20単語と、そのトピックを割り当てられた歌詞へのリンクを示します。トピックの番号はモデルが勝手に割り当てたものなので、特に意味はありません。

トピック94(7.1%)

君, 僕, いつ, よう, 今, 何, こと, あ, 夢, 日,
そう, 空, 時, もう, 見, 歩, 行, 誰, 心, 手

GReeeeN / 桜color
PENGIN / 青瞬
さよならポニーテール / ぼくらの季節

一番生成確率が高かったトピックで、全体の7.1% を占めます。王道 J-POP といったトピックでしょうか。確かに単語をみてみるとよくありそうな J-POP の歌詞が浮かんできます。 「あの日君と僕 空見上げ夢に手を伸ばして歩いて行こう」 とか?

トピック6(6.9%)

君, あなた, 愛, いつ, よう, 僕, こと, 今, 心, 私,
何, もう, 夢, 時, 誰, あ, 涙, 日, そう, 中

lecca / Snow Crystals
AZU / あなたに愛たくて feat. Spontania
鈴木雅之 / 君を抱いて眠りたい

ラブソング、それも少しオトナっぽい雰囲気のやつでしょうか。上位に代名詞が来ているのは先ほどの王道 J-POP と同じですが、さっきは「君、僕」と一人称と二人称どちらもあるのに対し、こちらは「君、あなた」の二人称がトップです。やはりラヴは相手に向けて歌わないと意味がないのですね(?)

トピック66(5.1%)

you, the, to, and, i, my, me, in, of, your,
is, that, be, it, i'm, don't, on, love, a, all

Aimee B / FUTURE IN MY HANDS
アンジェラ・アキ / Honesty
ヒャダイン / Million of Bravery (Excalibur strut_ENG

英詞の曲トピックです。J-POP とはいえ、英詞の曲も結構あるもんです。英単語は日本語の語彙と全く別の記号ですから、これを使っている曲は「英語」というトピックに括られるのは当然のことですね。

以上、上位のトピック3つについて見てみました。100個ある全てのトピックを紹介するスペースと時間はありませんので、以下目立ったものを取り上げて紹介します。

トピック36(2.4%)

you, love, 君, my, i, いつ, me, 愛, あなた, your,
to, よう, be, 今, the, 僕, baby, 心, 何, そう

青山テルマ / Happiness
naNami / はじめてのチュウ
宇多田ヒカル / First Love

上で取り上げた英詞の曲トピックの亜種でしょう。日本語ベースに少し英詞取り入れました系トピックです。確かに "you, love, baby" あたりの簡単な英語を取り入れた J-POP 歌詞はよく耳にしますので、納得です。このトピックに含まれる曲もなんとなくタイトルを知っているものが多い気がします。

トピック88(2.0%)

男, 夢, 俺, あ, 女, 花, 泣, 生き, 酒, おまえ,
涙, 人生, 一, 心, 人, 惚れ, いつ, あなた, ひと, 明日

大城バネサ / 俺の漁歌
扇ひろ子 / 華の女道
ひめキュンフルーツ缶 / 酒燃料爆進曲

どうみても演歌です。これは分かりやすいですね。

トピック95(1.2%)

愛, 夢, 今, よう, 心, 光, 君, 世界, 闇, 時,
誰, 中, 何, 空, ゆ, 命, 手, 胸, 生き, 未来

イヤホンズ(高野麻里佳/高橋李依/長久友紀) / 勇者へのミサ・ブレイヴィス
ワルキューレ / 破滅の純情
machine / RED SUNDANCE

「光、闇、世界」など中2というかファンタジーのような世界観の歌詞です。曲にもアニソンが多いです。

トピック91(0.6%)

夏, 君, 恋, そう, よう, もう, 太陽, 行, 海, する,
いつ, summer, 僕, あなた, 今, 何, oh, 夜, 夢, まま

AKB48 / 真夏のSounds good!
WANIMA / 渚の泡沫
湘南乃風 / 睡蓮花

モデルは夏ソングもしっかり捉えてくれます。

トピック96 (0.4%)

君, day, 日, 僕, happy, いつ, よう, こと, 今日, 何,
そう, birthday, あ, 誰, 夢, それ, 今, 時, you, it's

LUV / Birthday
ゴールデンボンバー / 誕生日でも結婚式でも使える歌
ENDRECHERI / おめでTU

バースデーソングもあるんですね。ふ〜ん。

トピック54 (0.4%)

あ, みんな, き, や, ぼく, そう, 何, 子, いつ, こと,
それ, み, する, よう, 誰, もう, もの, どう, なん, あなた

クリスマスソング / あわてんぼうのサンタクロース
木村カエラ / オバケなんてないさ
マキシマムザホルモン / アバラ・ボブ(BAMBOOMAN MIX#2)

ひらがなが多いので気になって調べてみました。童謡かな?と思っていたのですが、結構変なのも混じっていました。アバラ・ボブって何?

トピック47(0.04%)

夏, 風, 中, ざわ, 空, いつ, よう, 畑, 広, 波,
ゆ, 父, さとうきび, 一, どこ, 来, 通りぬけ, 雨, 今日, 我

錦織健 / さとうきび畑
上間綾乃 / さとうきび畑 ウチナーグチver
森山良子 / さとうきび畑

最後に一番生起確率の低いトピックです。「さとうきび、父、ざわ」などとかなり特徴的な単語が並んでいますが、どうやら同じ曲を複数のアーティストがカバーしていたため、コーパスに複数存在することになり、それをトピックと認定したようです。思わぬところでデータの偏りがあるものですね。

おわりに

20万曲を超える J-POP 歌詞から、混合ユニグラムモデルを使ってどのようなジャンルが学習されるか検証しました。割と人の直感に合うような「〇〇系の曲」みたいなくくりが機械で自動的に発見出来るというのはなかなか面白いものです。

次は歌詞コーパスから単語埋め込みを作って遊んでみようと思います。

参考資料

トピックモデル (機械学習プロフェッショナルシリーズ)