Почему оптимизированная подгонка кривой в scipy создает прямую линию для этой нелинейной модели? - PullRequest
0 голосов
/ 17 ноября 2018

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

import numpy as np
import scipy.optimize as optimize
import matplotlib.pyplot as plt

x = np.array([367.18,411.42,443.76,565.22,689.31,778.94,867.38,963.98,1085.79,1112.01,1212.47,1299.21,1408.08,1458.8,1528.76])
y = np.array([17.21,13.38,9.41,11.40,6.40,6.62,6.11,5.50,5.03,4.52,2.34,3.62,3.84,5.97,1.97])

def f(a,n,x1):
    return (a*np.power(x1,-n));

popt, pcov = optimize.curve_fit(f,x,y, diag=(1./x.mean(),1./y.mean()))
x1 = np.linspace(0,1700,num =1700)
plt.plot(x1, f(x1, *popt))
plt.plot(x,y,'ro')
plt.show()
print(popt, pcov)

Результат таков: Участок

Ответы [ 3 ]

0 голосов
/ 17 ноября 2018

Аргументы для функции f неверны. Согласно документации curve_fit,

Функция модели, f (x,…). Он должен принимать независимую переменную в качестве первого аргумента, а параметры - в качестве отдельных оставшихся аргументов.

Так что вам просто нужно изменить порядок аргументов на f, и сначала поставить x1:

def f(x1, a,n):
    return (a*np.power(x1,-n))

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

x1 = np.linspace(min(x),max(x),num =1700)

и тогда вы получите фигуру:

enter image description here

0 голосов
/ 18 ноября 2018

Я не могу разместить изображение в комментарии, поэтому разместите его здесь. Я обнаружил, что смещение значений X дало мне лучшее соответствие с данными, используя уравнение "y = a * pow ((xb), c)" с коэффициентами a = 2.2685718105301993E + 02, b = 2.7711446388529180E + 02 и c = -5,7863164386558297E-01 с R-квадратом = 0,895 и RMSE = 1,33 power shifted

0 голосов
/ 17 ноября 2018

При запуске строки

plt.plot(x1, f(x1, *popt))

вы передаете x1 в качестве первого параметра в функцию f. Первый параметр вашей функции f - это.

def f(a,n,x1):
    return (a*no.power(x1,-n))

Даже если вы вызываете свой первый параметр x1, функция заботится о порядке передачи переменных, а не об именах переменных. Таким образом, поскольку вы определили, что f принимает три аргумента, a, n и x1, при передаче x1 переменная x1 обрабатывается как a.

Переупорядочение определения функции, чтобы x1 был первым параметром, должно это исправить.

import numpy as np
import scipy.optimize as optimize
import matplotlib.pyplot as plt

x = np.array([367.18,411.42,443.76,565.22,689.31,778.94,867.38,963.98,1085.79,1112.01,1212.47,1299.21,1408.08,1458.8,1528.76])
y = np.array([17.21,13.38,9.41,11.40,6.40,6.62,6.11,5.50,5.03,4.52,2.34,3.62,3.84,5.97,1.97])

def f(x1,a,n):
    return (a*np.power(x1,-n));

popt, pcov = optimize.curve_fit(f,x,y, diag=(1./x.mean(),1./y.mean()))
x1 = np.linspace(0,1700,num =1700)
plt.plot(x1, f(x1, *popt))
plt.plot(x,y,'ro')
plt.show()
print(popt, pcov)
...