Могу ли я использовать привязку scipy.curve в python, когда один из установленных параметров изменяет значения массива ввода xdata?
Это мой первый вопрос, и я постараюсь сделать это настолько ясным, насколько могу, но не стесняюсь задавать вопросы.
Я пытаюсь подгонять модель к кривой, используя метод scipy.curve_fit, как показано ниже:
import numpy as np import matplotlib.pyplot as pyplot import scipy from scipy.optimize import curve_fit def func2(x,EM): return (((4.0*EM*(np.sqrt(8*10**-9)))/(3.0*(1.0-(0.5**2))*8*10**-9))*(((((x))*1*10**-9)**((3.0/2.0))))) ydata=[-0.003428768, -0.009050058, -0.0037997673999999996, -0.0003833233, -0.007557649, -0.0034860994, -0.0009856887, -0.0017508664, -0.00036931394999999996, -0.0040713947, -0.005737315000000001, 0.0005120568, -0.007336486, -0.00719302, -0.0039941817, -0.0029785274, -0.0013044578, -0.008190335, -0.00833507, -0.0074282060000000006, -0.009629990000000001, -0.009425125, -0.008662485999999999, -0.0019445216, -0.008331748, -0.009513038, -0.0047609017, -0.004364422, -0.010325097, -0.0036570733, -0.0060091914, -0.005655772, -0.0045517069999999995, -0.00066998035, 0.006374902, 0.006445733, 0.0019101816, 0.010262737999999999, 0.011139007, 0.018161469, 0.016963122, 0.022915895, 0.027177791, 0.028707139, 0.040105638, 0.044088004, 0.041657403, 0.052325636999999994, 0.062399405, 0.07020844, 0.076979915, 0.08888523, 0.099634745, 0.10961602, 0.12188646, 0.13677225, 0.15639512, 0.16833586, 0.18849944000000002, 0.21515548, 0.23989769000000002, 0.26319308, 0.29388397, 0.321042, 0.35637776, 0.38564656999999997, 0.4185209, 0.44986692, 0.48931552999999994, 0.52583893, 0.5626885, 0.6051665, 0.6461075, 0.69644346, 0.7447817, 0.7931281, 0.8381386000000001, 0.8883482, 0.9395609999999999, 0.9853629, 1.0377034, 1.0889026, 1.1334094] xdata=[34.51388, 33.963736999999995, 33.510695, 33.04127, 32.477253, 32.013624, 31.536019999999997, 31.02925, 30.541649999999997, 30.008646, 29.493828, 29.049707, 28.479668, 27.980956, 27.509590000000003, 27.018721, 26.533737, 25.972296, 25.471065, 24.979228000000003, 24.459624, 23.961517, 23.46839, 23.028454, 22.471411, 21.960924, 21.503428000000003, 21.007033, 20.453855, 20.013475, 19.492528, 18.995746999999998, 18.505670000000002, 18.040403, 17.603387, 17.104082, 16.563634, 16.138298000000002, 15.646187, 15.20897, 14.69833, 14.25156, 13.789688, 13.303409, 12.905278, 12.440909, 11.919262, 11.514609, 11.104646, 10.674512, 10.235055, 9.84145, 9.437523, 9.026733, 8.63639, 8.2694065, 7.944733, 7.551445, 7.231599999999999, 6.9697434, 6.690793299999999, 6.3989780000000005, 6.173159, 5.9157856, 5.731453, 5.4929328, 5.2866156, 5.066648000000001, 4.9190496, 4.745381399999999, 4.574569599999999, 4.4540283, 4.3197597000000005, 4.2694026, 4.2012034, 4.133134, 4.035212, 3.9837262, 3.9412007, 3.8503475999999996, 3.8178950000000005, 3.7753053999999997, 3.6728842] dstart=20.0 xdata=np.array(xdata[::-1]) xdata=xdata-dstart xdata=list(xdata) xdata1=[] ydata1=[] for i in range(len(xdata)): if xdata[i]>0: xdata1.append(xdata[i]) ydata1.append(ydata[i]) xdata=np.array(xdata1) ydata=np.array(ydata1) popt, pcov = curve_fit(func2, xdata, ydata) a=popt[0] print "E=", popt[0]/10**6 t=func2(xdata,a) ax=pyplot.figure().add_subplot(1,1,1) ax.plot(xdata,t, color="blue",mew=2.0,label="Hertz Fit") ax.plot(xdata,ydata,ls="",marker="x",color="red",mew=2.0,label="Data") ax.legend(loc=2) pyplot.show()
Значение «dstart» в основном отсекает нижнюю часть кода, который я не хочу укладывать, потому что он отрицательный, а модель не любит отрицательные числа. В настоящее время мне нужно вручную установить «dstart» перед запуском кода, а затем я вижу конечный результат.
Я начал с этой установки в Excel с помощью Solver, чтобы одновременно изменять переменную «EM» и «dstart», вставляя код, который настраивает xdata на «dstart» и отключает отрицательные значения в подходящей функции.
По сути, я хочу:
import numpy as np import matplotlib.pyplot as pyplot import scipy from scipy.optimize import curve_fit def func2(x,EM,dstart): xdata=np.array(x[::-1]) xdata=dstart-xdata xdata=list(xdata) xdata1=[] for i in range(len(xdata)): if xdata[i]>0: xdata1.append(xdata[i]) global xdata2 xdata2=np.array(xdata1) return (((4.0*EM*(np.sqrt(8*10**-9)))/(3.0*(1.0-(0.5**2))*8*10**-9))*(((((xdata2))*1*10**-9)**((3.0/2.0))))) ydata=[-0.003428768, -0.009050058, -0.0037997673999999996, -0.0003833233, -0.007557649, -0.0034860994, -0.0009856887, -0.0017508664, -0.00036931394999999996, -0.0040713947, -0.005737315000000001, 0.0005120568, -0.007336486, -0.00719302, -0.0039941817, -0.0029785274, -0.0013044578, -0.008190335, -0.00833507, -0.0074282060000000006, -0.009629990000000001, -0.009425125, -0.008662485999999999, -0.0019445216, -0.008331748, -0.009513038, -0.0047609017, -0.004364422, -0.010325097, -0.0036570733, -0.0060091914, -0.005655772, -0.0045517069999999995, -0.00066998035, 0.006374902, 0.006445733, 0.0019101816, 0.010262737999999999, 0.011139007, 0.018161469, 0.016963122, 0.022915895, 0.027177791, 0.028707139, 0.040105638, 0.044088004, 0.041657403, 0.052325636999999994, 0.062399405, 0.07020844, 0.076979915, 0.08888523, 0.099634745, 0.10961602, 0.12188646, 0.13677225, 0.15639512, 0.16833586, 0.18849944000000002, 0.21515548, 0.23989769000000002, 0.26319308, 0.29388397, 0.321042, 0.35637776, 0.38564656999999997, 0.4185209, 0.44986692, 0.48931552999999994, 0.52583893, 0.5626885, 0.6051665, 0.6461075, 0.69644346, 0.7447817, 0.7931281, 0.8381386000000001, 0.8883482, 0.9395609999999999, 0.9853629, 1.0377034, 1.0889026, 1.1334094] xdata=[34.51388, 33.963736999999995, 33.510695, 33.04127, 32.477253, 32.013624, 31.536019999999997, 31.02925, 30.541649999999997, 30.008646, 29.493828, 29.049707, 28.479668, 27.980956, 27.509590000000003, 27.018721, 26.533737, 25.972296, 25.471065, 24.979228000000003, 24.459624, 23.961517, 23.46839, 23.028454, 22.471411, 21.960924, 21.503428000000003, 21.007033, 20.453855, 20.013475, 19.492528, 18.995746999999998, 18.505670000000002, 18.040403, 17.603387, 17.104082, 16.563634, 16.138298000000002, 15.646187, 15.20897, 14.69833, 14.25156, 13.789688, 13.303409, 12.905278, 12.440909, 11.919262, 11.514609, 11.104646, 10.674512, 10.235055, 9.84145, 9.437523, 9.026733, 8.63639, 8.2694065, 7.944733, 7.551445, 7.231599999999999, 6.9697434, 6.690793299999999, 6.3989780000000005, 6.173159, 5.9157856, 5.731453, 5.4929328, 5.2866156, 5.066648000000001, 4.9190496, 4.745381399999999, 4.574569599999999, 4.4540283, 4.3197597000000005, 4.2694026, 4.2012034, 4.133134, 4.035212, 3.9837262, 3.9412007, 3.8503475999999996, 3.8178950000000005, 3.7753053999999997, 3.6728842] xdata2=list(xdata2) ydata1=[] for i in range(len(xdata2)): if xdata2[i]>0: ydata1.append(ydata[i]) popt, pcov = curve_fit(func2, xdata, ydata)
Но это не работает, поскольку я получаю ошибку значения. ValueError: операнды не могут быть переданы вместе с фигурами (28,) (30,) ». Я думаю, что мне нужно, чтобы curve_fit вводил xdata, настраивал первый догадавшийся «dstart», догадывался EM и проверял соответствие и минимизировал ошибку, попробовал новый «dstart», чтобы настроить xdata, угадать EM и проверить соответствие и свести к минимуму ошибку, так далее и т. д. Поскольку я все еще довольно новичок в Python, я определенно вышел из своего элемента с подходящей кривой, и я бы просто использовал Excel, если бы у меня не было потенциально тысячи кривых для запуска.
Любая помощь будет оценена!
- Как включить ошибки для моих данных в минимизации минимальных квадратов lmfit, и какова эта ошибка для функции conf_interval2d в lmfit?
- Как использовать наименьшие квадраты с весовой матрицей в python?
- Как я могу поместить наименьшие квадраты в python, используя данные, которые являются только верхним пределом?
- Минимальные комплексные номера минимальных квадратов
- пытаясь получить разумные значения от scipy powerlaw
Я разделил бы это на две части: концептуальную и кодирующую
Концептуальное:
Начнем с перефразирования вашего вопроса. В его основе лежит ответ: Да, очевидно. Просто поглотите зависящее от параметра изменение x
в целевой функции. Но это не решит вашу проблему. То, что вам действительно интересно, это то, что нужно делать с параметрами, для которых часть x
не может быть обработана вашей функцией. Для этого нет единого размера.
Вы можете считать такие параметры неприемлемыми, и в этом случае вам придется прибегать к ограниченной оптимизации. В scipy
есть несколько решателей, которые могут это сделать.
Вы можете выбрать удаление сложных точек из набора данных перед установкой.
Вы можете ввести мягкие ограничения и наказывать плохие значения, а не исключать их полностью.
Стиль программирования:
для циклов в числовых программах. На этом сайте есть gazillions сообщений, поэтому я приведу только один пример:
xdata2=list(xdata2) ydata1=[] for i in range(len(xdata2)): if xdata2[i]>0: ydata1.append(ydata[i])
можно записать в одну строку, которая будет выполняться намного быстрее и вернуть array
вместо list
:
ydata1 = ydata[xdata2 > 0]
посмотрите на учебник / документы numpy или найдите этот сайт для «векторизации», если вы хотите изучить эту технику.
Кроме того, никаких жалоб.
Почему ваша вторая программа не работает.
Вы просеиваете и ваши x
и y
, поэтому они должны иметь одинаковую форму. Но затем вы продолжаете использовать старую копию вместо новой y
тогда как используете новый x
. Вот почему формы не совпадают
Btw. то, как вы его настроили (изменить x
в func2
), более или менее реализует стратегию поглощения, о которой я упоминал ранее. Только, поскольку у вас нет доступа к y
вы не можете изменить форму x
.