我有一个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
答案 0 :(得分:2)
我会以不同的方式接近这一点。首先,创建两个矩阵,其中每个矩阵的相应列对应于矩阵中唯一的一对列。
我能想到的最简单的方法是创建所有可能的对组合,并消除重复。您可以通过创建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,......等)
所有这一切的重点是,然后可以使用X
和Y
创建两个新矩阵,其中包含位于每对X
和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
请注意,我们可以使用norm
因为我们为函数中的每个输入指定了向量。我们首先预先分配一个矩阵B
,它将包含所有可能组合的点积。然后,我们浏览每对组合 - 请注意内部for
循环从最外面的for
循环索引添加1 开始,所以你不要看任何重复。我们采用位置ii
和jj
引用的相应列的点积,并将结果存储在B
中。我需要一个外部计数器,以便我们可以正确访问正确的插槽,将结果放入每对列中。