こんにちは。

本日はMeCabというライブラリを用いてword2vecをやってみました。調べるとどうやらにニューラルネットワークを使っているようです。なのでニューラルネットワークを知ってる人ならすぐわかります。もし知らないのであればこちらへ。ではみていきましょう。

word2vecとは

単語をベクトル化してさらに次元圧縮したもの

とはいえ、単語をベクトル化?と疑問が出ると思うのでまずはそこから話していきます。

昔、One-Hot-Vectorについてお話ししました。ズバリそれです。例えばN単語ある場合、それをどうやって数値化、つまりベクトル化するのかというとOne-Hot-Vectorを使います。以下が例です。
とりあえずコレでベクトル化できました。しかし、コレは明らかに問題です。なぜなら形態素解析を行う際にN=4なんてことはあり得ないからです。何百、何千、何万といったワードを扱うことになります。加えて、ベクトルの四則にがないのでコレでは分析どころではありません。ではどうすればうまく単語を扱えるのか?そこで「分散表現」が現れます。
分散表現は先ほど問題だった
  • 次元
  • 四則
を解決します。つまり、次元は300ほどに落ち(300がポピュラー?)、ベクトルの演算が意味を持ちます。有名は例としては

[王子様ベクトル] – [男ベクトル] + [女様ベクトル] = [王女様ベクトル]

といった感じです。とはいえこの分散表現はOne-Hot-Vectorから計算されます。ではアルゴリズムの紹介に移りたいと思います。

CBOWとSkip-gram

word2vecで使われる考え方は上の2つです。多対一または一対多ですね。

  • CBOW: 周辺の単語から対象の単語を学習
  • Skip-gram: 対象の単語から周辺の単語を学習
ここで窓(window)というワードが大切、コレは周辺の大きさを定義するもの。下の例はプロテインを対象の単語としています。
Skip-gramに焦点を当てて解説していきます。こっちの方が精度が良いようです。そのためにはSoftmax関数を知る必要があります。

    \[ p\left(v | v_{c}\right)=\frac{\exp \left(v^{T} v_{c}\right)}{\sum_{w=1}^{N} \exp \left(v_{w}^{T} v_{c}\right)}\]

vがとある周辺の単語、Vは単語数、v_{c}が対象の単語、v_{w}は周辺の単語、v^{T}は周辺のある単語の特徴ベクトルです。コレから分かるように出力は確率ですね。word2vecを解説しているサイトの多くが横ベクトルを用いていますが、基本的にベクトルといえば縦です。別にどっちが正しいとかそういうことはないのですが縦に慣れておいた方がいいと僕は個人的に思います。(論文は横ベクトルだった、汗)
上のものは一例です。入出力が4次元ですがコレは4単語の場合の学習です。隠れ層のサイズも例として3にしました。Skip-gramではソフトマックスを用いて確率を出力するのでした。つまり重み更新時は実際に周辺単語であるWindowに基づいて学習されていきます。つまり、Word2vecを使うときの注意点は前述した

  • CBOW: 周辺の単語から対象の単語を学習
  • Skip-gram: 対象の単語から周辺の単語を学習
の選び方とWindowのサイズですね。では実際に使ってみるんですが今回はツイートを約1ヶ月分(パンプというワードが含まれるもの)を用いました。そして分かち書き(単語ごとに具ぎり空白を置くこと)の前処理を行なってあとは形態素解析してTSNEとUMAPで可視化してみました。TSNEは非常にうポピュラーなアルゴリズムですが噂によるとUMAPとかなり熱いということなので今回、比較のために使ってみました。ではまず結果から
‘胸’というワードと近しい150単語を2次元に落とし込みました。(パンプでやるべきだったのかもしれない)

コレトレーニングしてる人だと分かると思うんですけど、例えば「二頭・三頭」が近いのは恐らく「スーパーセットなんだな」とか考えちゃうんですよね。あとはトレーニング部位は密集していますし、スクワットやフライなどの種目も密集しているのでやはり精度は高そうですね。ではTSNEとUMAP、どちらがいいのか、という問に対してですが僕的には今回の場合はTSNEだと思います。理由はグループごとの塊がしっかりしているように見えるからです。

では、最後にコードを貼っておきます。
今回自然言語処理を初めてやってみましたがニューラルネットワークがベースになっているのは少し驚きでした。今後も勉強していきたいと思いました。でわ

References