从数组的每一行中减去多个向量(超广播)

Eng*_*ero 3 matlab vectorization octave bsxfun

我有一个数据集,Xm x 2三个存储在矩阵C = [c1'; c2'; c3']中的向量3 x 2.我试图对我的代码进行矢量化,为每个数据点找到X哪个矢量C最接近(平方距离).我想减去每个向量(行)C从每个向量(行)X,导致m x 63m x 2的的元素之间的差异矩阵X和的元素C.我目前的实现一次只进行一行X:

for i = 1:size(X, 1)
    diffs = bsxfun(@minus, X(i,:), C);    % gives a 3 x 2 matrix result
    [~, idx(i)] = min(sumsq(diffs), 2);   % returns the index of the closest vector
                                          % in C to the ith vector in X
end
Run Code Online (Sandbox Code Playgroud)

我想摆脱这个for循环,只是矢量化整个事情,但bsxfun(@minus, X, C)在Octave中给我一个错误:

错误:bsxfun:不一致的尺寸:300x2和3x2

我有什么想法可以"超广播"这两个矩阵之间的减法运算?

Da *_*ang 5

此问题的核心是计算D大小的距离矩阵,m x 3该矩阵包含所有数据点X和所有数据点之间的成对距离C.第i个矢量x_i输入X和第j个矢量c_j输入之间的欧几里德距离C可以改写为:

|x_i-c_j|^2 = |x_i|^2 - 2<x_i, c_j> + |c_j|^2
Run Code Online (Sandbox Code Playgroud)

其中<,>指内在产品.这个等式的右边可以很容易地进行矢量化,因为所有对的内积X * C'都是BLAS3操作.这种计算距离矩阵的dist2方法在Christopher Bishop的书籍模式识别和机器学习中被称为函数.我稍微修改了下面的功能.

function D = dist2(X, C)        
    tempx = full(sum(X.^2, 2));
    tempc = full(sum(C.^2, 2).');
    D = -2*(X * C.'?;
    D = bsxfun(@plus, D, tempx);
    D = bsxfun(@plus, D, tempc);
Run Code Online (Sandbox Code Playgroud)

full这里的情况下,使用XC是稀疏矩阵.

注意:D由于数字舍入误差,以这种方式计算的距离矩阵可能具有微小的负数条目.为了防范这种情况,请使用

D = max(D, 0);
Run Code Online (Sandbox Code Playgroud)

C可以从D以下位置检索最近矢量的索引:

[~, idx] = min(D, [], 2);
Run Code Online (Sandbox Code Playgroud)

  • @Engineero:看他的[网页](http://www.cc.gatech.edu/~dkuang3/software/kmeans3.html) - 我想你会觉得很有意思:) (2认同)