Sé acerca de los tipos de datos básicos y que los tipos flotantes (flotante, doble) no pueden contener algunos números exactamente.

Sin embargo, al portar algún código de Matlab a Python (Numpy) encontré algunas diferencias significativas en los cálculos, y creo que está volviendo a la precisión.

Tome el siguiente código, normalizando z un vector de 500 dimensiones con solo dos primeros elementos que tienen un valor distinto de cero.

Matlab:

Z = repmat(0,500,1); Z(1)=3;Z(2)=1;
Za = (Z-repmat(mean(Z),500,1)) ./ repmat(std(Z),500,1);
Za(1)
>>> 21.1694

Python:

from numpy import zeros,mean,std
Z = zeros((500,))
Z[0] = 3
Z[1] = 1
Za = (Z - mean(Z)) / std(Z)
print Za[0]
>>> 21.1905669677

Además de que el formato muestra un poco más de dígitos en Python, hay una gran diferencia (en mi opinión), más de 0.02

Tanto Python como Matlab están utilizando un tipo de datos de 64 bits (afaik). Python usa 'numpy.float64' y Matlab 'double'.

¿Por qué la diferencia es tan grande? ¿Cuál es más correcto?

18
Peter Smit 20 sep. 2011 a las 12:29

3 respuestas

La mejor respuesta

Tal vez la diferencia proviene de las llamadas mean y std. Compara esos primero.

Hay varias definiciones para std, algunas usan la raíz cuadrada de

1 / n * sum((xi - mean(x)) ** 2)

Otras usan

1 / (n - 1) * sum((xi - mean(x)) ** 2)

En lugar de.

Desde un punto matemático: estas fórmulas son estimadores de la varianza de una variable aleatoria distribuida normal. La distribución tiene dos parámetros sigma y mu. Si sabe mu exactamente, el estimador óptimo para sigma ** 2 es

1 / n * sum((xi - mu) ** 2)

Si tiene que estimar mu a partir de los datos utilizando mu = mean(xi), el estimador óptimo para sigma**2 es

1 / (n - 1) * sum((xi- mean(x))**2)
27
rocksportrocker 2 feb. 2015 a las 16:18

Para responder a su pregunta, no , esto no es un problema de precisión. Como @rocksportrocker señala, hay dos estimadores populares para la desviación estándar. std de MATLAB tiene ambos disponibles, pero como usos estándar uno diferente de lo que usaste en Python.

Pruebe std(Z,1) en lugar de std(Z):

Za = (Z-repmat(mean(Z),500,1)) ./ repmat(std(Z,2),500,1);Za(1)
sprintf('%1.10f', Za(1))

Lleva a

Za (1) = 21.1905669677

En MATLAB Lea la respuesta de rockspotrocker sobre cuál de los dos resultados es más apropiado para lo que desea hacer ;-).

14
Community 23 may. 2017 a las 12:33

De acuerdo con la documentación de std en SciPy , tiene un parámetro llamado ddof:

ddof : int, opcional
Significa Delta Grados de libertad. El divisor usado en los cálculos es N - ddof, donde N representa El número de elementos. Por defecto, ddof es cero.

En numpy, ddof es cero por defecto, mientras que en MATLAB es uno. Entonces, creo que esto puede resolver el problema:

std(Z,ddof=1)
3
cartoonist 3 ene. 2014 a las 19:03