scipy.stats.chisquare не дает ожидаемых результатов от входных данных - PullRequest
1 голос
/ 10 апреля 2019

У меня есть некоторые данные, к которым я хочу применить подгонку, а затем выполнить тест хи-квадрат, чтобы получить правильную подгонку. Очевидно, что применение, которое я применяю, не очень хорошо вписывается в данные (что само по себе не является проблемой, я не обязательно ожидаю этого), но значения, которые возвращает scipy.stats.chisquare, могут подсказать почти идеальная посадка, что явно неправильно.

На данный момент я определил функцию, описывающую подгонку, которую я применяю (синусоидальную подгонку), затем использовал scipy.optimize.curve_fit для подгонки этой функции к моим данным, получая параметры подгонки из popt, затем используя их в ранее определенной функции для генерации подгонки.

Затем я беру измеренные данные и подогнанные данные и помещаю их в scipy.stats.chisquare в попытке получить подгонку, но при этом возвращается значение p, равное 1,0, что не может быть правильным. Я предполагаю, что есть некоторая проблема с использованием значений, сгенерированных scipy.optimize.curve_fit в scipy.stats.chisquare, но если это так, я не понимаю, почему это проблема или как обойти ее.

У меня есть данные измерений в двух списках, которые я называю "время" и "скорость" ниже

import numpy as np
import math
%matplotlib inline
import matplotlib.pyplot as plt
from statistics import stdev
import scipy


time =[309.6666666666667, 326.3333333333333, 334.6666666666667, 399.9166666666667, 416.5833333333333, 433.25, 449.91666666666663, 466.58333333333337, 483.25, 499.91666666666663,]

rate = [0.298168, 0.29317, 0.306496, 0.249861, 0.241532, 0.241532, 0.206552, 0.249861, 0.253193, 0.239867]

def oscillation(t,A,C):
    return(A*np.cos((2*np.pi*(t-x0))/(t0))+C)
t0 = 365.25
A = 0.35/2
x0 = 152.5
C = 0.475

popt, pcov = curve_fit(oscillation, time, rate, p0=[A,C])


rate_fit = []

for t in time:
    r = oscillation(t, popt[0],popt[1])
    rate_fit.append(r)

print(scipy.stats.chisquare(rate, f_exp=rate_fit))

plt.plot(time,rate, '.')
plt.plot(time,rate_fit,'--')

Вывод вышеупомянутого является подбором, который выглядит как наилучшее соответствие данным при построении графика, но явно не является идеальным подбором, делая другой вывод со значением p 0,999999999999458533, что явно неверно

1 Ответ

0 голосов
/ 12 апреля 2019

Вы подходите только для двух параметров, A и C, тем самым форсируя фазу и период.
Если вы также подходите для фазы и периода, вы получите гораздо лучшую подгонку:

enter image description here

Также в этом случае моё значение p равно 1,0.

Причина, по которой ваше значение p равно 1,0, когда x0 и t0 являются фиксированными, заключается в том, что ваш результат наилучшим образом подходит для с этими значениями для x0 и t0. Форсирование этих значений, скорее всего, приведет к худшему совпадению. Для сравнения, с x0 и t0 бесплатно я получаю

A = -3.45840427e-02
C = 2.65142203e-01
x0 = 1.88838771e+02
t0 = 2.61112538e+02

Сравните это с t0 = 365.25 и x0 = 152.5.

Конечно, есть (физические) причины, которые вы хотите исправить, например, t0 до года, но в таком случае вам следует меньше беспокоиться о том, что сюжет выглядит плохо; Ваше значение p по-прежнему учитывает это.

Более вероятная причина, однако, в том, что вы также забыли параметр ddof в scipy.stats.chisquare. По умолчанию это ddof=0, это не то, что у вас есть: в вашем случае это len(rate) - 2, в моем случае это будет len(rate) - 4.
Для вашей подгонки (t0 и x0 фиксированный) это приводит к p = 0.902 Если все параметры свободны, это приводит к 0,999887 (т. Е. Снова к 1).


Бонус: вывод, когда я фиксирую период от t0 до 365.25:

A = -4.05218922e-02
C = 2.74772524e-01
x0 = 8.69008279e+01

p = 0.997

и построенная посадка:

enter image description here

...