【问题标题】:Fast element wise multiplication of a column vector with a row vector in PLSPLS 中列向量与行向量的快速元素乘法
【发布时间】:2017-06-01 12:44:52
【问题描述】:

我正在使用 Matlab 执行大量迭代,并使用偏最小二乘法 (PLS) 作为每次迭代中处理数据的算法。它运行得很慢。使用profile 监控我的代码的每一行使用的时间表明X = X-t*p' 行,其中X 是大小为r 的矩阵ctp 是列向量大小为rc,大部分时间都需要花费。我认为原因可能是t*p' 扩展了内存,它从两个向量生成了一个矩阵,这是一个众所周知的原因,它会减慢 Matlab 中的计算速度。有没有办法加快这个速度?

PLS 代码是:

for iter = 1:maxiter % maxiter is defaultedly set as 10,000
    % preparing data....
    ......
    % perform PLS using NIPALS algorithm
    for a = 1:A
        x = X'*y;
        w = x/norm(x);
        t = X*w;
        tt = sum(t.^2);
        p = X'*(t/tt);
        q = sum(y.*t)/tt;
        X = X-t*p';     % updata X, this line costs most of the time
        y = y-t*q;        % updata y
    end

    % output w, P, q
    .......
end

【问题讨论】:

  • 我认为内置的向量乘法已经是一个很好的实现,你不能轻易地进一步优化。研究其他一些优化可能会更好:你能调整你的算法来避免乘法吗?你可以使用更少的迭代次数吗?
  • 为什么我被否决了?如果我能找到解决方案,我想我不会在这里发布任何问题。
  • @m7913d 我同意你的观点,Matlab 极大地优化了矩阵乘法。所以我发布了我实现的算法。我花了几天时间尝试优化算法并减少迭代次数,但失败了。
  • 如果您想总体上优化您的 PLS 算法,最好将其反映在您的标题中。你试过plsregress吗?
  • @m7913d 很好的提醒。它比我的要快得多。但是输出结果中存在问题可能是因为plsregress没有适合我的情况的参数,所以我会仔细研究Matlab实现PLS的方式,找出任何可以加快我的PLS的技巧。谢谢。

标签: matlab vector matrix-multiplication


【解决方案1】:

为避免XX = X-t*p'; 压缩,有三种方法,如"Computational performance and cross-validation error precision of five PLS algorithms using designed and real data sets" 中所述。我使用了以下算法:

  • SIMPLS

    for iter = 1:maxtest
        % preparing data...
        ... ...
        for a = 1:A
            % for a vector, eigenvector of S'*S is always 1
            ri = s;
            t = X*ri;
            normt = sqrt(sum(t.^2));
            t = t/normt;
            ri = ri/normt;
            % X loadings
            pi = X'*t;
            q = y'*t;
            %u = y*q;
            v = pi;
            if a > 1
                v = v-V(:,1:a-1)*(V(:,1:a-1)'*pi);
                %u = u-T(:,1:a-1)*(T(:,1:a-1)'*u);
            end
            v = v/sqrt(sum(v.^2));
            s = s-v*(v'*s);
    
            V(:,a) = v;
            R(:,a) = ri;
            Q(a) = q;
        end
        % PLS coefficient...
        b = R*Q;
        ...
    end
    
  • NIPALS-y

    for iter = 1:maxtest
        % preparint data...
        ... ...
        % NIPALS
        for a = 1:A
            x = X'*y;
            rx = x/norm(x);
            w = rx;
            if a > 1
                rx = rx-R(:,1:a-1)*(P(:,1:a-1)'*w);
            end
            t = X*rx;
            tt = sum(t.^2);
            P(:,a) = X'*t/tt;
            q(a) = y'*t/tt;
            y = y-t*q(a);
            % W(:, a) = w;
            R(:, a) = rx;
        end
    
        % PLS coefficient...
        b = R*q;
        ... ...
    end
    
  • 对角化

    for iter = 1:maxtest
        v = X'*y/norm(X'*y);
        u = X*v;
        normu = sqrt(sum(u.^2));
        u = u/normu;
        R(1) = normu;
        V(:,1) = v;
        U(:,1) = u;
        for a = 2:A
            v = X'*u-normu*v;
            normv = sqrt(sum(v.^2));
            v = v/normv;
            u = X*v-normv*u;
            normu = sqrt(sum(u.^2));
            u = u/normu;
            U(:,a) = u;
            V(:,a) = v;
            R(a-1,a) = normv;
            R(a,a) = normu;
        end
        % PLS coefficients...
        b = V*(R\(U'*y));
    end
    

使用大小为43 by 195的测试数据和10折交叉验证,双对角化方法最快,与论文结果一致。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-04
    相关资源
    最近更新 更多