単語ベクトルを2値ベクトル化
背景
以前、アトラクタ的なダイナミクスをもったニューラルネットワークで、単語の連想記憶を試した。 blog.hassaku-labs.com
この時点では、単語ベクトルをニューラルネットワークに入力する際、単にランダム行列射影を通して、次元数の調整をしただけで、連想記憶するベクトル情報自体は、連続値分散表現パターンのままであった。
しかしながら、シグモイド的な発火パターンを特徴としたニューラルネットワークの特性上、2値ベクトルの方が好ましい。
そこで、既存単語ベクトルを2値化する仕組みを探していたところ、手軽に出来そうな方法を見つけたので記録しておく。
word2bitsによる単語ベクトルの2値化
用いたのはword2bitsという手法。元々は、量子化によるデータのサイズ削減を目的としたものだが、類似度タスクでは性能が向上したとのことなので、連想記憶用の表現としても適していると思われる。
word2bitsについて、日本語で参考になりそうな記事はこちら。 medium.com
既存日本語単語ベクトルの変換
とりあえず検証用なので、比較的小さめの日本語単語ベクトルを用意すべく、こちらを利用させて頂きました。
$ wget https://s3-ap-northeast-1.amazonaws.com/dev.tech-sketch.jp/chakki/public/ja.text8.zip $ unzip ja.text8.zip $ wc ja.text8 0 16900730 100000347 ja.text8 $ ls -lh ja.text8 -rw-r--r-- 1 imt adm 96M 10月 4 2017 ja.text8 (「権限 が ある こと も 認め て いる 。」のような分かち書きされた文章が、連結された1行で存在している)
word2bitsによる量子化を実行する。とりあえず次元数は200。
$ git clone https://github.com/agnusmaximus/Word2Bits.git $ cd Word2Bits $ ./word2bits -bitlevel 1 -size 200 -window 8 -negative 24 -threads 4 -iter 5 -min-count 5 -train ja.text8 -output 1b200d_vectors_ja -binary 1
検証
pythonから読み込んで、確認してみる。
$ ptpython >>> from gensim.models import KeyedVectors >>> wv_from_bin = KeyedVectors.load_word2vec_format("1b200d_vectors_ja", binary=True) >>> wv_from_bin["サッカー"].shape (200,) >>> wv_from_bin["サッカー"] array([ 0.33333334, -0.33333334, 0.33333334, -0.33333334, 0.33333334, 0.33333334, -0.33333334, -0.33333334, 0.33333334, 0.33333334, ... >>> wv_from_bin.most_similar_cosmul("サッカー", topn=10) [('バスケットボール', 0.9099991321563721), ('選手', 0.8699991703033447), ('アメリカンフットボール', 0.8649991750717163), ('クラブ', 0.8649991750717163), ('バレーボール', 0.8599991798400879), ('ディフェン>ダー', 0.839999258518219), ('フットボール', 0.839999258518219), ('ポジション', 0.8349992632865906), ('ラグビー', 0.8349992632865906), ('ミッドフィールダー', 0.8299992680549622)] >>> sum(wv_from_bin["サッカー"] > 0) 102 >>> sum(wv_from_bin["サッカー"] < 0) 98
0.3と-0.3が半々の2値ベクトルが用意できた。
さいごに
以前構築した単語の連想記憶モデルに、今回の2値ベクトルを取り入れて、再度色々試してみたい。おそらく、パターン間の距離に応じた、アトラクタの引き込みとかは、より適切になるはずだと思われる。