web-dev-qa-db-ja.com

MATLABで行列を正規化するための高速手法

Matlabの行列の各列を正規化したい。私は2つの実装を試しました:

オプション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秒。したがって、より良い解決策はありますか?

10
RYN

MATLABでは、ベクトル化=速度であることを忘れないでください。

AがMx 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
8
eykanal

ループの代わりに bsxfun を使用します。これは少し速いかもしれません。ただし、より多くのメモリを使用する場合もあります(これは、あなたの場合に問題になる可能性があります。ページングしている場合、すべてが非常に遅くなります)。

平均値と標準値で正規化するには、次のように記述します。

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

xn = bsxfun(@minus,x,mn);
xn = bsxfun(@rdivide,xn,sd);
15
Jonas

注:このコードは、OctaveおよびMATLABバージョンR2016b以降で機能します。

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

Xm 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

注:前述のように、これは単により高速なソリューションであり、マトリックスをループするのと同じタスクを実行します。この組み込み関数の基礎となる実装により、機能が高速化されます

3
Rishi Dua

注:私は新たに新しい回答を提供していませんが、提案された回答を比較しています。

オプション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
tashuhka

使ってみませんか

normc(X)

これにより、行列Xが列方向に正規化されます。ただし、インストールにニューラルネットワークツールボックスを含める必要があります。

1
agcala