matlab - normalizar - ¿Cómo funciona este código para estandarizar datos?
z score matlab (1)
Tengo una función
standardize
para un curso de aprendizaje automático que no estaba bien documentada y todavía soy nuevo en MATLAB, así que solo estoy tratando de desglosar la función.
Cualquier explicación de la sintaxis o la idea general de estandarización sería de gran ayuda.
Utilizamos esta función para estandarizar un conjunto de datos de capacitación proporcionados en una matriz grande.
Un desglose de la mayoría de las líneas del fragmento de código me ayudaría mucho.
Muchas gracias.
function [X, mean_X, std_X] = standardize(varargin)
switch nargin
case 1
mean_X = mean(varargin{1});
std_X = std(varargin{1});
X = varargin{1} - repmat(mean_X, [size(varargin{1}, 1) 1]);
for i = 1:size(X, 2)
X(:, i) = X(:, i) / std(X(:, i));
end
case 3
mean_X = varargin{2};
std_X = varargin{3};
X = varargin{1} - repmat(mean_X, [size(varargin{1}, 1) 1]);
for i = 1:size(X, 2)
X(:, i) = X(:, i) / std_X(:, i);
end
end
Este código acepta una matriz de datos de tamaño
M x N
, donde
M
es la dimensionalidad de una muestra de datos de esta matriz y
N
es el número total de muestras.
Por lo tanto, una columna de esta matriz es
una
muestra de datos.
Las muestras de datos están todas apiladas horizontalmente y son columnas.
Ahora, el verdadero propósito de este código es tomar todas las columnas de su matriz y estandarizar / normalizar los datos para que cada muestra de datos muestre media cero y varianza unitaria . Esto significa que después de esta transformación, si encuentra el valor medio de cualquier columna en esta matriz, sería 0 y la varianza sería 1. Este es un método muy estándar para normalizar valores en análisis estadístico, aprendizaje automático y visión por computadora. .
Esto en realidad proviene de la z-score en el análisis estadístico. Específicamente, la ecuación para la normalización es:
Dado un conjunto de puntos de datos, restamos el valor en cuestión por la media de estos puntos de datos, luego dividimos por la desviación estándar respectiva.
Cómo llamarías a este código es el siguiente.
Dada esta matriz, que llamaremos
X
, hay dos formas de llamar a este código:
-
Método # 1:
[X, mean_X, std_X] = standardize(X);
-
Método # 2:
[X, mean_X, std_X] = standardize(X, mu, sigma);
El primer método infiere automáticamente la media de cada columna de
X
y la desviación estándar de cada columna de
X
mean_X
y
std_X
devolverán vectores
1 x N
que le dan la desviación media y estándar de cada columna en la matriz
X
El segundo método le permite especificar manualmente una media (
mu
) y una desviación estándar (
sigma
) para cada columna de
X
Posiblemente sea para su uso en la depuración, pero en este caso especificaría tanto
mu
como
sigma
como vectores
1 x N
Lo que se devuelve para
mean_X
y
std_X
es idéntico a
mu
y
sigma
.
El código está un poco mal escrito en mi humilde opinión, porque ciertamente puede lograr esto vectorizado, pero la esencia del código es que encuentra la media de cada columna de la matriz
X
si estamos utilizando el Método # 1, duplica este vector para que se convierte en una matriz
M x N
, luego restamos esta matriz con
X
Esto restará cada columna por su respectiva media.
También calculamos la desviación estándar de cada columna antes de la resta media.
Una vez que hacemos eso, normalizamos nuestra
X
dividiendo cada columna por su respectiva desviación estándar.
Por cierto, hacer
std_X(:, i)
es superfluo ya que
std_X
ya es un vector
1 x N
std_X(:, i)
significa tomar todas las filas en la
i
ésima
columna.
Si ya tenemos un vector
1 x N
, esto simplemente se puede reemplazar con
std_X(i)
, un poco exagerado para mi gusto.
El Método # 2 realiza lo mismo que el Método # 1, pero proporcionamos nuestra propia media y desviación estándar para cada columna de
X
Por el bien de la documentación, así es como habría comentado el código:
function [X, mean_X, std_X] = standardize(varargin)
switch nargin %// Check how many input variables we have input into the function
case 1 %// If only one variable - this is the input matrix
mean_X = mean(varargin{1}); %// Find mean of each column
std_X = std(varargin{1}); %// Find standard deviation of each column
%// Take each column of X and subtract by its corresponding mean
%// Take mean_X and duplicate M times vertically
X = varargin{1} - repmat(mean_X, [size(varargin{1}, 1) 1]);
%// Next, for each column, normalize by its respective standard deviation
for i = 1:size(X, 2)
X(:, i) = X(:, i) / std(X(:, i));
end
case 3 %// If we provide three inputs
mean_X = varargin{2}; %// Second input is a mean vector
std_X = varargin{3}; %// Third input is a standard deviation vector
%// Apply the code as seen in the first case
X = varargin{1} - repmat(mean_X, [size(varargin{1}, 1) 1]);
for i = 1:size(X, 2)
X(:, i) = X(:, i) / std_X(:, i);
end
end
Si puedo sugerir otra forma de escribir este código, usaría la poderosa y poderosa función
bsxfun
.
Esto evita tener que duplicar elementos y podemos hacerlo bajo el capó.
Reescribiría esta función para que se vea así:
function [X, mean_X, std_X] = standardize(varargin)
switch nargin
case 1
mean_X = mean(varargin{1}); %// Find mean of each column
std_X = std(varargin{1}); %// Find std. dev. of each column
X = bsxfun(@minus, varargin{1}, mean_X); %// Subtract each column by its respective mean
X = bsxfun(@rdivide, X, std_X); %// Take each column and divide by its respective std dev.
case 3
mean_X = varargin{2};
std_X = varargin{3};
%// Same code as above
X = bsxfun(@minus, varargin{1}, mean_X);
X = bsxfun(@rdivide, X, std_X);
end
Yo diría que el nuevo código anterior es mucho más rápido que usar
for
y
repmat
.
De hecho, se sabe que
bsxfun
es más rápido que el enfoque anterior, especialmente para matrices más grandes.