Подтвердить что ты не робот

Точность, почему 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'.

Почему разница такая огромная? Какой из них более правильный?

4b9b3361

Ответ 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)