「Javaで学ぶ自然言語処理と機械学習」という本で紹介されていた Wikipedia でトレーニング済みの単語分散表現データが便利。 このデータの活用例として日本のブランドのマップを作成してみた。
ちなみに、この手の 単語ベクトルを2次元まで圧縮して2D表示的な話は Qitta をはじめあちこちで散々出ているネタですが、自分用メモおよび Ubuntu 18.04 の人および Java で機械学習やりたい人の参考になればと思いシェアします。 もっとも肝心の 2D マップ変換は 普通に Python です。
Wikipedia Entity Vectors で配布されている Wikipedia Entity Vectors release data の jawiki.word_vectors.100d.txt.gz を入手。
この jawiki.word_vectors.100d.txt.gz などのデータを読むためのライブラリ(手前味噌ですが)を以下から入手して ローカル maven レポジトリに入れる。
git clone して ./gradlew publishMavenPublicationToMavenLocal するだけです。
かなり恣意的ではあるが以下のブランドを試す。
結果は result.json へ保存される。
createJson.groovy
@GrabResolver(name='local', root='file://~/.m2/repository')
@Grab(group='jp.osima.app.ml', module='wevr', version='0.1.0-SNAPSHOT')
import groovy.json.*
import jp.osima.app.ml.wevr.WordDictionaryFactory
def gzippedVectorsTxtFile = new File('jawiki.word_vectors.100d.txt.gz')
def cacheFile = new File('cache.mdb')
def obj = [:]
obj.list = []
def wordDictionary = WordDictionaryFactory.createWordDictionary(gzippedVectorsTxtFile, cacheFile)
if( wordDictionary!=null ){
def words = 'ユニクロ,無印良品,フランフラン,セブンイレブン,ローソン,ファミリーマート,ビックカメラ,ヨドバシカメラ'.split(/,/)
words.each { word->
def vecWord = wordDictionary.get( word.trim() )
if( vecWord!=null ){
obj.list << [
word: vecWord.word,
vector: vecWord.vector]
}
else {
println "${word.trim()} not found"
}
}
}
new File('result.json').text = new JsonBuilder( obj ).toString()
出力した result.json を読み込み 2D マップを出力する。 (コードは python3 用)
createMap.py
import matplotlib.pyplot as plot
from sklearn.decomposition import PCA
import json
plot.rcParams["figure.figsize"] = [8, 8]
plot.rcParams['font.size'] = 6
jsonFile = open('result.json', 'r')
jsonObj = json.load(jsonFile)
data = []
labels = []
length = len(jsonObj['list'])
for index in range(0, length):
item = jsonObj['list'][index]
data.append( item['vector'] )
labels.append( item['word'] )
pca = PCA(n_components=2)
pca.fit(data)
data_pca = pca.transform(data)
length = len(data_pca)
for index in range(0, length):
x = data_pca[index][0]
y = data_pca[index][1]
plot.plot(x, y, ms=5.0, zorder=2, marker="o")
label = labels[index]
plot.annotate(label, (x, y), size=14)
plot.savefig('word-map.png')
結果 word-map.png に出力される。 以上です。
Matplotlib はインストールした状態では 日本語フォントが設定されていないらしい。 結構面倒だったので、Ubuntu 18.04 での日本語フォント設定をメモしておきます。
日本語フォントを入れる
sudo apt install fonts-ipaexfont
以下のコードを実行して、システム全体の設定ファイルの所在とか、自分用の設定ファイルの所在を把握しておく。
check.py
import matplotlib
print(matplotlib.matplotlib_fname())
print(matplotlib.get_configdir())
自分用設定ファイルは ~/.config/matplotlib/matplotlibrc だったので・・・これの以下の部分を変更。
font.family : sans-serif
font.sans-serif : IPAexGothic, DejaVu Sans, .... 以下略
そして、フォントキャッシュがあれば削除する(重要)
rm -rf ~/.cache/matplotlib/fontlist-v300.json
これで日本語出力できるようになりました。
フォントキャッシュを消さないと設定が反映されないので、この部分でかなり時間をとられました。 ドキュメント読めばたぶん書いてあるんでしょうけど。