2017-04-14 1 views
1

Supposons que j'ai 2 chaînes comme celle-ci.comment implémenter le coefficient de jaccard dans Java?

Query1: "Les idées de Mars"

Query2: "Ceaser mort en Mars"

Fonction (j) = (Query1 intersection Query2)/(Query1 union Query2)

Je cherche à la précision par rapport au nombre de jetons (mots), quelle que soit leur position.

Query1 intersection Query2 = 1 {Mars}

Query1 union QUERY2 = 6 {Des idées, des, Mars, Ceaser, est mort, dans}

Dans cette fonction de contexte (j) devrait revenir 1/6 .

Y at-il de toute façon que je peux trouver le nombre d'intersection et le nombre d'union de deux phrases? Pour un exemple, ici,

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; 
} 

Est-ce une fonction disponible en Java pour obtenir le nombre d'intersection et le nombre d'union sans utiliser des bibliothèques externes comme Google goyave?

+0

Notez que le coefficient Jaccard Index/Tanimoto n'a pas de définition unique. Il s'agit plutôt d'une méthode de mise en relation d'une intersection et d'une union avec un indice de précision, et son interprétation dépend donc de l'intersection particulière et des mesures d'union utilisées. Vous devez être spécifique à ce que vous recherchez, par ex. précision en termes de nombre de caractères communs en cas de traitement indépendant de la position, ou nombre de caractères en commun en fonction d'un alignement optimal (qui est alors soumis à l'algorithme d'alignement particulier utilisé). –

+1

@TasosPapastylianou Je regarde la précision par rapport au nombre de jetons (mots), quelle que soit leur position. – Yash

+0

Dans ce cas, tokenisez et triez par ordre alphabétique (en ignorant le cas ou non, jusqu'à vous) la concaténation des deux textes (ie ne gardant que des jetons uniques), puis faites deux tableaux en tenant compte du nombre de fois qu'un mot apparaît pour chaque individu texte. Votre interesection est la somme du minimum entre les deux tableaux sur tous les jetons, et votre union est la somme du maximum correspondant. –

Répondre

-1

Vous pouvez utiliser le texte d'Apache commons, qui n'a aucune autre dépendance externe. (https://commons.apache.org/proper/commons-text/)

texte similitude documentation de l'algorithme: https://commons.apache.org/sandbox/commons-text/apidocs/org/apache/commons/text/similarity/package-summary.html

Et vous pouvez trouver la mise en œuvre du coefficient Jaccard ici: https://github.com/apache/commons-text/blob/master/src/main/java/org/apache/commons/text/similarity/JaccardDistance.java

0

Comme vous ne souhaitez que la taille de l'union/intersection, vous pouvez calculer la taille de ces deux ensembles sans créer réellement l'ensemble d'union et d'intersection (union(a, b).size() est a.size() + b.size() - intersection(a, b).size() -> seule la taille d'intersection est requise).

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; 
}