【问题标题】:Cosine similarity using Armadillo C++ gives me negative results使用犰狳 C++ 的余弦相似度给了我否定的结果
【发布时间】:2016-07-11 15:32:56
【问题描述】:

我已经实现了一个使用犰狳 c++ 线性库的余弦相似度函数。我的代码是下一个:

double cosine_similarity(rowvec A, rowvec B)
{
   double dot = as_scalar(A*B.t());
   double denomA = as_scalar(A*A.t());
   double denomB = as_scalar(B*B.t());
   return dot / (sqrt(denomA) * sqrt(denomB)) ;
}

我以这个矩阵为例:

-0.0261 -0.6780 -0.7338 0.0345

-0.0230 0.0082 -0.0400 -0.7056

-0.2590 -0.7052 0.6590 -0.0371

-0.9650 0.2072 -0.1551 0.0426

-0.0230 0.0082 -0.0400 -0.7056

当我计算第二行与所有行之间的余弦相似度时,我得到以下结果:

相似度 [1,0]:-1.07944e-16

相似度[1,1]:1

相似度 [1,2]:-1.96262e-17

相似度 [1,3]:-1.71729e-16

相似度 [1,4]: 1

这是正确的吗?我担心负面结果,即使它们的意思是零。我想知道我是否做错了什么。 cosine_similarity 是这样使用的:

for (unsigned int row = 0; row < redV.n_rows ; row++)
{
    double ans = cosine_similarity(redV.row(indicate), redV.row(row));
    cout << "Similarity [" << indicate << "," << row << "]: " << ans << endl;
    cout << "Similarity [" << indicate << "," << row << "]: " << norm_dot(redV.row(indicate), redV.row(row)) << endl;
}

【问题讨论】:

  • 为什么不直接使用norm_dot()函数呢?
  • 感谢您的建议。我得到了相同的结果。当 sm 在 matlab 上进行相同的计算时,我得到的数字略有不同..
  • 您还没有显示完整的代码。计算 Similarity [1,0] 的代码是什么?展示如何使用 cosine_similarity() 的具体示例。
  • @hbrerkere 我已经编辑了这个问题,所以你应该能够看到我如何调用余弦相似度函数。
  • 你的代码还没有完成——你还没有展示redV是如何初始化的。我得到以下结果:Similarity [1,0]: 6.99982e-05Similarity [1,1]: 1Similarity [1,2]: -1.1143e-05... 这些结果与 Matlab 和 Octave 相同。可能redV中数据不正确有问题。

标签: c++ linear-algebra armadillo


【解决方案1】:

您的代码似乎正确,您只是遇到了机器精度问题。 A*B.t() 用于第三行的AB 用于第二行(反之亦然)应该为零,但不是,但在机器精度范围内。 Scipy’s cosine也有同样的问题:

In [10]: from scipy.spatial.distance import cosine

In [11]: 1 - cosine([-0.2590, -0.7052, 0.6590, -0.0371], [-0.0230, 0.0082, -0.0400, -0.7056])
Out[11]: -1.114299639159988e-05  # <=============== should not be negative!

(我减去 1 只是因为 Scipy 定义 cosine 的方式。这个答案与你的答案不匹配,因为你只发布了四个小数点——但妙语是,它是否定的。)

如果要检查浮点数x 是否在另一个y 的机器精度范围内,请将它们与std::numeric_limits::epsilon 的差异进行比较。参见almost_equal here 的定义。您可能希望 cosine_similarity 检查结果是 almost_equal 为 0 还是 1,在这种情况下返回 0 或 1。

【讨论】:

    猜你喜欢
    • 2011-02-08
    • 2013-05-29
    • 2020-08-12
    • 1970-01-01
    • 2016-08-14
    • 2011-01-01
    • 1970-01-01
    • 2018-10-27
    相关资源
    最近更新 更多