2016-04-09 1 views
6

J'ai un tableau d'horodatage, croissant pour chaque ligne de la 2ème colonne de la matrice X. Je calcule la valeur moyenne des horodatages et elle est supérieure à la valeur max. J'utilise un memmap numpy pour le stockage. Pourquoi cela arrive-t-il?numpy signifie est plus grand que max pour memmap

>>> self.X[:,1] 
memmap([ 1.45160858e+09, 1.45160858e+09, 1.45160858e+09, ..., 
    1.45997146e+09, 1.45997683e+09, 1.45997939e+09], dtype=float32) 
>>> np.mean(self.X[:,1]) 
1.4642646e+09 
>>> np.max(self.X[:,1]) 
memmap(1459979392.0, dtype=float32) 
>>> np.average(self.X[:,1]) 
1.4642646e+09 
>>> self.X[:,1].shape 
(873608,) 
>>> np.sum(self.X[:,1]) 
memmap(1279193195216896.0, dtype=float32) 
>>> np.sum(self.X[:,1])/self.X[:,1].shape[0] 
memmap(1464264515.9120522) 

EDIT: Je ai téléchargé le fichier memmap ici. http://www.filedropper.com/x_2 Voici comment je le charge.

filepath = ... 
shape = (875422, 23) 
X = np.memmap(filepath, dtype="float32", mode="r", shape=shape) 

# I preprocess X by removing rows with all 0s 
# note this step doesn't affect the problem 
to_remove = np.where(np.all(X == 0, axis=1))[0] 
X = np.delete(X, to_remove, axis=0) 
+0

Est-ce que le changement de comportement si vous testez avec 'np.array (self.X)' au lieu de 'self.X' ou' np.array (self.X [:, 1]) 'la place de 'self.X [:, 1]'? – user2357112

+0

@ user2357112 non, il renvoie toujours la mauvaise moyenne – siamii

+0

@siamii: C'est un problème d'accumulateur. Vous devriez utiliser des accumulateurs float64 pour de tels tableaux. Vérifiez la réponse pour plus de détails. – Vasanth

Répondre

6

Ceci n'est pas un problème de type numpy ou memmap. Le problème est avec virgule flottante, float32 pour être précis. Vous pouvez voir la même erreur se produire dans d'autres langages comme C++.

L'accumulateur float32 utilisé devient imprécis à mesure que de plus en plus de numéros y sont ajoutés.

In [26]: a = np.ones((1024,1024), dtype=np.float32)*4567 

In [27]: a.min() 
Out[27]: 4567.0 

In [28]: a.max() 
Out[28]: 4567.0 

In [29]: a.mean() 
Out[29]: 4596.5264 

Cela ne se produira pas dans le type np.float64 (donne un peu plus de répit).

In [30]: a = np.ones((1024,1024), dtype=np.float64)*4567 

In [31]: a.min() 
Out[31]: 4567.0 

In [32]: a.mean() 
Out[32]: 4567.0 

Vous pouvez faire mean() utiliser un tampon float64 en spécifiant explicitement.

In [12]: a = np.ones((1024,1024), dtype=np.float32)*4567 

In [13]: a.mean(dtype=np.float64) 
Out[13]: 4567.0 
+0

Est-ce que la spécification de dtype in mean ne fait qu'allouer 1 (ou O (1)) float64 en mémoire, ou est-ce qu'il lance le tableau entier? Je suppose que le premier, mais juste curieux. – Paul

+0

Il s'agit simplement du type de données de l'accumulateur utilisé pour le calcul. N'alloue pas un nouveau tableau 'float64'. – Vasanth

+0

@Vasanth pouvez-vous donner pour une réponse détaillée quant à pourquoi cela se produit? –