Подгонка кривой Левенберга-Марквардта MATLAB

введите здесь описание изображения. Я не знаю, как выбрать lb и ub для lsqcurvefit в MATLAB, а также x0, чтобы подогнать мою функцию к данным, я имею в виду, что у меня есть некоторые выходные данные, но они неверны,

Вот мои данные:

xdata= [22.8700000000000;7.92000000000000;3.45000000000000;1.78000000000000;
        1.57000000000000;6.41000000000000;12.9000000000000;1.82000000000000;
        1.86000000000000;3.71000000000000;12.0900000000000;15.9900000000000;
        18.9600000000000;23.1500000000000;23.4500000000000;24.8200000000000;
        25.0700000000000;13.2800000000000];
ydata= [8.44300000000000;7.92100000000000;7.64600000000000;7.51600000000000;
        7.47100000000000;7.82100000000000;8.03200000000000;7.76200000000000;
        7.77400000000000;7.87800000000000;8.07000000000000;8.26000000000000;
        8.40000000000000;8.52000000000000;8.52000000000000;8.57000000000000;
        8.58000000000000;8.03200000000000];

и тогда у меня будет myfunc в отдельном файле m:

 function F = myfun(x,xdata)
  F=x(1)*(1-x(2)^2)./((1+x(2)^2+2*x(2)*cosd(xdata)).^1.5);

У меня есть x(1) и x(2), неизвестные, которые я люблю оценивать после подгонки к моим данным, и я знаю, что k x(2) не будет отрицательным значением.

Поэтому я установил lsqcurvefit следующим образом:

[x, resnorm]=lsqcurvefit(@myfun,[-0.5:0.5], xdata, ydata, 0, 1.5, options)

И это результат:

x = 1,5000 -0,4945
resnorm = 52,1739

который показывает отрицательное значение для x(2)!

Не могли бы вы мне помочь?

Большое спасибо за ответ на мой вопрос, и теперь, когда команда вычислила x и resnorm, я использую результаты в своей функции, это означает, что я использовал x (1) = 92,8054 x (2) = 0,7427

so;

F=92,8054*(1-(0,7427)^2)./((1-0,7427)^2+2*(0,7427)*cosd(xdata)).^1,5;

теперь у меня есть вектор F , когда я рисую свои данные и результаты, plot(xdata, ydata, 'o', xdata, F, '*')

Я не понимаю, почему диапазон оси y такой разный! может быть, мне нужно добавить x (3) к моей функции.

Я прикрепил рисунок.введите здесь описание изображения

введите здесь описание изображения

введите здесь описание изображения


person user1331843    schedule 30.07.2012    source источник
comment
Вы уверены, что это правильная модель для ваших данных? Построение графика зависимости xdata от ydata не сильно отличается от прямой. Если полностью исключить lb и ub и попробовать несколько сотен начальных значений, они последовательно сходятся к чему-то, что мало похоже на данные... Кроме того, косинусная часть выглядит как что-то полученное из закона косинусов, но затем перепутанное. ...вы действительно уверены, что это правильная формула?   -  person Rody Oldenhuis    schedule 30.07.2012
comment
Я почти уверен в этой функции, мой вопрос заключается в том, что, например, в данных наблюдения диапазон вариаций составляет от 7,4 до 8,8, но когда я использую результат в своей функции, диапазон составляет от 21,5 до 25, как вы можете видеть выше в графики. и извините, я не получил ваш комментарий, вы имеете в виду, что я должен изменить значение x0, которое уже равно [-0,5:0,5]?   -  person user1331843    schedule 30.07.2012
comment
Ваша ошибка в том, что вы использовали 1-0,7427 для вычисления F вместо 1+0,7427. то есть попробуйте F=92,8054*(1-(0,7427)^2)./((1+0,7427)^2+2*(0,7427)*cosd(xdata)).^1,5;   -  person Dan    schedule 30.07.2012
comment
вау, мне очень жаль, какая глупая ошибка, и большое спасибо.   -  person user1331843    schedule 30.07.2012


Ответы (3)


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

Так, например, если вы хотите, чтобы x (1) был неограниченным, а x (2) находился в диапазоне от 0 до 1,5, попробуйте

[x, resnorm]=lsqcurvefit(@myfun,[-0.5:0.5], xdata, ydata, [-inf, 0], [inf, 1.5], options)

Чтобы вычислить F, используйте уже созданную вами целевую функцию:

F = myfun(x, xdata), а затем постройте его так, как у вас уже есть. В вашем комментарии ниже вы переключили + на - , поэтому ваши графики не выравниваются.

person Dan    schedule 30.07.2012
comment
Я использую результаты в своей функции, это означает, что я использовал x (1) = 92,8054 x (2) = 0,7427, поэтому; F=92,8054*(1-(0,7427)^2)./((1-0,7427)^2+2*(0,7427)*cosd(xdata)).^1,5; теперь у меня есть вектор F , когда я рисую свои данные и результаты, график (xdata, ydata, 'o', xdata, F, '*') я не понимаю, почему диапазон оси y настолько отличается! может быть, мне нужно добавить x (3) к моей функции - person user1331843; 30.07.2012
comment
Смотрите мое редактирование, это потому, что ваша формула выше отличается от вашей целевой функции. Вы заменили + на - - person Dan; 30.07.2012
comment
да, вы правы, спасибо, и если я хочу использовать больше параметров, как мне написать для них границы, я имею в виду, если я каким-то образом увеличу x (3) и x (4), так это правильно? например [-Inf -Inf 0 -Inf] или между ними нужна запятая? - person user1331843; 31.07.2012
comment
да вы правы. Нижняя граница для x(1), x(2) или x(4) не будет установлена, но принудительно x(3) будет положительным (или нулем! границы включительно). В Matlab [a b c] совпадает с [a, b, c] запятой или пробелом, означающим конкатенацию столбцов, где точка с запятой будет конкатенацией строк. - person Dan; 31.07.2012

Параметры lb и ub — это нижняя и верхняя границы вашего вывода, т. е. ваше оптимизированное значение xopt будет удовлетворять lb <= xopt <= ub.

Как вы уже знаете, x(2) не может быть отрицательным, у вас уже есть одна нижняя граница, равная нулю, то есть lb(2) = 0. Теперь вам нужно только определить нижнюю границу для x(1) и верхнюю границу для x(1) и x(2).

Следующий код будет ограничивать x(1) to [-inf, 1e3] и x(2) to [0, 1e3]:

lb = [-inf, 0];
ub = [1e3, 1e3];
[x, resnorm] = lsqcurvefit(@myfun,[-0.5:0.5], xdata, ydata, 0, 1.5, ...
                           lb, ub, options)

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

[x, resnorm] = lsqcurvefit(@myfun,[-0.5:0.5], xdata, ydata, 0, 1.5, ...
                           [], [], options)

Возможно, у нас разные версии Matlab.

person Mehrwolf    schedule 30.07.2012

Почему бы не использовать простое решение наименьших квадратов:

in = [ones(size(xdata, 1), 1), xdata];
w = in \ ydata;
ydata_fit = in * w;

Результат:

введите здесь описание изображения

>> disp(w)
    7.5744
    0.0401
person Serg    schedule 30.07.2012
comment
Невозможно указать границы для переменной оптимизации, используя простой метод наименьших квадратов. - person Mehrwolf; 31.07.2012