【问题标题】:Cosine similarity of each row in a matrix矩阵中每一行的余弦相似度
【发布时间】:2016-09-08 05:11:38
【问题描述】:

我有一个名为vectors[i][j]的矩阵。我想计算每一行之间的余弦相似度。例如对于这个矩阵

    1 0 1 0 1 0 0
v=  0 0 1 1 1 0 1
    1 1 0 0 1 0 1

我想在第 1 行和第 2 行、第 1 行和第 3 行、第 2 行和第 3 行之间进行相似度计算。如果第 1 行和第 2 行之间的相似度相等 = 0.6,其他分别为 0.5 和 0.4,则进一步计算。我想在其中的每个元素(e=!0)上将此值添加到行中,并得到这样的最终矩阵。

    2.1    0    2.1   0   2.1    0    0
v=  0      0     2    2    2     0    2
    1.9   1.9    0    0   1.9    0   1.9

这是我定义和填充矩阵的代码部分;

string text = Request.Form["TextBox1"]; ; // text
            string[] textInArray = text.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
            int[,] vectors = new int[textInArray.Length, keywords.Length];

            for (int i = 0; i < textInArray.Length; i++)
            {
                string[] words = textInArray[i].Split(' ');
                for (int j = 0; j < keywords.Length; j++)
                {
                    foreach (var word in words)
                    {
                        if (word.Contains(keywords[j]))
                        {
                            vectors[i, j]++;
                        }
                    }
                }
            }

这是我计算相似度的代码,但我认为它在某个地方不完整,我有错误,我不知道如何在当前两行的元素上添加这个值。

for(i=1 i<matrix.GetLength(0) i++){
   for(j=1 j<matrix.GetLength(0) j++){
            dot += vectors[i] * vectors[j];
            mag1 += Math.Pow(vectors[i], 2);
            mag2 += Math.Pow(vectors[j], 2);
        }

        float M= dot / (Math.Sqrt(mag1) * Math.Sqrt(mag2));  

}
}

【问题讨论】:

  • 删除 asp.net 标记,因为问题似乎与 asp.net 没有任何关系,添加 C#

标签: c# matrix cosine-similarity


【解决方案1】:

分解您的解决方案!提取Similarity方法

private static double Similarity(double[] left, double[] right) {
  double ab = 0.0;
  double aa = 0.0;
  double bb = 0.0;

  for (int i = 0; i < left.length; ++i) {
    aa += left[i] * left[i];
    ab += left[i] * right[i];
    bb += right[i] * right[i]; 
  }

  // do not forget degenerated cases: all-zeroes vectors 
  if (aa == 0) 
    return bb == 0 ? 1.0 : 0.0;
  else if (bb == 0) 
    return 0.0;
  else
    return ab / Math.Sqrt(aa) / Math.Sqrt(bb);
}

然后放简单的逻辑

// vectors[][] is an array of array, so we can get lines easily by vectors[0] etc.
double sim12 = Similarity(vectors[0], vectors[1]);
double sim23 = Similarity(vectors[1], vectors[2]);
double sim13 = Similarity(vectors[0], vectors[2]);

// compare double with tolerance
if ((Math.Abs(sim12 - 0.6) < 1e-10) &&
    (Math.Abs(sim13 - 0.5) < 1e-10) &&
    (Math.Abs(sim23 - 0.4) < 1e-10)) {
  //TODO: update the matrix
}

编辑:因为事实上vectorsdouble[,] (二维数组)

private static double Similarity(double[,] matrix, int left, int right) {
  double ab = 0.0;
  double aa = 0.0;
  double bb = 0.0;

  for (int i = 0; i < matrix.GetLength(1); ++i) {
    aa += matrix[left, i] * matrix[left, i];
    ab += matrix[left, i] * matrix[right, i];
    bb += matrix[right, i] * matrix[right, i]; 
  }

  if (aa == 0) 
    return bb == 0 ? 1.0 : 0.0;
  else if (bb == 0) 
    return 0.0;
  else
    return ab / Math.Sqrt(aa) / Math.Sqrt(bb);
}

....

double sim12 = Similarity(vectors, 0, 1);
double sim23 = Similarity(vectors, 1, 2);
double sim13 = Similarity(vectors, 0, 2);

【讨论】:

  • 我收到此错误“[] 内的索引数量错误;对于 linedouble sim12= Similarity(....) 预期为 2”你认为这是因为我在开始时定义了我的矩阵吗像这样? int[,] 向量 = new int[textInArray.Length, keywords.Length];
  • @:dpointttt:它是。如果您有像 the question vectors[i][j] 中的矩阵,即 array of array 我的代码会这样做;但如果你真的把它放在int[,] vectors2D array 我的代码不会做。数组数组(又名 jugged 数组)比 2D 数组灵活得多
  • @:dpointttt:但是,主要原理是一样的:提取方法无论你有什么矩阵表示。
  • 感谢您的快速回答,我怎样才能改变我的矩阵,这将与您发布的方法一起使用我尝试过但没有奏效; int[][] 向量 = new int[textInArray.Length, keywords.Length];或 double[][] 向量= new double[textInArray.Length][keywords.Length];
  • 我已将定义矩阵的代码部分添加到第一篇文章
猜你喜欢
  • 1970-01-01
  • 2021-08-20
  • 2015-07-17
  • 2019-12-23
  • 2012-07-09
  • 2017-06-13
  • 2019-05-31
  • 2015-12-23
  • 2020-10-28
相关资源
最近更新 更多