矩阵列的点积
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
值来做到这一点,其中输出 X
和 Y
为您提供每对向量的配对,并且仅 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、...等)
所有这一切的要点是,然后可以使用 X
和 Y
创建两个新矩阵,其中包含位于每对 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 开始,因此您不需要不要看任何重复项。我们对位置 ii
和 jj
引用的相应列进行点积,并将结果存储在 B
中。我需要一个外部计数器,这样我们就可以正确访问正确的插槽来为每对列放置我们的结果。
我有一个 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
值来做到这一点,其中输出 X
和 Y
为您提供每对向量的配对,并且仅 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、...等)
所有这一切的要点是,然后可以使用 X
和 Y
创建两个新矩阵,其中包含位于每对 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 开始,因此您不需要不要看任何重复项。我们对位置 ii
和 jj
引用的相应列进行点积,并将结果存储在 B
中。我需要一个外部计数器,这样我们就可以正确访问正确的插槽来为每对列放置我们的结果。