Кривая не подходит даже на синусоиде - PullRequest
4 голосов
/ 14 ноября 2011

Я пытаюсь использовать curve_fit для подбора простой синусоидальной волны (даже без шума) в качестве теста, прежде чем перейти к более сложным задачам.К сожалению, это не дает даже отдаленно правильный ответ.Вот мой синтаксис:

x = linspace(0,100,300)
y = sin(1.759*x)
def mysine(x, a):
    return sin(a*x)

popt, pcov = curve_fit(mysine, x, y)
popt
array([ 0.98679056])

И затем, если я попытаюсь сделать первоначальное предположение (скажем, 1,5):

popt, pcov = curve_fit(mysine, x, y, p0=1.5)
popt
array([ 1.49153365])

... что все еще далеко от правильного ответа.

Полагаю, я удивлен тем, что, учитывая, как хорошо сэмплируется функция, подгонка не работает хорошо.

Ответы [ 2 ]

6 голосов
/ 15 ноября 2011

Если вы знаете частоту синусоидальной волны, которую вы пытаетесь подобрать, вы можете использовать линейную регрессию для подгонки синусоидальной волны.Любая синусоида может быть представлена ​​линейной комбинацией функции синуса и косинуса.Вы можете найти коэффициенты для синуса и косинуса, используя линейную регрессию.Хорошая вещь в этом подходе состоит в том, что не требуется первоначальное угадывание, и есть только один ответ, который удовлетворяет формуле регрессии (например, вы не получите ответы, которые являются «неправильными»).

http://exnumerus.blogspot.com/2010/04/how-to-fit-sine-wave-example-in-python.html имеет краткое руководство с примером кода.

6 голосов
/ 14 ноября 2011

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

Даже если вы попытались сделать первоначальное предположение, я бы сказал, что у вас есть дополнительная проблема, связанная с вашей частотой дискретизации и частотой вашей волны. Для получения дополнительной информации, вы можете взглянуть на теорему отсчетов Найквиста-Шеннона в Википедии. Проще говоря, частота вашей волны равна 1.759 / (2 * pi) = 0.28, что оказывается очень близко к частоте дискретизации вашего массива x (~ 0.33). Другая проблема, которая может возникнуть, - это слишком большое количество колебаний, чтобы соответствовать вашей функции.

Чтобы ваш код работал, я бы предложил либо увеличить частоту вашей волны (a> 4 * 0,33), либо увеличить частоту дискретизации и уменьшить длину вашего пространственного вектора x.

Я запустил следующий код и получил результаты, как показано здесь :

# -*- coding: utf-8 -*-
import numpy as np
import pylab as pl
from scipy.optimize import curve_fit

def mysine(x, a):
    return 1. * np.sin(a * x)

a = 1.759 # Wave frequency
x = np.linspace(0, 10, 100) # <== This is what I changed
y = np.sin(a * x) + 0. * np.random.normal(size=len(x))

# Runs curve fitting with initial guess.
popt, pcov = curve_fit(mysine, x, y, p0=[1.5])

# Calculates the fitted curve
yf = mysine(x, *popt)

# Plots results for comparison.
pl.ion()
pl.close('all')
fig = pl.figure()
ax = fig.add_subplot(111)
ax.plot(x, y, '-', c=[0.5, 0.5, 0.5])
ax.plot(x, yf, 'k-', linewidth=2.0)
ax.text(0.97, 0.97, ur'a=%.4f, ã=%.4f' % (a, popt[0]), ha='right', va='top', 
    fontsize=14, transform=ax.transAxes)
fig.savefig('stow_curve_fit.png')
...