Я столкнулся со странным явлением, когда вычислял скалярное произведение матриц, используя numpy
. Короче говоря, для математически идентичных вычислений numpy
дает мне разные результаты.
Следующий фрагмент кода иллюстрирует проблему:
import numpy as np
np.set_printoptions(precision=10)
np.random.seed(2) # for reproducibility
# create matrices:
A = np.random.rand(300, 1)
A = A/np.sum(A)
A = np.repeat(A, 15, 1)
B = np.random.rand(300, 300)
# convert data to float32:
A_star = A.astype("float32")
B_star = B.astype("float32")
# do the matrix multiplication A'BA and take the diagonal:
res_star = np.diag(A_star.transpose().dot(B_star.dot(A_star)))
# print the results:
print(res_star)
При запуске в python3.5
с numpy1.11.1
на машине с Windows печатается следующий массив:
[0.5000683069 0.5000683069 0.5000683069 0.5000683069 0.5000683069
0.5000683069 0.5000683069 0.5000683069 0.5000683069 0.5000683069
0.5000683069 0.5000683069 0.5000681877 0.5000681877 0.5000683069]
Обратите внимание, что значения в res_star[12:14]
отличаются от других элементов массива - хотя математически можно ожидать, что они совпадают.
Мои собственные исследования этих различий не были особенно успешными, но, думаю, я немного их сузил:
- с dtype
float64
значения в полученном массиве идентичны
- в случае значений
float32
различия в значениях обычно начинаются только с 7-го знака после запятой (области, где заканчивается точность float32
)
Тем не менее, для меня эти выводы не могут реально объяснить различия в массиве, поскольку происходит одна и та же математическая операция (они действительно объясняют различия в значениях, если бы я вычислял те же точечные произведения на тех же матрицах с dtype float64
). Кроме того, для разных начальных чисел и размеров матрицы результирующие значения могут фактически совпадать, поэтому это поведение не соответствует.
- на машине UNIX приведенный выше фрагмент кода возвращает идентичные цифры (по крайней мере, в этой конкретной конфигурации)
Сейчас
1) что вызывает такое поведение и
2) как я могу обеспечить идентичные результаты в массиве, не меняя dtype на float64
?