我有一个n x m矩阵。让该矩阵的某一行表示为x。每行代表一些功能x1, x2, x3, ...
现在,我希望收到x * x'
对角线以上的元素,即:x1*x2, x1*x3, x2*x3
,...但不是x1*x1
。另外,如果我有x1*x2
,则不需要x2*x1
。
我想将这些列与产品一起添加到我的矩阵中。鉴于我之前有m
列,我会为这些产品添加其他列,即:(m^2 + m)/2 - m
列。
这应该为我的矩阵的每一行完成。
我已经在Matlab中找到了解决方案。然而,它似乎非常缓慢,我想知道是否有更多的矢量化解决方案,Matlab可以更快地执行。
我当前的解决方案使用包来获取上对角线上方元素的向量:https://de.mathworks.com/matlabcentral/fileexchange/23391-triangular-and-diagonal-indexing
矩阵M(itriu(size(M),1))
的 M
将在对角线上方提供矩阵元素。例如,如果我投入[1 2 3; 4 5 6; 7 8 9]
,我将得到2 3 6
作为结果。
我的代码如下:
function [ X_out ] = permutateFeatures( X_in )
%PERMUTATEFEATURES given a matrix with m features in the columns
% and n samples in the rows, return a [n (m^2 + m)/2] matrix
% where each additional column contains a element-wise product of two of
% the original columns
n = size(X_in, 1);
m = size(X_in, 2);
X_out = [X_in zeros(n, (m^2 + m)/2 - m)];
for i = 1:n
outerProduct = X_out(i,1:m)' * X_out(i,1:m);
X_out(i,:) = [X_in(i,:) outerProduct(itriu(size(outerProduct),1))'];
end
end
是否有更有效的解决方案?
答案 0 :(得分:2)
这是一个矢量化解决方案 -
[r,c] = find(triu(true(size(X_in,2)),1));
out = [X_in X_in(:,r).*X_in(:,c)];
运行时测试
时间码 -
% Setup input array
% (as stated in comments : m is mostly <20. n goes into the millions)
X_in = randi(5,[50000,20]);
disp('--------------------------- Original Solution')
tic,
n = size(X_in, 1);
m = size(X_in, 2);
X_out = [X_in zeros(n, (m^2 + m)/2 - m)];
for i = 1:n
outerProduct = X_out(i,1:m)' * X_out(i,1:m);
X_out(i,:) = [X_in(i,:) outerProduct(itriu(size(outerProduct),1))'];
end
toc
disp('--------------------------- Proposed Solution')
tic,
[r,c] = find(triu(true(size(X_in,2)),1));
out = [X_in X_in(:,r).*X_in(:,c)];
toc,
计时 -
--------------------------- Original Solution
Elapsed time is 8.618389 seconds.
--------------------------- Proposed Solution
Elapsed time is 0.131146 seconds.
60x+
的巨大加速!
答案 1 :(得分:1)
这里矩阵乘法是矢量化的,这是计算中更大的部分。如果你愿意,你也可以矢量化vec1和vec2的创建,但只有更多的效率:
vec1=[];
vec2=[];
for i = 1:n
vec1=[vec1 i*ones(1,n-i)];
vec2=[vec2 (i+1):n];
end
X_out2=[X_in X_in(:,vec1).*X_in(:,vec2)];
对于rand(1000,1000)
旧方法而言,执行此方法
Elapsed time is 24.709988 seconds.
Elapsed time is 6.753230 seconds.
在我的机器上,使用相同的解决方案。