如何在MATLAB中有效地标准化vector? 任何相关的内置函数?
我在MATLAB中对vectorV进行归一化,如下所示:
normalized_V = V/norm(V);
然而,在MATLAB中规范化vector是否是最优雅(有效)的方法呢?
您build议的原始代码是最好的方法。
Matlab非常擅长vector化操作,至less对于大型vector来说。
内置的规范function非常快。 以下是一些计时结果:
V = rand(10000000,1); % Run once tic; V1=V/norm(V); toc % result: 0.228273s tic; V2=V/sqrt(sum(V.*V)); toc % result: 0.325161s tic; V1=V/norm(V); toc % result: 0.218892s
V1在这里被第二次计算,以确保在第一次调用时没有重要的caching损失。
这里的时序信息是在Windows上用R2008a x64制作的。
编辑:
根据gnovice的build议修改答案(见注释)。 matrixmath(几乎)赢:
clc; clear all; V = rand(1024*1024*32,1); N = 10; tic; for i=1:N, V1 = V/norm(V); end; toc % 6.3 s tic; for i=1:N, V2 = V/sqrt(sum(V.*V)); end; toc % 9.3 s tic; for i=1:N, V3 = V/sqrt(V'*V); end; toc % 6.2 s *** tic; for i=1:N, V4 = V/sqrt(sum(V.^2)); end; toc % 9.2 s tic; for i=1:N, V1=V/norm(V); end; toc % 6.4 s
恕我直言,“规范(V)”和“sqrt(V'* V)”之间的区别足够小,对于大多数程序来说,最好使用更清晰的程序。 对我来说,“规范(V)”更清晰易读,但“sqrt(V'* V)”在Matlab中仍然是惯用的。
我不知道任何MATLAB,我从来没有使用它,但在我看来,你正在分裂。 为什么? 这样的事情会更快:
d = 1/norm(V) V1 = V * d
你遇到的唯一问题是如果V的范数是零(或者非常接近它)。 这可能会给你Inf或NaN ,除以零分的警告。 如果您不关心获取Inf或NaN ,可以使用警告开启和closures警告 :
oldState = warning('off','MATLAB:divideByZero'); % Return previous state then % turn off DBZ warning uV = V/norm(V); warning(oldState); % Restore previous state
如果您不需要任何Inf或NaN值,则必须先检查规范的大小:
normV = norm(V); if normV > 0, % Or some other threshold, like EPS uV = V/normV; else, uV = V; % Do nothing since it's basically 0 end
如果我在程序中需要它,我通常会把上面的代码放在我自己的函数中,通常称为单位 (因为它基本上把一个vector变成指向相同方向的单位vector)。
我拿了Fooz先生的代码,也加了Arlen的解决scheme,下面是我为Octave获得的时间:
clc; clear all; V = rand(1024*1024*32,1); N = 10; tic; for i=1:N, V1 = V/norm(V); end; toc % 7.0 s tic; for i=1:N, V2 = V/sqrt(sum(V.*V)); end; toc % 6.4 s tic; for i=1:N, V3 = V/sqrt(V'*V); end; toc % 5.5 s tic; for i=1:N, V4 = V/sqrt(sum(V.^2)); end; toc % 6.6 s tic; for i=1:N, V1 = V/norm(V); end; toc % 7.1 s tic; for i=1:N, d = 1/norm(V); V1 = V*d;end; toc % 4.7 s
然后,由于我目前正在看的东西,我testing了这个代码,以确保每行的总和为1:
clc; clear all; m = 2048; V = rand(m); N = 100; tic; for i=1:N, V1 = V ./ (sum(V,2)*ones(1,m)); end; toc % 8.2 s tic; for i=1:N, V2 = bsxfun(@rdivide, V, sum(V,2)); end; toc % 5.8 s tic; for i=1:N, V3 = bsxfun(@rdivide, V, V*ones(m,1)); end; toc % 5.7 s tic; for i=1:N, V4 = V ./ (V*ones(m,m)); end; toc % 77.5 s tic; for i=1:N, d = 1./sum(V,2);V5 = bsxfun(@times, V, d); end; toc % 2.83 s tic; for i=1:N, d = 1./(V*ones(m,1));V6 = bsxfun(@times, V, d);end; toc % 2.75 s tic; for i=1:N, V1 = V ./ (sum(V,2)*ones(1,m)); end; toc % 8.2 s
通过增加一切的合理性,我在列表的最后添加条目
clc; clear all; V = rand(1024*1024*32,1); N = 10; tic; for i=1:N, V1 = V/norm(V); end; toc % 4.5 s tic; for i=1:N, V2 = V/sqrt(sum(V.*V)); end; toc % 7.5 s tic; for i=1:N, V3 = V/sqrt(V'*V); end; toc % 4.9 s tic; for i=1:N, V4 = V/sqrt(sum(V.^2)); end; toc % 6.8 s tic; for i=1:N, V1 = V/norm(V); end; toc % 4.7 s tic; for i=1:N, d = 1/norm(V); V1 = V*d;end; toc % 4.9 s tic; for i=1:N, d = norm(V)^-1; V1 = V*d;end;toc % 4.4 s
到目前为止最快(时间与雅各比相比):
clc; clear all; V = rand(1024*1024*32,1); N = 10; tic; for i=1:N, d = 1/sqrt(V(1)*V(1)+V(2)*V(2)+V(3)*V(3)); V1 = V*d; end; toc % 1.5s