Точность, почему Matlab и Python numpy дают разные результаты?
Я знаю о базовых типах данных и что типы float (float, double) не могут точно содержать некоторые числа.
При переносе некоторого кода из Matlab в Python (Numpy) я обнаружил некоторые существенные различия в вычислениях, и я думаю, что он вернется к точности.
Возьмите следующий код, z-нормализуя 500-мерный вектор, только с первыми двумя элементами, имеющими ненулевое значение.
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
Кроме того, форматирование показывает немного больше цифр в Python, существует огромная разница (imho), более 0,02
Оба Python и Matlab используют 64-битный тип данных (afaik). Python использует 'numpy.float64' и Matlab 'double'.
Почему разница такая огромная? Какой из них более правильный?
Ответы
Ответ 1
Возможно, разница связана с вызовами mean
и std
. Сначала сравните их.
Существует несколько определений для std
, некоторые используют корень sqaure
1 / n * sum((xi - mean(x)) ** 2)
другие используют
1 / (n - 1) * sum((xi - mean(x)) ** 2)
вместо.
Из математической точки: эти формулы являются оценками дисперсии нормальной распределенной случайной величины. Распределение имеет два параметра sigma
и mu
. Если вы знаете mu
, то оптимальной оценкой для sigma ** 2
является
1 / n * sum((xi - mu) ** 2)
Если вам нужно оценить mu
из данных с помощью mu = mean(xi)
, оптимальная оценка для sigma**2
равна
1 / (n - 1) * sum((xi- mean(x))**2)
Ответ 2
Чтобы ответить на ваш вопрос, нет, это не проблема точности. Как отмечает @rocksportrocker, есть две популярные оценки стандартного отклонения. MATLAB std
имеет оба варианта, но в качестве стандарта используется другой, чем вы использовали в Python.
Попробуйте std(Z,1)
вместо std(Z)
:
Za = (Z-repmat(mean(Z),500,1)) ./ repmat(std(Z,2),500,1);Za(1)
sprintf('%1.10f', Za(1))
приводит к
Za (1) = 21.1905669677
в MATLAB. Прочтите ответ rockpotrocker о том, какой из двух результатов более подходит для того, что вы хотите сделать, -).
Ответ 3
В соответствии с документацией std
на SciPy у него есть параметр ddof
:
ddof: int, необязательный
Средства Дельта Степени Свободы. Используемый делитель в расчетах N - ddof, где N представляет количество элементов. По умолчанию ddof равен нулю.
В numpy значение ddof
по умолчанию равно нулю, а в MATLAB - одно. Поэтому я думаю, что это может решить проблему:
std(Z,ddof=1)