JavaScriptで類似度を計算する方法

Pocket

以前、Pythonで類似度を計算する方法を書きましたが、これをJavaScriptに書き換えてみました。
Pythonの方が書き慣れてしまったこともありますが、JavaScriptも便利な記法が増えていて、移植に時間がかかりました。

コード

function calc_tf(term, terms) {
  ct = 0;
  for (i in terms) {
    w = terms[i];
    if (w == term) {
      ct += 1;
    }
  }
  return ct / terms.length;
}
function calc_idf(term, texts) {
  ct = 0;
  for (i in texts) {
    terms = texts[i];
    if (terms.includes(term)) {
      ct += 1;
    }
  }
  if (ct == 0) {
    return 0;
  }
  result = Math.log(texts.length / ct) + 1;
  return result;
}
function calc_tfidf(word, words, texts) {
  tr = calc_tf(word, words);
  idf = calc_idf(word, texts);
  return tr * idf
}
function cosine_similarity(vector0, vector1) {
  // 類似度
  mykeys = Object.keys(vector0).concat(Object.keys(vector1));
  mykeys = Array.from(new Set(mykeys));
  a = [];
  for (i in mykeys) {
    k = mykeys[i];
    if (k in vector0) {
      a[k] = vector0[k];
    } else {
      a[k] = 0;
    }
  }

  b = [];
  for (i in mykeys) {
    k = mykeys[i];
    if (k in vector1) {
      b[k] = vector1[k];
    } else {
      b[k] = 0;
    }
  }
  x = 0;
  y = 0;
  z = 0;
  for (k in a) {
    u = a[k];
    v = b[k];
    x += u * v
    y += u ** 2
    z += v ** 2
  }
  if (y == 0 || z == 0) {
    return 0;
  }
  return x / (y ** (1 / 2)) / (z ** (1 / 2));
}
function calc_vector_tfidf(target_terms, texts) {
  v = [];
  for (i in target_terms) {
    target = target_terms[i];
    v[target] = calc_tfidf(target, target_terms, texts);
  }
  return v;
}
function get_similar_tfidf(target_terms, texts) {
  vector_target = calc_vector_tfidf(target_terms, texts);
  results = [];
  for (i in texts) {
    text = texts[i];
    vector_one = calc_vector_tfidf(text, texts);
    result = cosine_similarity(vector_target, vector_one);
    results.push([result, text]);
  }
  results.sort(function(a, b) {
    return b[0] - a[0];
  });
  return results;
}

テスト

target_terms = ["りんご", "みかん"];
texts = [
  ["りんご", "みかん"],
  ["りんご", "みかん", "みかん"],
  ["りんご", "みかん", "ばなな"],
  ["りんご", "ぶどう", "ばなな"],
  ["すいか", "ばなな"],
];
results = get_similar_tfidf(target_terms, texts)
console.log(results);

元となる配列
["りんご", "みかん"]
結果
1.00, ['りんご', 'みかん']
0.96, ['りんご', 'みかん', 'みかん']
0.79, ['りんご', 'みかん', 'ばなな']
0.24, ['りんご', 'ぶどう', 'ばなな']
0.00, ['すいか', 'ばなな']

「りんご みかん」の場合は1.00となり、「すいか ばなな」の場合は0.00となります。
その他の結果も妥当であると思われます。

[ 2022年7月31日 | カテゴリー: JavaScript | タグ: ]

« | »

コメント

  1. […] JavaScriptで類似度を計算する方法を書きました。 これを使って複数の文から類似度の高い文を検索する方法を考えます。 […]

コメントを残す

メールアドレスが公開されることはありません。

送信してください。


タグ

カテゴリー

最近の投稿

最近のコメント

固定ページ

アーカイブ

stabucky

写真

メタ情報