矩阵列的点积

dot product of matrix columns

我有一个 4x8 矩阵,我想 select 它的两个不同列,然后导出它们的点积,然后除以 selected 列的标准值,然后重复此操作对于所有可能的两个不同列,并将向量保存在一个新矩阵中。谁能为此提供一个 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

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

我能想到的最简单的方法是创建所有可能的对组合,并消除重复项。您可以通过创建一个 meshgrid 值来做到这一点,其中输出 XY 为您提供每对向量的配对,并且仅 select 输出下三角部分每个矩阵偏移 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

如你所见,如果我们 select 取出每个矩阵的下三角部分,不包括对角线,你将得到所有唯一的对组合,这就是我在最后一部分所做的代码。选择下半部分很重要,因为通过这样做,MATLAB selects out values column-wise,并遍历每个矩阵的下三角部分的列给你每对列的正确顺序(即 1-2、1-3、...、1-7、2-3、2-4、...等)

所有这一切的要点是,然后可以使用 XY 创建两个新矩阵,其中包含位于每对 X 和 [=18 的列=],然后为此使用 dot to apply the dot product to each matrix column-wise. We also need to divide the dot product by the multiplication of the magnitudes of the two vectors respectively. You can't use MATLAB's built-in function 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 中。我需要一个外部计数器,这样我们就可以正确访问正确的插槽来为每对列放置我们的结果。