Как подогнать синусоиду к данным с помощью pylab и numpy?
Я пытаюсь показать, что экономики следуют относительно синусоидальному паттерну роста. Я разрабатываю симуляцию на Python, чтобы продемонстрировать, что даже при наличии некоторой степени случайности мы можем получить результаты, близкие к синусоиде.
Я доволен данными, которые я получаю, но теперь хотел бы найти способ построить синусоидальную кривую, которая будет достаточно точно соответствовать этим данным. Я знаю, что можно использовать полиномиальную аппроксимацию, но возможно ли провести синусоидальную аппроксимацию?
2 ответ(ов)
Функция 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
мы подгоняем функцию к данным и визуализируем результат, что позволяет увидеть, насколько хорошо наша модель описывает данные.
Если вы уже знаете частоту, вы можете выполнить линейную регрессию, которая будет вычислительно более эффективной, чем нелинейные методы подгонки. Как указывает @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]
Таким образом, вы получите параметры модели, которые сможете использовать для дальнейшего анализа или предсказаний.
Почему не работает plt.savefig?
Построение гистограммы на логарифмической шкале с помощью Matplotlib
Цветовой график 2D массива в matplotlib
Как извлечь частоту, связанную с FFT значениями в Python?
Преобразование байтового массива обратно в массив numpy