9_3:似ているか? 似ていないか? ml5.js JavaScript

以下は、「単語の意味をベクトルで表現する」を理解するための、”適切ではないかもしれない”簡易的な例です。

「old woman」と「aunt」は、どちらも同じ女性で年もとっているという点で、「old woman」と「girl」よりも似ていると言えます。同様に、「old woman」と「old man」は、「old woman」と「uncle」よりも似ていると言えます。なぜなら、「old man」も「uncle」も「old woman」と異なる性別ですが、「old man」の方が「old woman」に年齢が近いからです。

人間は単語の意味を知っているので、こういった類似性が理解できますが、Word2vecのモデルは似ているかどうかを、ベクトルの内積を使って判断します。

内積はベクトルの成分同士を掛け、それらを合計することで求まります。その際、掛け合わせるベクトルの大きさを前もって1にしておくと、求まる内積が-1と1の間に収まります。

ml5.jsの舞台裏で動作しているTensorFlow.jsのコードを使った、2つのベクトルから内積を返す関数は次のように記述できます。

const getDotProduct = (vec1, vec2) => {
    // vec1の大きさ
    const magnitude1 = tf.norm(vec1);
    // 大きさを1にする(単位ベクトル)
    const normVec1 = tf.div(vec1, magnitude1);
    const magnitude2 = tf.norm(vec2);
    const normVec2 = tf.div(vec2, magnitude2);
    // 大きさを1にした2つのベクトルの内積を計算して返す
    // 単位ベクトル同士の内積は-1から1の間の数値になる
    return tf.dot(normVec1, normVec2).sum().dataSync()[0].toFixed(5);
}

TensorFlow.jsでベクトルを作成し、この関数に渡すと、内積が得られます。

// 性別と年齢の特徴をベクトルの数値に盛り込む。
// 女性は1、超高齢なので1.5
const superOldWoman = tf.tensor1d([1, 1.5]);
// 高齢なので1
const oldWoman = tf.tensor1d([1, 1]);
// まあ高齢なので0.75
const aunt = tf.tensor1d([1, 0.75]);

const res1 = getDotProduct(oldWoman, oldWoman);
document.getElementById('old-woman').textContent = 'oldWoman ・ oldWoman => ' + res1;
const res2 = getDotProduct(oldWoman, aunt);
document.getElementById('aunt').textContent = 'oldWoman ・ aunt => ' + res2;

「old woman」・「old woman」は同じベクトル同士の内積なので1になります。これは”同じ”ということです。「old woman」・「aunt」は0.98995なので、両者はとてもよく似ていると言えます。「superOldWoman」も0.98058なのでよく似ていますが、ほんの少しだけ「aunt」の方が似ています。

男性に移ると、「old woman」とは似ていないと言えますが、似ていない程度に差があることが分かります。一番似ていないのは「boy」です。

内積が2つのベクトルが似ているか似ていないかを表すことについては、「画像認識と数学 | 数理女子」が参考になります。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA