#概要
fastTextはFacebookが自然言語処理を行うために公開しているツールです。高速に自然言語処理を行うことができます。
GitHub fastText
仕組みについては、解説サイトを参照お願いします。
Facebookが公開した10億語を数分で学習するfastTextで一体何ができるのか
今回、そのfastTextを利用して、自然言語処理ではなく、競馬の血統をベクトル化したいと思います。
fastTextを利用して自然言語処理以外のことを行うというアイデアは、下記の記事に触発されたものです。
fastTextを使って単語じゃないものの分散表現を獲得する
実行結果
githubにベクトルファイルとhowto用のjupyter notebookファイルをアップロードしています。
github keiba_ketto_vec
作成方法
データセット
血統過去3代をfastTextのフォーマットに落とし込みます。
競走馬サトノダイヤモンドの場合の血統表です。
血統 | 馬名 |
---|---|
子 | サトノダイヤモンド |
父 | ディープインパクト |
母 | マルペンサ |
父父 | サンデーサイレンス |
父母 | ウインドインハーヘア |
母父 | Orpen |
母母 | Marsella |
父父父 | Halo |
父父母 | Wishing Well |
父母父 | Alzao |
父母母 | Burghclere |
母父父 | Lure |
母父母 | Bonita Francita |
母母父 | サザンヘイロー |
母母母 | Riviere |
上記の表の馬名を半角スペース区切りで1行に変換します。
他の競走馬についても同様です。
サトノダイヤモンド ディープインパクト マルペンサ サンデーサイレンス ウインドインハーヘア Orpen Marsella Halo WishingWell Alzao Burghclere Lure BonitaFrancita サザンヘイロー Riviere
サイモントルナーレ ゴールドアリュール ユーモレスク サンデーサイレンス ニキーヤ アフリート アリーウイン Halo WishingWell Nureyev ReluctantGuest Mr.Prospector PoliteLady Alydar FleetVictress
ウォータールルド ウォーターリーグ ウォーターエナン Dehere Solo BostonHarbor Scrape DeputyMinister SisterDot Halo MineOnly Capote HarborSprings Mr.Prospector File
...
ベクトル化
ベクトル化にはfasttextのskipgramコマンドを利用します。
実行すると、binファイルとvecファイルが生成されているはずです。
$fasttext skipgram -input input.csv -output ketto_model -minn 50
- inputオプション
インプットファイルを指定します - outputオプション
アウトプットとなるモデル名を指定します - minnオプション
文字列を文字に分解する際の最小サイズを指定します。
minnオプションについてですが、fastTextの仕組みとして、スペース区切りした単語に加えて、単語ひとつひとつをさらに文字レベルで分解して分析を行っているようです。
fastTextの実装を見てみた
この機能は、例えば"ゴールドアリュール"と"ゴールドシップ"という馬を"ゴールド"で一括りにしてしまいます。
今回は、名前そのものには意味は無いので、機能を無効化するためにminnオプションを利用して文字レベルへの分解を防ぎます。
結果確認
gensimを利用してベクトル化したファイルを読み込み、ベクトル演算を実施してみます。
サトノダイヤモンドからベクトル演算を利用して、父違いの妹であるリナーテを算出できるかチェックします。
- サトノダイヤモンド(父:ディープインパクト)
- リナーテ(父:ステイゴールド)
ですので、
サトノダイヤモンド + ステイゴールド - ディープインパクト = リナーテ
という式が成り立つはずです。
import gensim
# gensimを使ってベクトルデータを読み込み
model = gensim.models.KeyedVectors.load_word2vec_format('ketto_model.vec', binary=False)
# most_similarメソッドを使って演算
# positiveに足し合わせるデータをリストで渡し、negativeに差し引くデータをリストで渡す。
model.most_similar(
positive=["ステイゴールド", "サトノダイヤモンド"],
negative=["ディープインパクト"]
)
gensimの利用方法については下記をチェックしてください。
gensim models.word2vec
[('ポーレン', 0.8220623731613159),
('マルケッサ', 0.8190209865570068),
('マルペンサ', 0.814713716506958),
('リナーテ', 0.80884850025177),
('シャピーラ', 0.8080180287361145),
('ムーンライトナイト', 0.8041872382164001),
('Semplice', 0.7995823621749878),
('OnAir', 0.7940067648887634),
('フュージョンロック', 0.7933699488639832),
('Orpen', 0.7927322387695312)]
母父Orpen系のポーレンが一番似ているという結果になってしまいましたが、 母のマルペンサ、半妹のマルペンサ(父オルフェーヴル、父父ステイゴールド)につづき、 リナーテもしっかり演算結果に出現したので、ベクトル化は成功しているといえるのではないでしょうか。
以上。