単語埋め込みとは、単語を200次元~300次元の実数ベクトルで表現する技術です。近い意味の単語を近いベクトルに対応させることができるとともに、ベクトルの足し引きで king – man + women = queenのような演算ができるようになります。
実際にPythonで単語ベクトルの演算を実演している方の動画があるので参考にどうぞ。
Contents
日本語は日本語の学習済み単語ベクトルが必要?
実際にこの方法でやってみたのですが、’king’ – ‘male’ + ‘female’ = ‘queen’という結果は得られるのですが、「王様」-「男」+「女」だと期待している「女王」という結果が得られません。日本語の処理は苦手なようです。
でも日本語でも同じようなことをしてみたいので探してみた結果、以下のようなfastTextの日本語の学習済み単語ベクトルがあることがわかりました。モデルにはいくつか種類がありますが、今回はこちらにあるWEBクローラーとWikipediaの文書から学習したモデルを利用します。cc.ja.300.vec.gzのサイズは1.2GB。ちょっと大きいけれどもダウンロードしてJupiterLabで処理をしてみることにします。
まずpipコマンドでgensimをインストールしておきます。
1 2 |
# gensimをインストール pip install gensim |
そのあと
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import gensim # 学習済モデルのパス model_path = 'cc.ja.300.vec.gz' model = gensim.models.KeyedVectors.load_word2vec_format(model_path, binary=False) # ロードに10分以上かかります。 # ためしにどれくらいの単語が登録されているか調べる words = list(model.index_to_key) len(words) # 「2000000」と表示される # 単語ベクトルの演算 model.most_similar(positive=['王様', '女'], negative=['男']) |
「王様」-「男」+「女」=「女王」
実行結果は以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 |
# 以下のように出力される。「王様」-「男」+「女」=「女王」。合っている [('女王', 0.4983246922492981), ('ラジオキッズ', 0.4979418218135834), ('王さま', 0.49087509512901306), ('熟', 0.483914315700531), ('王妃', 0.4745190143585205), ('アンナ・レオノーウェンズ', 0.4703938066959381), ('タプチム', 0.4547259509563446), ('ゲムケン', 0.4503451883792877), ('裸', 0.4499166011810303), ('お姫様', 0.44970372319221497)] |
他にもやってみました。
1 2 3 4 5 6 7 8 9 10 11 12 |
model.most_similar(positive=['姪', '男性'], negative=['女性']) # 以下のように出力される。「姪」-「女性」+「男性」=「甥」、合っている [('甥', 0.8209505081176758), ('叔父', 0.6412276029586792), ('叔母', 0.6293267011642456), ('従姉', 0.62241530418396), ('弟', 0.6069883108139038), ('従兄', 0.5955628156661987), ('従姉妹', 0.594235360622406), ('伯父', 0.5939351320266724), ('義妹', 0.5894801020622253), ('従兄弟', 0.5876302123069763)] |
アメリカ合衆国の首都はニューヨーク?
1 2 3 4 5 6 7 8 9 10 11 12 |
model.most_similar(positive=['東京', 'アメリカ'], negative=['日本']) # 以下のように出力される(アメリカの首都はニューヨークではない!) [('ニューヨーク', 0.6167320609092712), ('ロサンゼルス', 0.5732739567756653), ('フィラデルフィア', 0.5673415064811707), ('フロリダ', 0.5639087557792664), ('都', 0.5559900999069214), ('カリフォルニア', 0.5455960631370544), ('テキサス', 0.5384708642959595), ('ニュージャージー', 0.5370973944664001), ('サンフランシスコ', 0.5291856527328491), ('シカゴ', 0.5268759727478027)] |
韓国の首都は釜山?
1 2 3 4 5 6 7 8 9 10 11 12 |
model.most_similar(positive=['東京', '韓国'], negative=['日本']) # 以下のように出力される(韓国の首都は釜山ではなくソウル) [('釜山', 0.6325470805168152), ('ソウル', 0.6058447957038879), ('大邱', 0.5559118390083313), ('済州', 0.5450431704521179), ('都', 0.5370016098022461), ('大阪', 0.5297954082489014), ('仁川', 0.5165692567825317), ('新大久保', 0.5141767859458923), ('慶州', 0.5130058526992798), ('光州', 0.5123242735862732)] |
ちょっと答えが違うんじゃないかと思うものもありますが、だいたいはいい線を突いています。
AKB48? 知らんがな
1 2 |
# 「アイドル」と類似する単語10件表示 model.most_similar('アイドル', topn=10) |
このようにすれば「アイドル」と類似する単語が10件表示されます。
1 2 3 4 5 6 7 8 9 10 |
[('グラビア', 0.6978503465652466), ('グラドル', 0.63138347864151), ('芸能人', 0.6298618912696838), ('インディーズアイドル', 0.6295033097267151), ('タレント', 0.6276111602783203), ('スーパーアイドルグループ', 0.6195115447044373), ('美少女', 0.5984371304512024), ('ジュニアアイドルグループ', 0.5916925072669983), ('グラビアアイドルグループ', 0.5844401717185974), ('イケメンアイドルグループ', 0.5802721381187439)] |
ではこれならどうでしょうか?
1 2 3 4 |
model.most_similar('AKB48', topn=10) KeyError: "Key 'AKB48' not present" # 結果はなんとエラー。'AKB48'は登録されていないようです。 |
ただちょっと変えて’AKB48’ではなく’AKB’で調べてみると結果は返されます。姉妹グループの名前が表示されています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# これだと登録されているらしい model.most_similar('AKB', topn=10) # 以下のように出力される [('AKB', 0.8159908652305603), ('SKE', 0.7957296967506409), ('NMB', 0.7423932552337646), ('HKT', 0.7359083890914917), ('akb', 0.7271713614463806), ('wAKB', 0.7211538553237915), ('wwAKB', 0.6963992118835449), ('Akb', 0.6858618259429932), ('SKE', 0.670630156993866), ('wwwAKB', 0.664301335811615)] |
有名なメンバーの名前ならどうか試してみましたが、”Key ‘○○’ not present”というエラーしかでません。
WEBクローラーとWikipediaの文書から学習したモデルなのですが、全名詞について網羅されているわけではないということです。興味がある分野の単語に関しては自分で集めるしかないのかな?