Как подобрать функцию с фиксированным параметром? - PullRequest
1 голос
/ 14 февраля 2012

У меня есть начальные параметры для lsqcurvefit, как

a0 = [value1, value2, value3];

, а затем

curvefitoptions = optimset('Display','final','MaxFunEvals',10000,'MaxIter',5000);
[a] = lsqcurvefit(@myfun,a0,x,y,lb,ub,curvefitoptions);

Я хочу иметь возможность исправить любой из начальных параметров, например. Я фиксирую a0 (1) и a0 (3) при заданном значении и оптимизирую только a0 (2). Как это сделать? Я пытался исправить это в UB и LB, но те же значения не допускаются. Конечно, я могу добавить немного для ub, но это не очень хороший способ сделать это:)

Есть предложения? Спасибо!

Ответы [ 2 ]

3 голосов
/ 14 февраля 2012

Вы можете создать анонимную функцию, которая фиксирует значение первого и третьего элементов.Вам также нужно настроить начальные точки (2-й аргумент) и верхнюю и нижнюю границы так, чтобы они применялись только ко 2-му элементу, например,

a = lsqcurvefit( @(x, xdata) myfun([a0(1); x; a0(3)], xdata), a0(2), x, y, ...
        lb(2), ub(2), curvefitoptions );

Вы можете легко изменить это, чтобы исправить 2-ю и 3-юэлементы, например,

a = lsqcurvefit( @(x, xdata) myfun([x; a0(2); a0(3)], xdata), a0(1), x, y, ...
        lb(1), ub(1), curvefitoptions );

Или исправить только 2-й элемент

a = lsqcurvefit( @(x, xdata) myfun([x(1); a0(2); x(2)], xdata), a0([1,3]), x, y, ...
        lb([1,3]), ub([1,3]), curvefitoptions );

Чтобы сделать это в общем, начните с определения следующей (или аналогичной) функции

function a = interlace( a, x, fix )
a(~fix) = x;
end

Затем вы можете заменить код, подобный [a0(1); x; a0(3)] в приведенных выше примерах, на вызов interlace().Например,

fix = [1; 0; 1];
a_free = lsqcurvefit( @(x, xdata) myfun( interlace( a0, x, fix ), xdata), ...
    a0(~fix), x, y, lb(~fix), ub(~fix), curvefitoptions );
a = interlace( a0, a_free, fix );

Мое тестирование этого ограничено следующим кодом:

%% A function
myfun = @(x, xdata) x(1) + x(2)*xdata + x(3)./xdata;

%% Some Data
x = [0.036;0.14;0.42;0.49;0.66;0.68;0.76;0.79;0.8;0.85;0.92;0.93;0.96];
y = [0.83;1;0.66;0.53;0.58;0.6;0.64;0.62;0.62;0.55;0.41;0.39;0.33];

%% Initial conditions
a0 = [1; 2; 3];

%% Bounds
lb = [-1; -2; -3];
ub = [0.1; 0.2; 0.3];

%% Fitting options
curvefitoptions = optimset( 'Display', 'iter' );

%% Fit all three parameters
a = lsqcurvefit( myfun, a0, x, y, lb, ub, curvefitoptions )

%% Fix some parameters
fix = [1; 0; 1];

a_free = lsqcurvefit( @(x, xdata) myfun( interlace( a0, x, fix ), xdata), ...
    a0(~fix), x, y, lb(~fix), ub(~fix), curvefitoptions );
a = interlace( a0, a_free, fix );
2 голосов
/ 14 февраля 2012

То, что вы в основном хотите, это версия @myfun, которая фиксирует значения a0(1) и a0(3), что на самом деле означает, что в качестве параметра требуется только value2.

Начните с вашей функциикоторый принимает входной вектор с 3 элементами

function ydata = myfun(x, xdata)
    ...your function which assumes size(x) = [1 3]
end

Определите другую функцию, которая фиксирует первый и третий элементы

function ydata = myfun_fix(value2, xdata)  % value2 should be scalar

    value1_fix = 0; % initialize to your value1
    value3_fix = 0; % initialize to your value3

    x = [value1_fix, value2, value3_fix];

    ydata = myfun(x, xdata);

end

Затем просто передайте эту новую функцию в lsqcurvefit

...initialize curvefitoptions
[a] = lsqcurvefit(@myfun_fix, value2, x, y, lb, ub, curvefitoptions);

Возможно, вы могли бы упростить эту работу, определив value1_fix и value3_fix как глобальные (чтобы вы могли изменить их из основного сценария) вместо «констант» в myfun_fix.

...