Почему numpy std () дает другой результат для matlab std ()?

87

Я пытаюсь преобразовать код Matlab в numpy и выяснил, что numpy имеет другой результат с функцией std.

в Matlab

std([1,3,4,6])
ans =  2.0817

в тупике

np.std([1,3,4,6])
1.8027756377319946

Это нормально? И как мне с этим справиться?

Густавганы
источник

Ответы:

145

Функция NumPy np.stdпринимает необязательный параметр ddof: «Дельта степеней свободы». По умолчанию это 0. Установите его, чтобы 1получить результат MATLAB:

>>> np.std([1,3,4,6], ddof=1)
2.0816659994661326

Чтобы добавить немного больше контекста, при вычислении дисперсии (стандартное отклонение которой представляет собой квадратный корень) мы обычно делим на количество имеющихся у нас значений.

Но если мы выберем случайную выборку Nэлементов из большего распределения и вычислим дисперсию, деление на Nможет привести к занижению фактической дисперсии. Чтобы исправить это, мы можем уменьшить число, на которое мы делим ( степени свободы ), до числа меньше N(обычно N-1). ddofПараметр позволяет изменить делитель на величину мы указываем.

Если не указано иное, NumPy вычислит смещенную оценку для дисперсии ( ddof=0, деления на N). Это то, что вам нужно, если вы работаете со всем распределением (а не с подмножеством значений, которые были случайно выбраны из более крупного распределения). Если ddofуказан параметр, NumPy N - ddofвместо этого делит на .

Поведение MATLAB по умолчанию std- исправить смещение для дисперсии выборки путем деления на N-1. Это избавляет от некоторой (но, вероятно, не всей) систематической ошибки стандартного отклонения. Вероятно, это именно то, что вам нужно, если вы используете функцию для случайной выборки из большего распределения.

Хороший ответ @hbaderts дает дополнительные математические подробности.

Алекс Райли
источник
4
Я добавлю, что в Matlab std([1 3 4 6],1)это эквивалентно NumPy по умолчанию np.std([1,3,4,6]). Все это довольно четко объяснено в документации для Matlab и NumPy, поэтому я настоятельно рекомендую OP обязательно прочитать их в будущем.
Horchler
В какой-то момент этот стандарт изменился: np.std () = np.std (ddof = 1), хотя в документации сказано, что np.std () по умолчанию должен быть ddof = 0 ...
ColinMac,
61

Стандартное отклонение - это квадратный корень из дисперсии. Дисперсия случайной величины Xопределяется как

определение дисперсии

Таким образом, оценка дисперсии будет

предвзятый оценщик

где выборочное среднееобозначает выборочное среднее. Для случайно выбранных xiзначений можно показать, что эта оценка не сходится к реальной дисперсии, а к

объективный оценщик

Если вы выбираете выборки случайным образом и оцениваете среднее значение выборки и дисперсию, вам придется использовать скорректированный (несмещенный) оценщик.

объективный оценщик

который будет сходиться к сигма в квадрате. Поправочный член п-1также называется поправкой Бесселя.

Теперь по умолчанию MATLABs stdвычисляет несмещенную оценку с поправочным членом n-1. NumPy однако (как @ajcr объяснено) вычисляет смещенную оценщик без какого - либо поправочного члена по умолчанию. Параметр ddofпозволяет установить любой срок коррекции n-ddof. Установив его на 1, вы получите тот же результат, что и в MATLAB.

Точно так же MATLAB позволяет добавить второй параметр w, который определяет «схему взвешивания». Значение по умолчанию, w=0приводит к поправочному члену n-1(несмещенная оценка), в то время как для w=1, только n используется в качестве поправочного члена (смещенная оценка).

Hbaderts
источник
2
В формуле скорректированной оценки фактор n (в сумме) не должен присутствовать.
Frunobulax
3
Интуиция, лежащая в основе термина n-1 в дисперсии: вы уже использовали свои выборки для оценки среднего, которое вы будете использовать для аппроксимации дисперсии. Это вводит корреляцию, и поэтому ddof должен быть 1.
Маттиас
@Frunobulax Я исправил опечатку для потомков. В исходном уравнении произошло то, что верхний предел суммы не отображался должным образом. Вместо того, чтобы nидти вверху обозначения суммирования, он помещался внутри суммы.
Rayryeng
4

Для людей, которые не разбираются в статистике, упрощенное руководство:

  • Включите, ddof=1если вы рассчитываете np.std()для выборки, взятой из вашего полного набора данных.

  • Убедитесь ddof=0, что вы рассчитываете np.std()для всего населения

DDOF включен для выборок, чтобы уравновесить смещение, которое может возникнуть в числах.

MJM
источник