Быстрая техника для нормализации матрицы в MATLAB - PullRequest
10 голосов
/ 23 декабря 2010

Я хочу нормализовать каждый столбец матрицы в Matlab. Я пробовал две реализации:

Вариант А:

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

Однако эти параметры занимают слишком много времени для моих данных, например, 3-4 секунды на матрице 5000x53. Таким образом, есть ли лучшее решение?

Ответы [ 7 ]

15 голосов
/ 23 декабря 2010

Используйте bsxfun вместо цикла. Это может быть немного быстрее; однако он также может использовать больше памяти (что может быть проблемой в вашем случае; если вы выполняете пейджинг, все будет очень медленно).

Чтобы нормализовать со средним и стандартным значением, вы должны написать

mn = mean(x);
sd = std(x);
sd(sd==0) = 1;

xn = bsxfun(@minus,x,mn);
xn = bsxfun(@rdivide,xn,sd);
8 голосов
/ 23 декабря 2010

Помните, в 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 голосов
/ 27 июня 2016

Примечание: Этот код работает в версиях Octave и MATLAB R2016b или выше.

function X_norm = normalizeMatrix(X)      
      mu = mean(X); %mean    
      sigma = std(X); %standard deviation   
      X_norm = (X - mu)./sigma;    
end
3 голосов
/ 31 июля 2014

Примечание. Я не даю новый ответ, но сравниваю предложенные ответы.

Вариант 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 .

enter image description here

Ось X - это квадратный корень числа матричных элементов, а ось Y - время вычисления в секундах.

3 голосов
/ 28 сентября 2013

Пусть 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

Примечание: Как уже упоминалось, это просто более быстрое решение и выполняет ту же задачу, что и цикл по матрице. Базовая реализация этой встроенной функции заставляет ее работать быстрее

1 голос
/ 13 октября 2017

Как насчет использования

normc(X)

, что нормализует матрицу X по столбцам. Вам нужно включить Neural Network Toolbox в вашу установку.

0 голосов
/ 12 апреля 2015

Как насчет этого?

A = [7, 2, 6; 3, 8, 4]; % 2x3 матрица

Asum = сумма (A); % суммы столбцов

Anorm = A./Asum(ones(size(A, 1), 1), :); % нормализовать столбцы

...