xlabel - title matlab
Cómo normalizar un vector en MATLAB de manera eficiente? ¿Alguna función incorporada relacionada? (6)
El único problema con el que se encontraría es si la norma de V es cero (o muy cercana). Esto podría darte Inf o NaN cuando dividas, junto con una advertencia de dividir por cero. Si no le importa obtener un Inf o NaN , puede activar y desactivar la advertencia utilizando WARNING :
oldState = warning(''off'',''MATLAB:divideByZero''); % Return previous state then
% turn off DBZ warning
uV = V/norm(V);
warning(oldState); % Restore previous state
Si no quiere ningún valor Inf o NaN , primero debe verificar el tamaño de la norma:
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
Si lo necesito en un programa, generalmente pongo el código anterior en mi propia función, generalmente llamada unidad (ya que básicamente convierte un vector en un vector unitario que apunta en la misma dirección).
Normalizo un vector V en MATLAB de la siguiente manera:
normalized_V = V/norm(V);
sin embargo, ¿es la forma más elegante (eficiente) de normalizar un vector en MATLAB?
El código original que sugieres es la mejor manera.
Matlab es extremadamente bueno en operaciones vectorizadas como esta, al menos para vectores grandes.
La función de norma incorporada es muy rápida. Aquí hay algunos resultados de tiempo:
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 se calcula por segunda vez aquí solo para asegurarse de que no haya penalizaciones de caché importantes en la primera llamada.
La información de tiempo aquí se produjo con R2008a x64 en Windows.
EDITAR:
Respuesta revisada basada en las sugerencias de gnovice (ver comentarios). La Matriz matemática (apenas) gana:
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
En mi humilde opinión, la diferencia entre "norma (V)" y "sqrt (V ''* V)" es lo suficientemente pequeña como para que para la mayoría de los programas, es mejor ir con la que es más clara. Para mí, "norma (V)" es más clara y fácil de leer, pero "sqrt (V ''* V)" sigue siendo idiomática en Matlab.
Lo más rápido posible (el tiempo es en comparación con Jacobs):
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
No conozco ningún MATLAB y nunca lo he usado, pero me parece que estás dividiéndote. ¿Por qué? Algo así será mucho más rápido:
d = 1/norm(V)
V1 = V * d
Por la razón de hacer que todo sea una multiplicación, agrego la entrada al final de la lista
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
Tomé el código del Sr. Fooz y también agregué la solución de Arlen y aquí están los tiempos que he obtenido para 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
Luego, debido a algo que estoy mirando actualmente, probé este código para asegurar que cada fila sume a 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