문제

벡터 간의 코사인 유사성을 어떻게 찾습니까?

두 줄의 텍스트 사이의 관련성을 측정하기 위해 유사성을 찾아야합니다.

예를 들어 다음과 같은 두 문장이 있습니다.

사용자 인터페이스를위한 시스템

사용자 인터페이스 머신

… 그리고 TF-IDF 이후의 각각의 벡터, 예를 들어 LSI를 사용한 정규화[1,0.5] 그리고 [0.5,1].

이 벡터들 사이의 분명성을 어떻게 측정합니까?

도움이 되었습니까?

해결책

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 작업을했습니다. 나는이 코사인 유사성 방법을 사용했습니다 Jama : Java 매트릭스 패키지.

전체 소스 코드는 참조하십시오 Java와의 IR 수학 : 유사성 측정, 좋은 몇 가지 다른 유사성 측정을 다루는 정말 좋은 리소스.

다른 팁

이러한 간단한 작업을 위해 타사 라이브러리에 의존하지 않으려면 다음은 일반 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));
}

함수는 두 벡터의 길이가 같은 것으로 가정합니다. 안전을 위해 명시 적으로 확인하고 싶을 수도 있습니다.

다음을 살펴보십시오. http://en.wikipedia.org/wiki/cosine_similarity.

벡터 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() 표준 계산의 경우. 더 읽기 쉬운 동일한 결과는 맛에 따라 다릅니다.

얼마 전에 텍스트 채굴 작업을 할 때 심해 Java에서 다양한 메트릭을 제공하는 라이브러리. 더 많은 것이 필요하다면 항상 R과 크랜 보려면.

그러나 Wikipedia의 설명에서 그것을 코딩하는 것은 다소 사소한 일이며 좋은 운동이 될 수 있습니다.

사용하는 벡터의 드문 표현 Map(dimension -> magnitude)다음은 스칼라 버전입니다 (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))
}

스칼라 버전

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top