どのように私は2つのベクトルのコサイン類似度を計算するのですか?
-
21-08-2019 - |
質問
どのように私は、ベクトル間のコサイン類似度を見つけるのですか?
私は2行のテキスト間の関連性を測定するための類似性を見つける必要があります。
たとえば、私のような2つの文を持っています
ユーザインタフェースのためのシステム
ユーザインタフェース機
...とTF-IDF後にそれぞれのベクターは、例えば、LSIを用いて正規化が続きます
[1,0.5]
と[0.5,1]
ます。
どのように私はこれらのベクトル間のsmiliarityを測定するのですか?
解決
public class CosineSimilarity extends AbstractSimilarity {
@Override
protected double computeSimilarity(Matrix sourceDoc, Matrix targetDoc) {
double dotProduct = sourceDoc.arrayTimes(targetDoc).norm1();
double eucledianDist = sourceDoc.normF() * targetDoc.normF();
return dotProduct / eucledianDist;
}
}
私は大学で私の情報検索ユニットのために、最近、いくつかのTF-IDFのものをしました。 私はジャマを使用しています。このコサイン類似の方法を使用:Javaのマトリックスパッケージの
の完全なソースコードを参照 IR数学についてJavaを使用:類似性尺度は、良いいくつかの異なる類似性の測定をカバーして本当に良いリソースをを。
他のヒント
、ここでは単純なJavaの実装です。
public static double cosineSimilarity(double[] vectorA, double[] vectorB) {
double dotProduct = 0.0;
double normA = 0.0;
double normB = 0.0;
for (int i = 0; i < vectorA.length; i++) {
dotProduct += vectorA[i] * vectorB[i];
normA += Math.pow(vectorA[i], 2);
normB += Math.pow(vectorB[i], 2);
}
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
}
関数は、2つのベクトルが同じ長さを有することを前提とすることに注意してください。あなたは明示的に安全のためにそれをチェックすることもできます。
を見てくださいます。
あなたはベクトルAとBを持っている場合。
の類似性は以下のように定義されます
cosine(theta) = A . B / ||A|| ||B||
For a vector A = (a1, a2), ||A|| is defined as sqrt(a1^2 + a2^2)
For vector A = (a1, a2) and B = (b1, b2), A . B is defined as a1 b1 + a2 b2;
So for vector A = (a1, a2) and B = (b1, b2), the cosine similarity is given as:
(a1 b1 + a2 b2) / sqrt(a1^2 + a2^2) sqrt(b1^2 + b2^2)
例:
A = (1, 0.5), B = (0.5, 1)
cosine(theta) = (0.5 + 0.5) / sqrt(5/4) sqrt(5/4) = 4/5
は、Javaでのマトリックスコードのために私はコルトのライブラリを使用してお勧めします。あなたがこれを持っている場合、コードは次のようになります(テストしたりコンパイルされません):
DoubleMatrix1D a = new DenseDoubleMatrix1D(new double[]{1,0.5}});
DoubleMatrix1D b = new DenseDoubleMatrix1D(new double[]{0.5,1}});
double cosineDistance = a.zDotProduct(b)/Math.sqrt(a.zDotProduct(a)*b.zDotProduct(b))
上記のコードは、ノルム計算のBlas.dnrm2()
方法またはAlgebra.DEFAULT.norm2()
のいずれかを使用するように変更することができます。正確に読みやすく、同じ結果が、味に依存します。
、私が提供 SimMetrics のライブラリを使用していましたJavaで異なるメトリックの広範な。それはあなたがより多くを必要とすることが起こった場合は、 R及びCRANを見にに常にあります。
しかし、ウィキペディアの記述からそれをコーディングすることはかなり簡単な作業であり、そして素敵なエクササイズすることができます。
Map(dimension -> magnitude)
を使用してベクトルの疎表現のため
ここではScalaのバージョンは(あなたは、Java 8に類似したものを行うことができます)です。
def cosineSim(vec1:Map[Int,Int],
vec2:Map[Int,Int]): Double ={
val dotProduct:Double = vec1.keySet.intersect(vec2.keySet).toList
.map(dim => vec1(dim) * vec2(dim)).sum
val norm1:Double = vec1.values.map(mag => mag * mag).sum
val norm2:Double = vec2.values.map(mag => mag * mag).sum
return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2))
}
def cosineSimilarity(vectorA: Vector[Double], vectorB: Vector[Double]):Double={
var dotProduct = 0.0
var normA = 0.0
var normB = 0.0
var i = 0
for(i <- vectorA.indices){
dotProduct += vectorA(i) * vectorB(i)
normA += Math.pow(vectorA(i), 2)
normB += Math.pow(vectorB(i), 2)
}
dotProduct / (Math.sqrt(normA) * Math.sqrt(normB))
}
def main(args: Array[String]): Unit = {
val vectorA = Array(1.0,2.0,3.0).toVector
val vectorB = Array(4.0,5.0,6.0).toVector
println(cosineSimilarity(vectorA, vectorA))
println(cosineSimilarity(vectorA, vectorB))
}
Scalaのバージョン