Précision, pourquoi Matlab et Python numpy donnent-ils des sorties si différentes?
je connais les types de données de base et que les types float (float, double) ne peuvent pas contenir certains nombres exactement.
en transférant du code de Matlab à Python (Numpy), j'ai cependant trouvé des différences significatives dans les calculs, et je pense que cela revient à la précision.
prendre le code suivant, z-normaliser un vecteur de 500 dimensions avec seulement deux premiers éléments ayant un non-zéro valeur.
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
<!-En plus du fait que le formatage montre un peu plus de chiffres en Python, il y a une énorme différence (imho), plus de 0.02
Python et Matlab utilisent tous deux un type de données 64 bits (afaik). Python utilise ' numpy.float64 "et Matlab "double".
Pourquoi la différence si énorme? Laquelle est la plus correcte?
3 réponses
Peut-être que la différence vient de la mean
et std
appels. Comparez les d'abord.
il existe plusieurs définitions pour std
, certains utilisent la racine sqaure de
1 / n * sum((xi - mean(x)) ** 2)
d'autres utilisent
1 / (n - 1) * sum((xi - mean(x)) ** 2)
à la place.
D'un point mathématique: ces formules sont des estimateurs de la variance d'une variable aléatoire normale distribuée. La distribution a deux paramètres sigma
et mu
. Si vous connaissez mu
exactement la estimateur optimal pour sigma ** 2
1 / n * sum((xi - mu) ** 2)
si vous devez estimer mu
à partir de données à l'aide de mu = mean(xi)
, l'estimateur optimal pour sigma**2
1 / (n - 1) * sum((xi- mean(x))**2)
pour répondre À ta question, aucun, ce n'est pas un problème de précision. @rocksportrocker, il y a des deux estimateurs pour l'écart-type. MATLAB's std
a les deux disponibles mais en standard utilise un différent de ce que vous avez utilisé en Python.
std(Z,1)
au lieu de std(Z)
:
Za = (Z-repmat(mean(Z),500,1)) ./ repmat(std(Z,2),500,1);Za(1)
sprintf('%1.10f', Za(1))
mène à
Za (1) = 21.1905669677
dans MATLAB. Lire rockspotrocker réponse sur laquelle des deux résultats est plus approprié pour ce que vous voulez faire ;-).
selon la documentation de std
SciPy, il a un paramètre appelé ddof
:
ddof: int, en option
Signifie Delta degrés de liberté. Le diviseur utilisé dans les calculs est n-ddof, où n représente le nombre d'éléments. Par défaut ddof est zéro.
Dans numpy, ddof
est zéro par défaut alors que dans MATLAB est un. Donc, je pense que cela pourrait résoudre le problème:
std(Z,ddof=1)