Невозможно подогнать нелинейную кривую к данным в Matlab
Я пытаюсь согласовать некоторые данные в Matlab с функцией Хилла вида y = r^n/(r^n+K^n). У меня есть данные для r,y, и мне нужно найти K,n.
Я попробовал два разных подхода после прочтения документов - один использует fit
из набора инструментов CurveFitting и других использует lsqcurvefit
из панели инструментов оптимизации. У меня не было никакого успеха ни с одним. Что мне не хватает?
Вот мои xdata и ydata:
xdata = logspace(-2,2,101);
ydata = [0.0981 0.1074 0.1177 0.1289 0.1411 0.1545 0.1692 0.1852 0.2027 ...
0.2219 0.2428 0.2656 0.2905 0.3176 0.3472 0.3795 0.4146 0.4528 ...
0.4944 0.5395 0.5886 0.6418 0.6994 0.7618 0.8293 0.9022 0.9808 ...
1.0655 1.1566 1.2544 1.3592 1.4713 1.5909 1.7183 1.8537 1.9972 ...
2.1490 2.3089 2.4770 2.6532 2.8371 3.0286 3.2272 3.4324 3.6437 ...
3.8603 4.0815 4.3065 4.5344 4.7642 4.9950 5.2258 5.4556 5.6833 ...
5.9082 6.1292 6.3457 6.5567 6.7616 6.9599 7.1511 7.3347 7.5105 ...
7.6783 7.8379 7.9893 8.1324 8.2675 8.3946 8.5139 8.6257 8.7301 ...
8.8276 8.9184 9.0029 9.0812 9.1539 9.2212 9.2834 9.3408 9.3939 ...
9.4427 9.4877 9.5291 9.5672 9.6022 9.6343 9.6638 9.6909 9.7157 ...
9.7384 9.7592 9.7783 9.7957 9.8117 9.8263 9.8397 9.8519 9.8630 ...
9.8732 9.8826];
'Fit' код:
HillEqn = '@(x,xdata)xdata.^x(1)./(xdata.^x(1)+x(2).^x(1))';
startPoints = [1 1];
fit(xdata',ydata',HillEqn,'Start',startPoints)
Сообщение об ошибке:
Error using fittype>iTestCustomModelEvaluation (line 726)
Expression @(x,xdata)xdata.^x(1)./(xdata.^x(1)+x(2).^x(1)) is not a valid MATLAB
expression, has non-scalar coefficients, or cannot be evaluated:
Undefined function 'imag' for input arguments of type 'function_handle'.
Код lsqcurvefit:
fun = @(x,xdata) xdata.^x(1)./(xdata.^x(1)+x(2).^x(1));
x0 = [1,1]; % Initial Parameter Estimates
x = lsqcurvefit(fun,x0,xdata,ydata);
Сообщение об ошибке:
Error using snls (line 47)
Objective function is returning undefined values at initial point. lsqcurvefit cannot
continue.
1 ответ
Во-первых, я думаю, что для начала вам нужно 3 переменные, потому что функция Хилла будет максимум 1, а ваши данные - максимум 10. Поэтому либо нормализуйте свои данные, выполнив ydata=ydata./max(ydata)
Или добавьте третью переменную (что я и сделал для демонстрации). Вот как я это сделал:
startPoints = [1 1 1];
s = fitoptions('Method','NonlinearLeastSquares',... %
'Lower',[0 0 0 ],...
'Upper',[inf inf inf],...
'Startpoint',startPoints);
HillEqn = fittype( 'x.^a1./(x.^a1+a2.^a1)*a3','options',s);
[ffun,gofrr] = fit(xdata(:),ydata(:),HillEqn);
yfit=feval(ffun,xdata(:)); %Fitted function
plot(xdata,ydata,'-bx',xdata,yfit,'-ro');
ffun =
General model:
ffun(x) = x.^a1./(x.^a1+a2.^a1)*a3
Coefficients (with 95% confidence bounds):
a1 = 1.004 (1.004, 1.004)
a2 = 0.9977 (0.9975, 0.9979)
a3 = 9.979 (9.978, 9.979)
Примечание:
В вашем случае вы действительно хотите преобразовать данные, посмотрев на Y=1./ydata
вместо этого, затем подходят, а затем взять другой 1./Y
чтобы получить ответ в предыдущем представлении функции "холма". Это потому, что ваша проблема носит билинейный характер, поэтому, идя 1./ydata
вы получите билинейное отношение, для которого polyfit
из заказа 1 сделаем:
Y=1./ydata;
X = 1./xdata;
p=polyfit(X,Y,1);
plot(X,Y,'-bx',X,polyval(p,X),'-ro')