0

我正在做一些工作来推荐文档,为此我使用了余弦相似度方法。这是该方法的代码:

static double cosineSimilarity(HashMap<String, Double> v1, HashMap<String, Double> v2) 
{
    Set<String> both = v1.keySet();
    both.retainAll(v2.keySet());
    double sclar = 0, norm1 = 0, norm2 = 0;
    for (String k : both) 
    {
      sclar += v1.get(k) * v2.get(k);
    }
    for (String k : v1.keySet())
    {
      norm1 += v1.get(k) * v1.get(k);
    }
    for (String k : v2.keySet()) 
    {
      norm2 += v2.get(k) * v2.get(k);
    }
    return sclar / Math.sqrt(norm1 * norm2);
}

问题是结果会根据参数传递的顺序而有所不同。例如,如果我调用cosineSimilarity(v1, v2)它将返回0.3,但如果我调用cosineSimilarity(v2, v1)它将返回一个完全不同的值。

我认为这与返回一个由地图支持的集合的事实有关Map.keySet() ,但我并不完全理解这一点的含义。

任何人都可以看到该方法出错的地方吗?

4

1 回答 1

6

尝试

Set<String> both = new HashSet<String>(v1.keySet());

代替

Set<String> both = v1.keySet();

您不应该修改从keySet方法获得的集合,因为 map 使用它,并且当您从中删除元素时(retainAll在您的情况下),元素也会从 map 中删除。例子:

Map<Integer, Integer> mp = new HashMap<Integer, Integer>();
mp.put(1, 1);
System.out.println(mp); // output {1=1}
mp.keySet().remove(1);
System.out.println(mp); // output {}
于 2012-12-28T16:04:07.567 回答