代码之家  ›  专栏  ›  技术社区  ›  Haybert Markarian

矩阵列的点积

  •  -1
  • Haybert Markarian  · 技术社区  · 9 年前

    我有一个4x8矩阵,我想选择其中两个不同的列,然后导出它们的点积,然后将它们除以所选列的范数值,然后对所有可能的两个不同列重复此操作,并将向量保存在新矩阵中。有人能为我提供一个matlab代码吗? 我应该给我输出的代码是:

    A=[1 2 3 4 5 6 7 8;1 2 3 4 5 6 7 8;1 2 3 4 5 6 7 8;1 2 3 4 5 6 7 8;];
    
    for i=1:8
    
        for j=1:7
            B(:,i)=(A(:,i).*A(:,j+1))/(norm(A(:,i))*norm(A(:,j+1)));
        end
    
    end
    
    1 回复  |  直到 9 年前
        1
  •  2
  •   rayryeng    9 年前

    我会用不同的方式来处理这个问题。首先,创建两个矩阵,其中每个矩阵的对应列对应于矩阵中唯一的一对列。

    我能想到的最简单的方法是创建所有可能的成对组合,并消除重复。您可以通过创建 meshgrid 输出的值 X Y 给你一对向量,只选择每个矩阵的下三角部分,偏移1,得到对角线下的主对角线……这样做:

    num_columns = size(A,2);
    [X,Y] = meshgrid(1:num_columns);
    X = X(tril(ones(num_columns),-1)==1); Y = Y(tril(ones(num_columns),-1)==1);
    

    在您的案例中,坐标网格如下所示:

    >> [X,Y] = meshgrid(1:num_columns)
    
    X =
    
         1     2     3     4     5     6     7     8
         1     2     3     4     5     6     7     8
         1     2     3     4     5     6     7     8
         1     2     3     4     5     6     7     8
         1     2     3     4     5     6     7     8
         1     2     3     4     5     6     7     8
         1     2     3     4     5     6     7     8
         1     2     3     4     5     6     7     8
    
    
    Y =
    
         1     1     1     1     1     1     1     1
         2     2     2     2     2     2     2     2
         3     3     3     3     3     3     3     3
         4     4     4     4     4     4     4     4
         5     5     5     5     5     5     5     5
         6     6     6     6     6     6     6     6
         7     7     7     7     7     7     7     7
         8     8     8     8     8     8     8     8
    

    如您所见,如果我们选择每个矩阵的下三角部分(不包括对角线),您将得到唯一的对的所有组合,这是我在代码的最后部分所做的。选择下半部分很重要,因为通过这样做,MATLAB可以选择值 列方向的 ,遍历每个矩阵的下三角部分的列,可以按正确的顺序(即1-2、1-3、…、1-7、2-3、2-4、…等)对每对列进行精确排序

    所有这些的要点是 十、 Y 创建两个新矩阵,其中包含位于每对 十、 Y ,然后使用 dot 以将点积按列应用于每个矩阵。我们还需要将点积分别除以两个向量的大小的乘积。你不能使用MATLAB的内置函数 norm 因为它将计算矩阵的矩阵范数。因此,您必须分别对两个矩阵的每一列的所有行求和,然后将两个结果元素相乘,然后求平方根-这是过程的最后一步:

    matrix1 = A(:,X);
    matrix2 = A(:,Y);
    B = dot(matrix1, matrix2, 1) ./ sqrt(sum(matrix1.^2,1).*sum(matrix2.^2,1));
    

    我得到这个是为了 B :

    >> B
    
    B =
    
      Columns 1 through 11
    
         1     1     1     1     1     1     1     1     1     1     1
    
      Columns 12 through 22
    
         1     1     1     1     1     1     1     1     1     1     1
    
      Columns 23 through 28
    
         1     1     1     1     1     1
    

    嗯……这根本没用。为什么?你实际上在做的是找到 余弦角 在两个向量之间,由于每个向量都是另一个向量的标量倍数,所以分离每个向量的角度实际上是0,0的余弦是1。

    您应该使用不同的值 A 这样你就可以亲眼看到它是有效的。


    要使此代码与复制和粘贴兼容,请执行以下操作:

    %// Define A here:
    A = repmat(1:8, 4, 1);
    
    %// Code to produce dot products here
    num_columns = size(A,2);
    [X,Y] = meshgrid(1:num_columns);
    X = X(tril(ones(num_columns),-1)==1); Y = Y(tril(ones(num_columns),-1)==1);
    matrix1 = A(:,X);
    matrix2 = A(:,Y);
    B = dot(matrix1, matrix2, 1) ./ sqrt(sum(matrix1.^2,1).*sum(matrix2.^2,1));
    

    次要注释

    如果你有很多列 A. ,这可能非常占用内存。您可以让原始代码使用循环,但需要更改每一列的操作。

    你可以这样做:

    num_columns = nchoosek(size(A,2),2);
    B = zeros(1, num_columns);
    
    counter = 1;
    for ii = 1 : size(A,2)
        for jj = ii+1 : size(A,2)
            B(counter) = dot(A(:,ii), A(:,jj), 1) / (norm(A(:,ii))*norm(A(:,jj)));
            counter = counter + 1;
        end
    end
    

    注意,我们可以使用 标准 因为我们为函数的每个输入指定了向量。我们首先预先分配一个矩阵 B 它将包含所有可能组合的点积。然后,我们检查每对组合-注意内部 for 循环从最外层开始 对于 循环索引 添加了1 所以你不会看到任何重复。我们取位置引用的相应列的点积 ii jj 并将结果存储在 B 。我需要一个外部计数器,这样我们就可以正确地访问正确的插槽,以便将结果放入每对列中。