在MATLAB中计算一个无循环的文法矩阵

在MATLAB中计算一个无循环的文法矩阵,matlab,svm,Matlab,Svm,我有一个矩阵X(10000800)。我想计算gram矩阵K(1000010000),其中K(I,j)=exp(-(X(I,:)-X(j,:)^2) 首先,我使用了double for循环,但是它永远挂起。 然后我试了一下: [N d] = size(X); aa = repmat(X',[1 N]); bb = repmat(reshape(X',1,[]),[N 1]); K = reshape((aa-bb).^2, [N*N d]); K = reshape(sum(D,2),[N N])

我有一个矩阵
X(10000800)
。我想计算gram矩阵
K(1000010000)
,其中
K(I,j)=exp(-(X(I,:)-X(j,:)^2)

首先,我使用了double for循环,但是它永远挂起。 然后我试了一下:

[N d] = size(X);
aa = repmat(X',[1 N]);
bb = repmat(reshape(X',1,[]),[N 1]);
K = reshape((aa-bb).^2, [N*N d]);
K = reshape(sum(D,2),[N N]);
但是它占用了很多额外的空间,我的内存很快就用完了。 有没有有效的矢量化方法。
我相信一定有什么原因,因为这是许多内核支持向量机以及图像处理的标准中间步骤。

为什么不使用简单的公式呢? 对于元素
K(i,j)=exp(sum_{K=0}^{n}(X(i,K)-X(j,K))^2
。 因此,
i
j
有两个外循环,
k
有一个内循环。时间复杂度是
O(m^2n)
,其中
X
中有
m
行和
n
列。空间复杂度是
O(1)
因为计算答案时,除了使用
X
K
矩阵外,不会使用更多的空间

你试过这个了吗?它真的很慢吗?

使用或pdist。请注意,Matlab中的pdist2只是。。。

代码:

我写这篇文章是为了更一般的情况,你有两个矩阵,你想找到所有的距离。
(x-y)^2=x'x-2x'y+y'y
如果要计算Gram矩阵,需要所有差分组合

X = rand(100, 3);
Y = rand(50, 3);
A = sum(X .* X, 2);
B = -2 *X * Y';
C = sum(Y .* Y, 2);
K = bsxfun(@plus, A, B);
K = bsxfun(@plus, K, C);
K = exp(-K);
编辑:速度比较 代码 请注意,在问题要求大小的第100位,另一个答案(
O(m^2 n)
)中建议的代码的性能要慢两个数量级。到那时,我插入了100k作为
X
矩阵的大小,这比我愿意等待的时间要长得多

全尺寸问题(
X=rand(10000800)
)的性能如下:

pdist took  5.470632e+01 seconds
Vectorized solution took    1.141894e+01 seconds.
评论
矢量化的解决方案用了11秒,Matlab的pdist用了55秒,而另一个示例中建议的手动解决方案从未完成。

请更清楚地说明这个语法矩阵的表达式。我认为这两个代码都是错误的。在第一个代码中,你取行向量的二次幂,并将向量分配给标量。在第二个代码段中,你取
D
,它没有定义。这里也没有指数,而在第一行代码中有exp。Gram矩阵看起来像所有可能的向量内积。为什么要计算exp?很抱歉搞混了。在第一个代码中,我的意思是取距离的范数的平方,所以它应该是量值的平方,实际上这只是解释什么是gram矩阵。在第二个代码片段中,它是K而不是D。K=0(N,N);对于i=1:N fprintf('i=%D\N',i运行外循环);对于j=1:nxij=X(i,:)-X(j,:);xij=norm(xij,2);xij=xij^2;K(i,j)=-xij;结束K=exp(K)我试过了,但是花了我一个多小时。所以,我认为如果有矢量化方法的话,应该可以加快速度。老实说,我不知道有什么神奇的矢量化。而且,
norm(xij,2)^2
dot(xij,xij)
,所以你可以写
K(I,j)=-(dot(xij,xij))
。除此之外,我觉得您可以尝试编写一个MEX文件(C模块),而不是一个时髦的矢量化解决方案。这非常简单!:)下面是一个链接,让您开始学习
% http://stackoverflow.com/questions/13109826/compute-a-gramm-matrix-in-matlab-without-loops/24407122#24407122
function time_gramm()
% I have a matrix X(10000, 800). I want to compute gramm matrix K(10000,10000), where K(i,j)= exp(-(X(i,:)-X(j,:))^2).
X = rand(100, 800);

%% The straight-forward pdist solution.
tic;
K = squareform(pdist(X, 'euclidean'));
K1 = exp(-K .^2);
t1 = toc;
fprintf('pdist took \t%d seconds\n', t1);

%% The vectorized solution
tic;
A = sum(X .* X, 2);
B = -2 * X * X';
K = bsxfun(@plus, A, B);
K = bsxfun(@plus, K, A');
K2 = exp(-K);
t2 = toc;
fprintf('Vectorized solution took \t%d seconds.\n', t2);

%% The not-so-smart triple-loop solution
tic;
N = size(X, 1);
K3 = zeros(N, N);
for i=1:N
    %     fprintf('Running outer loop for i= %d\n', i);
    for j=1:N
        xij = X(i,:) - X(j,:);
        xij = norm(xij, 2);
        xij = xij ^ 2;
        K3(i,j) = -xij;
        %         d = X(i,:) - X(j,:); % Alternative way, twice as fast but still
        %         orders of magnitude slower than the other solutions.
        %         K3(i,j) = exp(-d * d');
    end
end
K3 = exp(K3);
t3 = toc;
fprintf('Triple-nested loop took \t%d seconds\n', t3);
%% Assert results are the same...
assert(all(abs(K1(:) - K2(:)) < 1e-6 ));
assert(all(abs(K1(:) - K3(:)) < 1e-6 ));
end
pdist took  8.600000e-03 seconds
Vectorized solution took    3.916000e-03 seconds.
Triple-nested loop took     2.699330e-01 seconds
pdist took  5.470632e+01 seconds
Vectorized solution took    1.141894e+01 seconds.