はじめに
自然言語処理では単語をアルゴリズムで扱える数字に変換する前処理が必要です。
ここでは、単語のベクトル化と称します。
単語のベクトルにも主に2つのアプローチがあります。
ここではそれらのアプローチの概要と軽く実装を紹介しようと思います。
以下の自然言語処理処理の流れの中でベクトル化についての話です。
- 前処理
- 形態素解析
- ベクトル化
- アルゴリズム
- 後処理して出力
ベクトル化のアプローチ
ワンホットベクトル
単語をベクトルで表現する方法として、簡単に思いつく方法は、01のみのエンコードするケースです.
例とえば、文字0~9を表現する場合は、次元数は10の以下のようなベクトルで表現できます.
010000000
ただし、この方法にはいろいろな課題があります.
- 単語同士の計算ができない
- 単語間の関連性がわからない
- 次元数が単語数に比例する
- 例えば広辞苑にある24万語を表現すると24万の次元数になる
- データ量が非常に多くなってしまう
分散ベクトル
分散ベクトルとは、単語の意味をベクトルで表現したものです.
ベクトルで表現することで単語同士の演算ができ、類似度を測れたりと色々とメリットがあります.
例えば以下みたいな表現にすれば単語同士で計算でき、関連性が測れたりするのでは?
0.443 0.854 0.133, ...
分散表現がわかると、色々な嬉しいことがあります.
-
単語同士の計算ができる
-
単語間の関連性がわかる
-
少ない次元数で多様な単語を表現できる
nwjc2vec
- 大規模な日本語コーパスNWJC(258億語)で学習
- 次元数は200
- https://www.jstage.jst.go.jp/article/jnlp/24/5/24_705/_pdf
分散ベクトルのアルゴリズム
Word2Vec
- Word2Vecは、単語の分散表現を得るためほ手法(2013年 トマス・ミコロフらによる)
- 分散表現を得る際にニューラルネットを使用
- 飛躍的な精度向上
- 分布仮説をもとにしている
Word2Vecの手法
以下2つの方法があります。
Skip-gram
- 中心の単語から周辺語を予測する
CBOW
- 周辺語から中心の単語を予測する
分布仮説とは
単語の意味は周辺の単語によって決まるとい分布仮説というものがあります.
単語の分散表現を得る手法はWord2Vec以外にもありますが、基本がこの仮説をもとにしています.
例) eatとくれば大体次は食べ物の単語がくることが予想できます.
I eat 食べ物の単語.
genismで分散ベクトルを取得
genismを用いて単語の分散ベクトルを取得してみます。
genismはLDA(トピック分析)で使われるものですが、今回はLDAについては割愛します。
ベクトル化のAPIを使ってちょっと遊んでみます。
Gensim: topic modelling for humans
学習済の単語ベクトルを取得
import gensim.downloader as api
wv = api.load('word2vec-google-news-300')
出力してみる
wv["Tokyo"]
array([-2.16064453e-02, 1.79687500e-01, 1.98242188e-01, -1.62109375e-01,
-1.34765625e-01, 1.25732422e-02, -1.99218750e-01, -2.68554688e-02,
-3.78417969e-02, 1.66992188e-01, -3.26171875e-01, 4.66796875e-01,
8.74023438e-02, -2.63671875e-01, -8.69140625e-02, -2.55859375e-01,
1.67846680e-03, 2.61718750e-01, -3.58886719e-02, -4.83398438e-02,
6.17675781e-02, -1.97265625e-01, -8.30078125e-02, -6.49414062e-02,
-2.35595703e-02, 2.47070312e-01, -1.05468750e-01, 3.36914062e-02,
...
単語の次元数は300でした
wv["Toyko"].shape
(300,)
色々計算してみます。
ロンドン - イギリス + 日本 =東京
wv.similar_by_vector(wv["London"] - wv["England"] + wv["Japan"], 1)
[('Tokyo', 0.7490742206573486)]
東京 - 日本 + イギリス =ロンドン
wv.similar_by_vector(wv["Tokyo"] - wv["Japan"] + wv["England"] , 1)
[('England', 0.708386242389679)]
なるほど。。
おわりに
自然言語処理の単語のベクトル化について軽くまとめてみました。
ベクトル化をどう応用して実際の課題とアルゴリズムに適用するかはまた後ほど。