Среднее значение numpy больше максимального для memmap

У меня есть массив временных меток, увеличивающийся для каждой строки во 2-м столбце матрицы X. Я вычисляю среднее значение временных меток, и оно больше максимального значения. Я использую numpy 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)

РЕДАКТИРОВАТЬ: я загрузил файл memmap здесь. http://www.filedropper.com/x_2 Вот как я его загружаю.

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)

person siamii    schedule 09.04.2016    source источник
comment
Изменится ли поведение, если вы протестируете его с помощью np.array(self.X) вместо self.X или np.array(self.X[:, 1]) вместо self.X[:, 1]?   -  person user2357112 supports Monica    schedule 10.04.2016
comment
@user2357112 user2357112 нет, все равно возвращает неправильное среднее   -  person siamii    schedule 10.04.2016
comment
@siamii: это проблема с аккумулятором. Вы должны использовать аккумуляторы float64 для таких больших массивов. Проверьте ответ для более подробной информации.   -  person Vasanth    schedule 10.04.2016


Ответы (1)


Это не проблема numpy или memmap. Проблема связана с плавающей запятой, float32, если быть точным. Вы можете увидеть ту же ошибку, возникающую в других языках, таких как C++.

Используемый аккумулятор float32 становится неточным по мере того, как к нему добавляется все больше и больше чисел.

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

Этого не произойдет в типе np.float64 (дает больше передышки).

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

Вы можете заставить mean() использовать буфер float64, указав его явно.

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

In [13]: a.mean(dtype=np.float64)
Out[13]: 4567.0
person Vasanth    schedule 09.04.2016
comment
Означает ли указание dtype в памяти только выделение 1 (или O (1)) float64 или весь массив? Я бы предположил первое, но просто любопытно. - person Paul; 10.04.2016
comment
Это просто тип данных аккумулятора, используемого для вычислений. Не выделяет новый массив float64. - person Vasanth; 10.04.2016
comment
@Vasanth, можете ли вы дать подробный ответ, почему это происходит? - person Jeru Luke; 29.12.2016