【问题标题】:Fast technique for normalizing a matrix in MATLAB在 MATLAB 中对矩阵进行归一化的快速技术
【发布时间】:2011-05-30 03:02:12
【问题描述】:

我想在 Matlab 中标准化矩阵的每一列。我尝试了两种实现方式:

选项 A:

mx=max(x);
mn=min(x);
mmd=mx-mn;
for i=1:size(x,1)
    xn(i,:)=((x(i,:)-mn+(mmd==0))./(mmd+(mmd==0)*2))*2-1; 
end

选项 B:

mn=mean(x);
sdx=std(x);
for i=1:size(x,1)
    xn(i,:)=(x(i,:)-mn)./(sdx+(sdx==0));
end

但是,这些选项占用我的数据太多时间,例如在 5000x53 矩阵上 3-4 秒。那么,有没有更好的解决方案呢?

【问题讨论】:

    标签: matlab normalization performance


    【解决方案1】:

    使用bsxfun 代替循环。这可能会快一点;但是,它也可能会使用更多内存(在您的情况下这可能是一个问题;如果您正在分页,一切都会很慢)。

    要使用均值和标准进行归一化,您可以这样写

    mn = mean(x);
    sd = std(x);
    sd(sd==0) = 1;
    
    xn = bsxfun(@minus,x,mn);
    xn = bsxfun(@rdivide,xn,sd);
    

    【讨论】:

    • 你为什么用sd(sd==0) = 1;而不是sd(sd==0) = eps;
    • @tashuhka: 因为我后来除以sd 的值。如果我除以 1,结果不变;如果我除以eps,结果乘以一个大数。
    • 感谢您的回复。我想这是一个偏好问题。运算0/eps 总是返回零,所以除法没有问题。但是,如果我想保留 sd 矩阵以供进一步分析,eps 值比零更能表示实际可变性。
    【解决方案2】:

    请记住,在 MATLAB 中,矢量化 = 速度。

    如果A是一个M x N矩阵,

    A = rand(m,n);
    minA = repmat(min(A), [size(A, 1), 1]);
    normA = max(A) - min(A);               % this is a vector
    normA = repmat(normA, [length(normA) 1]);  % this makes it a matrix
                                           % of the same size as A
    normalizedA = (A - minA)./normA;  % your normalized matrix
    

    【讨论】:

      【解决方案3】:

      注意:我没有提供全新的答案,但我正在比较建议的答案。

      选项 A:使用bsxfun()

      function xn = normalizeBsxfun(x)
      
          mn = mean(x);
          sd = std(x);
          sd(sd==0) = eps;
      
          xn = bsxfun(@minus,x,mn);
          xn = bsxfun(@rdivide,xn,sd);
      
      end
      

      选项 B:使用 for 循环

      function xn = normalizeLoop(x)
      
          xn = zeros(size(x));
      
          for ii=1:size(x,2)
              xaux = x(:,ii);
              xn(:,ii) = (xaux - mean(xaux))./mean(xaux);
          end
      
      end
      

      我们比较不同矩阵大小的两种实现:

      expList = 2:0.5:5;
      for ii=1:numel(expList)
          expNum = round(10^expList(ii));
          x = rand(expNum,expNum); 
          tic;
          xn = normalizeBsxfun(x);
          ts(ii) = toc; 
          tic;
          xn = normalizeLoop(x);
          tl(ii) = toc; 
      end
      
      figure;
      hold on;
      plot(round(10.^expList),ts,'b');
      plot(round(10.^expList),tl,'r');
      legend('bsxfun','loop');
      set(gca,'YScale','log') 
      

      结果表明,对于小矩阵,bsxfun 更快。但是,对于更高的维度,差异是可以忽略的,因为它也在其他 post 中发现。

      x 轴是矩阵元素的平方根数,而 y 轴是以秒为单位的计算时间。

      【讨论】:

        【解决方案4】:

        X 成为m x n 矩阵,并且您希望按列标准化。

        下面的matlab代码做到了

        XMean = repmat(mean(X),m,1);
        XStd = repmat(std(X),m,1);
        X_norm = (X - XMean)./(XStd);
        

        元素方面的 ./ 操作符在这里解释:http://www.mathworks.in/help/matlab/ref/arithmeticoperators.html

        注意:正如操作所提到的,这只是一个更快的解决方案,并且执行与遍历矩阵相同的任务。这个内置函数的底层实现使它运行得更快

        【讨论】:

        • 这对矩阵进行了归一化,使每一列的均值为零,单位方差。最初的问题只是想将每一列标准化为[0,1]。 YMMV。
        【解决方案5】:

        注意:此代码适用于 Octave 和 MATLAB R2016b 或更高版本。

        function X_norm = normalizeMatrix(X)      
              mu = mean(X); %mean    
              sigma = std(X); %standard deviation   
              X_norm = (X - mu)./sigma;    
        end
        

        【讨论】:

        • 这在 matlab 中不起作用,但在 octave 中起作用。
        • 这不适用于旧版 MATLAB(2016b 之前的版本)。从 R2016b 开始,启用了自动广播,因此这适用于那些版本的 MATLAB。
        • 另请注意,此代码使用零均值单位方差执行归一化。这不一定能实现 OP 想要的,它只是将每一列标准化为[0,1] 的范围。
        【解决方案6】:

        如何使用

        normc(X)
        

        这将按列对矩阵 X 进行归一化。不过,您需要在安装中包含神经网络工具箱。

        【讨论】:

        • 这并没有为当前的答案列表添加任何有意义的东西......更不用说它依赖于一个工具箱,而所有其他方法都没有。
        【解决方案7】:

        这个怎么样?

        A = [7, 2, 6; 3、8、4]; % 一个 2x3 矩阵

        Asum = sum(A); % 对列求和

        Anorm = A./Asum(ones(size(A, 1), 1), :); % 规范化列

        【讨论】:

        • 元素与Asum(ones(...)) 的重复对于较大的矩阵是非常危险的。如果矩阵的大小很大,您将看到巨大的性能瓶颈。
        猜你喜欢
        • 2016-07-25
        • 1970-01-01
        • 2017-09-11
        • 1970-01-01
        • 2011-12-28
        • 1970-01-01
        • 2011-11-30
        • 2012-01-17
        • 1970-01-01
        相关资源
        最近更新 更多