見出し画像

単語のベクトル演算で「捕手-野球+サッカー」をやってみた

はじめに 

こんにちは自動化アーキテクトの森川です。

自然言語処理のライブラリを使って、単語のベクトル演算なるものをやってみました。

単語の分散表現

単語埋め込みとも呼ばれます。

単語の埋め込み(たんごのうめこみ、英語: Word embedding)とは、自然言語処理(NLP)における一連の言語モデリングおよび特徴学習手法の総称であり、単語や語句が実ベクトル空間上に位置づけられる。単語の数だけの次元を持つ空間から、はるかに低い次元を持つ連続ベクトル空間へと数学的な埋め込みが行われる。

単語の埋め込み - Wikipedia より

他の単語との関係性を解析しながら、単語の概念を固定長のベクトルにすることで数値化できる仕組みのようなものだと思っています。

詳しくは、自然言語処理の書籍をご覧ください。

単語のベクトル演算

ベクトル化することで、計算が可能になります。

”king”-”man”+”woman”=”queen”

王様という概念から男性を引いて、女性を足す。期待する答えは女王です。

それではやってみましょう。

FastTextをさわってみる

単語の分散表現で有名なライブラリは"Word2Vec"ですが、調べてみるとFacebook(現Meta)さんが開発したFastTextというライブラリは、更に性能が改善されているそうです。今回はこれを触ってみます。

Get started · fastText

環境構築

Dockerで手早く環境をつくります。オリジナルはc++ですが手軽に行きたいのでPythonで操作をします。

※ 手元のWSL2(Ubuntu20.04LTS)上でやっています。

├ Dockerfile
├ script/test_fs.py
└ model/wiki_ja__my_model.bin

DockerFileからイメージをビルド

# Dockerfile
FROM python:3.9

WORKDIR /app

RUN git clone https://github.com/facebookresearch/fastText.git && \
    cd fastText && \
    pip install .

CMD ["python", "app.py"]
docker build -t fasttext .

そこそこ時間を要します。

教師なしモデルの入手

Wikipedia日本語ページをfasttextでトレーニングしたデータを事前に作成してmodelに置きます。

大きさは約4GBと、かなりデカい

トレーニング済モデルはFastText公式に公開されているので、こちらを流用しても良いです。

※ ご利用の際はルールを守りましょう

https://fasttext.cc/docs/en/pretrained-vectors.html

コンテナ実行

docker run --rm -it -v ~/model:/model -v ~/script:/script fasttext /bin/bash

コンテナの中に入ってpythonを起動して、コマンドを打っていきましょう。

$ python
Python 3.9.13 (main, Jul 12 2022, 12:04:02) 
...
>>> import fasttext
>>> from pprint import pprint
>>> model = fasttext.load_model('/model/wiki_ja__my_model.bin')

実行結果

>>> pprint(model.get_word_vector("自然言語処理"))
array([ 2.77438134e-01, -8.66088197e-02, -3.12941849e-01, -8.79815221e-02,
        1.07949361e-01, -1.84897318e-01, -3.29486020e-02, -2.19183698e-01,
       -2.22590283e-01,  2.98827551e-02, -8.47320631e-03,  1.79108500e-01,
       ...
      dtype=float32)

少しだけ解説

model = fasttext.load_model('/model/wiki_ja__my_model.bin')

fasttextのインスタンスを初期化して、モデルをロードしています。

model.get_word_vector("自然言語処理")

「自然言語処理」という単語のベクトルを出力しています。

今回のモデルはdimension=300なので300個の意味深な数字が出力されました。

さて、ここから本題です。

単語ベクトルの演算

単語ベクトルを羅列されても生身の人間にはさっぱり理解できません。

しかしながら数値化されることで単語同士を演算することができます。

さっそくやってみましょう。

単語の類推をしてくれるFastTextのAPIget_analogiesを使います。

3つの引数を渡すと "A - B + C" をベクトル演算して類似する単語を出力します。

>>> pprint(model.get_analogies("王様", "男性","女性",k=10))
[(0.5490007996559143, '王女'),
 (0.5433363914489746, 'シンデレラ'),
 (0.534498929977417, 'マレフィセント'),
 (0.5192593932151794, 'お姫様'),
 (0.5052384734153748, 'ジミニー・クリケット'),
 (0.49663999676704407, '王さま'),
 (0.4936622083187103, '女王'),
 (0.4888650178909302, '魅惑'),
 (0.4867748022079468, 'オコノミミ'),
 (0.486691415309906, 'マリー・クリスティーヌ')]

"王女"が1番目に来てしまいました。"女王"は8位、がんばれクイーン。

気を取り直して、本記事タイトルの単語ベクトル演算 "捕手 - 野球 + サッカー" をやってみます。

期待する答えは"ゴールキーパー"です。

>>> pprint(model.get_analogies("捕手","野球","サッカー", k=4))
[(0.7237740159034729, 'ゴールキーパー'),
 (0.6964200735092163, 'GK'),
 (0.6818143725395203, 'サイドバック'),
 (0.6719012260437012, 'DF')]

見事に"ゴールキーパー"が1位です。さらに"GK"まで出してくれました!

捕手とゴールキーパーは厳密な意味では同義ではないのですが、なんとなくそうだよね?な答えを機械が導き出すところが素敵です。

調子に乗って、もう一つやってみましょう。

"荒川 - 東京 + 大阪"

期待する答えは"淀川"、そうですYODO Riverです。

>>> pprint(model.get_analogies("荒川", "東京","大阪",k=5))
[(0.6349592208862305, '淀川'),
 (0.6153256893157959, '大和川'),
 (0.567109227180481, '木津川'),
 (0.560580313205719, '寝屋川'),
 (0.535304069519043, '八尾')]

バッチリですね。関西出身としては、母校の近くを流れる大和川が2位に入っているところが嬉しいです。

最後に、少し難しいのをやってみましょう。

"責務 - 利益 + 尊い"

期待する答えは"ノブレスオブリージュ"です。

>>> pprint(model.get_analogies("責務", "利益","尊い",k=5))
[(0.4072819650173187, '厳か'),
 (0.4040670394897461, '使命'),
 (0.4022969603538513, 'ノブレスオブリージュ'),
 (0.3977338373661041, '大切'),
 (0.39596885442733765, '大事'),

惜しい!3番目でした。

テストファイルはこちら

# train/test_fs.py
import fasttext
from pprint import pprint

model = fasttext.load_model('/train/model.bin')
pprint(model.get_analogies("責務", "利益","尊い",k=5))

まとめ

  • DockerでFastTextを起動

  • 捕手 - 野球 + サッカー = ゴールキーパー となった。

トレーニングされたモデルを使って単語ベクトル演算をサクッとやってみました。

今日では広く使われる技術の基礎になっている考え方だと思いますが、手元で叩いてみると納得感と面白みがありました。

そして、MLツールを実行するとき「よくやってくれた!」という気持ちが少し湧くのは何故でしょう、不思議です。

FastTextには類似語検出や文章のベクトル出力のAPIも用意されています。

ご興味あるかたは触ってみてください。


執筆者プロフィール:森川 知雄
中堅SIerでテスト管理と業務ツール、テスト自動化ツール開発を10数年経験。
SHIFTでは、GUIテストの自動化ツールRacine(ラシーヌ)の開発を担当。
GUIテストに限らず、なんでも自動化することを好むが、ルンバが掃除しているところを眺めるのは好まないタイプ。
さまざま案件で自動化、効率化によるお客様への価値創出を日々模索している。
2021年からは技術イベントSHIFT EVOLVEの運営を主担当。好きな食べ物3位はきしめん。

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/