我会用不同的方式来处理这个问题。首先,创建两个矩阵,其中每个矩阵的对应列对应于矩阵中唯一的一对列。
我能想到的最简单的方法是创建所有可能的成对组合,并消除重复。您可以通过创建
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
。我需要一个外部计数器,这样我们就可以正确地访问正确的插槽,以便将结果放入每对列中。