Сгенерируйте код для lsqcurvefit или lsqnonlin

Этот пример показывает, как сгенерировать код С для нелинейных методов наименьших квадратов.

Данные и модель для наименьших квадратов

В этом примере вектор xdata представляет 100 точек данных и вектор ydata представляет связанные измерения. Смоделированная связь между xdata и ydata является

ydatai=a1+a2exp(a3xdatai)+εi.

Сгенерируйте данные для задачи.

rng(5489,'twister') % For reproducibility
xdata = -2*log(rand(100,1));
ydata = (ones(100,1) + .1*randn(100,1)) + (3*ones(100,1)+...
    0.5*randn(100,1)).*exp((-(2*ones(100,1)+...
    0.5*randn(100,1))).*xdata);

Код генерирует xdata из 100 независимых выборок экспоненциального распределения со средним 2. Код генерирует ydata из своего определяющего уравнения используя a = [1;3;2], возмущается добавлением нормальных отклонений со стандартными отклонениями [0.1;0.5;0.5].

Решение Генерации Кода для lsqcurvefit

Подход решателя

Цель состоит в том, чтобы найти параметры для модели a^i, i = 1, 2, 3, которые лучше всего соответствуют данным.

Для подгонки параметров к данным используя lsqcurvefitнеобходимо задать функцию аппроксимации. Для lsqcurvefitФункция аппроксимации принимает вектор параметра a и данные xdata и возвращает предсказание отклика, которое должно быть равно ydata без шума и идеальной модели. Определите функцию аппроксимации predicted как анонимная функция.

predicted = @(a,xdata) a(1)*ones(100,1)+a(2)*exp(-a(3)*xdata);

Чтобы соответствовать модели данным, lsqcurvefit нужна начальная оценка a0 параметров.

a0 = [2;2;2];

Звонить lsqcurvefit чтобы найти оптимальные параметры a^i.

[ahat,resnorm,residual,exitflag,output,lambda,jacobian] =...
   lsqcurvefit(predicted,a0,xdata,ydata);

Подход к генерации кода

Чтобы решить ту же проблему с помощью генерации кода, выполните следующие шаги.

  1. Напишите функцию, которая включает все предыдущие шаги: сгенерируйте данные, создайте функцию аппроксимации, создайте начальную точку и вызовите lsqcurvefit.

    function [x,res] = solvelsqcurve
    rng(5489,'twister') % For reproducibility
    xdata = -2*log(rand(100,1));
    ydata = (ones(100,1) + .1*randn(100,1)) + (3*ones(100,1)+...
        0.5*randn(100,1)).*exp((-(2*ones(100,1)+...
        0.5*randn(100,1))).*xdata);
    predicted = @(a,xdata) a(1)*ones(100,1)+a(2)*exp(-a(3)*xdata);
    options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt','Display','off');
    a0 = [2;2;2];
    lb = [];
    ub = [];
    [x,res] = lsqcurvefit(predicted,a0,xdata,ydata,lb,ub,options);
    end
  2. Создайте строение для генерации кода. В этом случае используйте 'mex'.

    cfg = coder.config('mex');
  3. Сгенерируйте код для solvelsqcurve функция.

    codegen -config cfg solvelsqcurve
  4. Протестируйте сгенерированный код, запустив сгенерированный файл с именем solvelsqcurve_mex.mexw64 или аналогичный.

    [x,res] = solvelsqcurve_mex
    x =
    
        1.0169
        3.1444
        2.1596
    
    
    res =
    
        7.4101

Решение Генерации Кода для lsqnonlin

Подход решателя

Цель состоит в том, чтобы найти параметры для модели a^i, i = 1, 2, 3, которые лучше всего соответствуют данным.

Для подгонки параметров к данным используя lsqnonlinнеобходимо задать функцию аппроксимации. Для lsqnonlinФункция аппроксимации принимает вектор параметра a, данные xdataи данные ydata. Функция аппроксимации возвращает различие между предсказанием отклика и данными ydata, который должен равняться 0 без шума и идеальной модели. Определите функцию аппроксимации predicted как анонимная функция.

predicted = @(a)(a(1)*ones(100,1)+a(2)*exp(-a(3)*xdata) - ydata)

Чтобы соответствовать модели данным, lsqnonlin нужна начальная оценка a0 параметров.

a0 = [2;2;2];

Звонить lsqnonlin чтобы найти оптимальные параметры a^i.

[ahat,resnorm,residual,exitflag,output,lambda,jacobian] =...
   lsqnonlin(predicted,a0);

Подход к генерации кода

Чтобы решить ту же проблему с помощью генерации кода, выполните следующие шаги.

  1. Напишите функцию, которая включает все предыдущие шаги: сгенерируйте данные, создайте функцию аппроксимации, создайте начальную точку и вызовите lsqnonlin.

    function [x,res] = solvelsqnon
    rng(5489,'twister') % For reproducibility
    xdata = -2*log(rand(100,1));
    ydata = (ones(100,1) + .1*randn(100,1)) + (3*ones(100,1)+...
        0.5*randn(100,1)).*exp((-(2*ones(100,1)+...
        0.5*randn(100,1))).*xdata);
    predicted = @(a) (a(1)*ones(100,1)+a(2)*exp(-a(3)*xdata) - ydata);
    options = optimoptions('lsqnonlin','Algorithm','levenberg-marquardt','Display','off');
    a0 = [2;2;2];
    lb = [];
    ub = [];
    [x,res] = lsqnonlin(predicted,a0,lb,ub,options);
    end
  2. Создайте строение для генерации кода. В этом случае используйте 'mex'.

    cfg = coder.config('mex');
  3. Сгенерируйте код для solvelsqnon функция.

    codegen -config cfg solvelsqnon
  4. Протестируйте сгенерированный код, запустив сгенерированный файл с именем solvelsqnon_mex.mexw64 или аналогичный.

    [x,res] = solvelsqnon_mex
    x =
    
        1.0169
        3.1444
        2.1596
    
    
    res =
    
        7.4101

    Решение идентично решению, сгенерированному solvelsqcurve_mex потому что решатели имеют одинаковые базовые алгоритмы. Таким образом, вы можете использовать решатель, который вы находите наиболее удобным.

См. также

| | | (MATLAB CODER)

Похожие темы