0

Как подогнать синусоиду к данным с помощью pylab и numpy?

16

Я пытаюсь показать, что экономики следуют относительно синусоидальному паттерну роста. Я разрабатываю симуляцию на Python, чтобы продемонстрировать, что даже при наличии некоторой степени случайности мы можем получить результаты, близкие к синусоиде.

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

2 ответ(ов)

0

Функция curve_fit действительно более удобна для пользователей. Вот пример использования этой функции:

import numpy as np
from scipy.optimize import curve_fit
import pylab as plt

N = 1000  # количество точек данных
t = np.linspace(0, 4 * np.pi, N)
data = 3.0 * np.sin(t + 0.001) + 0.5 + np.random.randn(N)  # создаем искусственные данные с шумом

# начальные предположения о параметрах
guess_freq = 1
guess_amplitude = 3 * np.std(data) / (2 ** 0.5)
guess_phase = 0
guess_offset = np.mean(data)

p0 = [guess_freq, guess_amplitude, guess_phase, guess_offset]

# создаем функцию, которую хотим апроксимировать
def my_sin(x, freq, amplitude, phase, offset):
    return np.sin(x * freq + phase) * amplitude + offset

# выполняем подгонку
fit = curve_fit(my_sin, t, data, p0=p0)

# используем для построения графика нашего первого предположения. Это может быть достаточно хорошо для вас
data_first_guess = my_sin(t, *p0)

# воссоздаем подогнанную кривую, используя оптимизированные параметры
data_fit = my_sin(t, *fit[0])

plt.plot(data, '.')
plt.plot(data_fit, label='после подгонки')
plt.plot(data_first_guess, label='первое предположение')
plt.legend()
plt.show()

В этом примере сначала мы создаем шумные данные с синусоидальной зависимостью, затем определяем начальные предположения для частоты, амплитуды, фазы и смещения. С помощью функции curve_fit мы подгоняем функцию к данным и визуализируем результат, что позволяет увидеть, насколько хорошо наша модель описывает данные.

0

Если вы уже знаете частоту, вы можете выполнить линейную регрессию, которая будет вычислительно более эффективной, чем нелинейные методы подгонки. Как указывает @JJacquelin, начальные предположения не требуются.

Явно, вы будете подгонять y=a+b*sin(x)+c*cos(x) к вашим данным. Обратите внимание, что это эквивалентно выражению A*sin(x+phi), благодаря тригонометрическим идентичностям. Однако представлено это в виде, который линеен по параметрам подгонки (хотя не по x и y). Таким образом, мы можем использовать линейную регрессию в Python.

Просто представьте, что x1 = sin(x) и x2 = cos(x) — ваши входные данные, и примените линейную функцию подгонки к уравнению y = a + b*x1 + c*x2.

Для этого используйте следующий код:

from sklearn.linear_model import LinearRegression
import numpy as np

reg = LinearRegression()

x = # ваш список значений x
y = # ваш список значений y
X = np.column_stack((np.sin(x), np.cos(x)))

reg.fit(X, y)

Вы можете получить параметры подгонки с помощью:

a = reg.intercept_
b = reg.coef_[0]
c = reg.coef_[1]

Таким образом, вы получите параметры модели, которые сможете использовать для дальнейшего анализа или предсказаний.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь