2017-04-14 5 views
1

이렇게 두 개의 문자열이 있다고 가정합니다.자바에서 jaccard 계수를 구현하는 방법은 무엇입니까?

에 Query1 :

QUERY2 "월의 아이디어": "Ceaser 월에 사망"

기능 (J) = (Query1을 교차 QUERY2)/(Query1을 조합 QUERY2가)

내가 찾고 있어요 위치에 관계없이 토큰 수 (단어)에 대한 정확성.

Query1을 교차 QUERY2 = 1 {월}

Query1을 조합 QUERY2 = 6이 컨텍스트 기능 (J)에서

{의 아이디어,, 3 월, Ceaser는 사망} 1/6을 반환해야 .

어쨌든 두 문장의 교차 수 및 결합 수를 찾을 수 있습니까? 예를 들어,

public double calculateSimilarity(String oneContent, String otherContent) 
{ 
    double numerator = intersection(oneContent,otherContet); 
    double denominator = union(oneContent,otherContet); 

    return denominator.size() > 0 ? 
    (double)numerator.size()/(double)denominator.size() : 0; 
} 

, 여기에이 구글 구아바 같은 외부 라이브러리를 사용하지 않고 교차로의 수와 노동 조합 수를 얻을 자바에서 사용 가능한 기능인가?

+0

Jaccard Index/Tanimoto 계수에는 단일 정의가 없습니다. 오히려 그것은 교차점과 노동 조합을 정확도 지수에 연관시키는 방법이기 때문에 해석은 사용 된 특정 교차점과 노동 조합 측정치에 달려 있습니다. 내가 뭘했는지 구체적으로 설명해야합니다. 위치와 무관하게 취급 할 때의 공통 문자 수의 정확성 또는 주어진 주어진 최적 정렬 (다음은 사용 된 특정 정렬 알고리즘의 적용을 받는다)의 문자 수. –

+1

@TasosPapastylianou 나는 토큰의 수 (단어)에 관계없이 정확도를 찾고있다. – Yash

+0

그런 경우 tokenize와 알파벳순으로 정렬 (대소 문자는 무시하거나 고유하지 않음)하여 두 텍스트의 연결 (즉 고유 토큰 만 유지)을 한 다음 각 개인에 대해 단어가 나타나는 횟수를 계산하는 두 개의 배열을 만듭니다 본문. 인터셉션은 모든 토큰에 대해 두 배열 사이의 최소 합계이며 사용자 유니온은 해당 최대 값의 합계입니다. –

답변

-1

다른 외부 종속성이없는 Apache commons 텍스트를 사용할 수 있습니다. (https://commons.apache.org/proper/commons-text/)

텍스트 유사성 알고리즘 문서 : https://commons.apache.org/sandbox/commons-text/apidocs/org/apache/commons/text/similarity/package-summary.html

그리고 당신은 여기 인 Jaccard 계수 구현을 찾을 수 있습니다 https://github.com/apache/commons-text/blob/master/src/main/java/org/apache/commons/text/similarity/JaccardDistance.java

0

당신이 노조/교차로의 크기에만 관심이있다, 당신은 계산할 수 있습니다 이 두 세트의 크기는 실제로 조합과 교차 세트를 만들지 않고 (union(a, b).size()a.size() + b.size() - intersection(a, b).size() -> 교차 크기 만 필요합니다).

public static void main(String[] args) { 
    final String a = "Ideas of March"; 
    final String b = "Ceaser died in March"; 
    final java.util.regex.Pattern p 
     = java.util.regex.Pattern.compile("\\s+"); 
    final double similarity = similarity(
      p.splitAsStream(a).collect(java.util.stream.Collectors.toSet()), 
      p.splitAsStream(b).collect(java.util.stream.Collectors.toSet())); 
    assert similarity == 1d/6; 
    System.out.println(similarity); // 0.1666... 
} 

public static double similarity(Set<?> left, Set<?> right) { 
    final int sa = left.size(); 
    final int sb = right.size(); 
    if ((sa - 1 | sb - 1) < 0) 
     return (sa | sb) == 0 ? emptyJaccardSimilarityCoefficient : 0; 
    if ((sa + 1 & sb + 1) < 0) 
     return parallelSimilarity(left, right); 
    final Set<?> smaller = sa <= sb ? left : right; 
    final Set<?> larger = sa <= sb ? right : left; 
    int intersection = 0; 
    for (final Object element : smaller) try { 
     if (larger.contains(element)) 
      intersection++; 
    } catch (final ClassCastException | NullPointerException e) {} 
    final long sum = (sa + 1 > 0 ? sa : left.stream().count()) 
        + (sb + 1 > 0 ? sb : right.stream().count()); 
    return 1d/(sum - intersection) * intersection; 
}