在PLS中将列向量与行向量快速元素相乘

时间:2017-06-01 12:44:52

标签: matlab vector matrix-multiplication

我使用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

1 个答案:

答案 0 :(得分:0)

为避免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倍交叉验证,双向对角化方法是最快的,与论文结果一致。