矩阵列的点积

时间:2015-09-02 15:26:06

标签: matlab matrix dot-product

我有一个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 个答案:

答案 0 :(得分:2)

我会以不同的方式接近这一点。首先,创建两个矩阵,其中每个矩阵的相应列对应于矩阵中唯一的一对列。

我能想到的最简单的方法是创建所有可能的对组合,并消除重复。您可以通过创建meshgrid个值来执行此操作,其中输出XY为您提供每对向量的配对,并且仅选择每个矩阵的下三角形部分抵消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,......等)

所有这一切的重点是,然后可以使用XY创建两个新矩阵,其中包含位于每对XY的列,然后使用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

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