Word Rotator’s Distance

Word Rotator’s Distance とは

2つの自然言語文あるいは文書が与えられたとき,それらの(非)類似度を測る尺度として Word Mover’s Distance (WMD)*1と呼ばれる手法が提案されている。 これは文を構成する単語ベクトルのアラインメントを最適輸送コストに基づき計算することで,文間の(非)類似度を見積もる手法である。 WMDの解説は下記が詳しい。 yubessy.hatenablog.com

WMDはgensimに実装がありすぐに使える。

gensim.models.Word2Vec.wmdistance

Word Rotator’s Distance(WRD)は,このWMDの改良版であり2020年に横井らにより提案された*2

多くの先行研究や観測事実を鋭い洞察力で整理し,合理的でシンプルなアイデアでありながらも誰も思いつかなかったのを最初にやったという意味ではすごい(小並感)。 実装コストもほぼ無で計算機パワーも手持ちのラップトップで十分という,個人的にはこういう研究がとても好み。

閑話休題

さて,自分語りはキモいのでここまでとして, WRDのポイントを一言でいうとWMDでは単語の意味と重要度を混ぜて計算していたのをWRDではそれらを分離して性能向上しましたよという話である。 詳細は横井らの論文を読んでほしい。arXiv版がより詳しいが, さくっと日本語で概要を掴みたい人は人工知能学会版*3もしくは言語処理学会*4の予稿を読むと良い。

実装

最適輸送の実装は論文にも書いてある通りPythonの最適輸送ライブラリであるPOTを使うとよい。関数をコールするだけである。

POT: Python Optimal Transport — POT Python Optimal Transport 0.7.0 documentation

最適輸送の計算に必要なのは,2つの確率分布とコスト行列である。 確率分布が文ベクトル,コスト行列が文を構成する単語ベクトル間の非類似度に対応する。 WRDでは,文ベクトルの各要素を各単語ベクトルのノルムで重み付けし正規化する。また単語ベクトル間の非類似度としてコサイン距離を使う。 WMDでは,この重みが一様分布であり,非類似度がL2ノルムだったのである。 詳細はarXiv版のAlgorithm1にあるのでそれを書くだけ。冗長に書けば例えば下記。

import numpy as np
from sklearn.preprocessing import normalize
import ot


def wrd(s, sp):

    w_norm = np.linalg.norm(s, ord=2, axis=1)
    wp_norm = np.linalg.norm(sp, ord=2, axis=1)
    ms = w_norm/np.sum(w_norm)
    msp = wp_norm/np.sum(wp_norm)

    s_norm = normalize(s, norm='l2', axis=1, copy=False) 
    sp_norm = normalize(sp, norm='l2', axis=1, copy=False)

    C = 1 - s_norm @ sp_norm.T

    Wd = ot.emd2(ms, msp, C)

    return Wd

全体のコードは整理したらGitHubで公開する。

実験

論文ではSTS-B(dev)で評価しているので同じデータセットを使う。 ここからダウンロードできる。

単語ベクトルは手元にあったglove.6B.100d.txtを使った。 ここからダウンロードできる。

結果

stopwordsの除去有無での Pearson' ρ は以下の通り。 stopwordsはnltkのをそのまま適用した。

  • 除去あり: 0.71247

  • 除去なし: 0.62859

微妙に違うけど論文のTable.6の結果のような数字が出た。

なお,未知語は除去しWRDのスコアはSTS-Bの人手スコアとは逆センスなので-1倍した。

次やること

単語ベクトルの各種後処理(VC)をかましてみる。

私からは以上です。