Как пройти заранее сгенерированных значений в анонимную функцию, чтобы ускорить посадку?


В MATLAB я использую сочетание fit и fittype функция (от подгонки элементов) соответствует сигнал, используя анонимную функцию.

Моя проблема заключается в том, что эта анонимная функция использовать integral функция Матлаб, и это очень много времени. Поэтому я пытаюсь избавиться от этой функции внутри анонимной функции.

Удивительное улучшение будет предварительно вычислить Интеграл и передать его fit функция, но я не знаю как это сделать.

Я пытался определить вектор, который содержит эти интеграционные ценности и передать его fit определив его как 'dependent' или 'problem' переменная в fittype но это не сделать трюк. Я тоже пробовал сцепление координат и в результате этот Интеграл. При выполнении двух вектор-столбец, он пытался вписаться в поверхность (что это не тот случай). При объединении в один вектор-столбец его жалуются на то, что набор данных и системы координат должны быть одинакового размера.

В качестве альтернативы я также попытался с помощью sum и trapz вместо integral но fittype мне сказали, что функция не удовлетворяют критериям анонимную функцию.

Меня хватает идей и на способы задать поиск двигателей для новых идей и будем приветствовать все новые точки зрения относительно того, как решить эту.


Для любознательных здесь народов является оригинальным анонимная функция, которую я использую:

function [ y ] = zeusEquation(varargin)
    psi0=varargin{1};% in radian 
    a1 = varargin{2};% parameter to be fitted
    a2 = varargin{3};%parameter to be fitted
    a3 = varargin{4};% average of background signal/ offset in gray level
    a4 = varargin{5};% slope on the signal background
    a5 = varargin{6};% decentering of the signal (in meter)
    a6 = varargin{7};% width of the signal in radian
    x = varargin{8};%Coordinate system in meter!!!!
    y = zeros(size(x));

    %fundamental bloc equation needed
    sinIntegral = @(t) 2.*sin(t)./(pi.*t);
    u = @(f, e, x) f.*abs(x-e);

    %Actual signal calculation
    for i = 1:max(size(x))
        if u(a6,a5,x(i))~=0
            y(i) = a3...
             +a4.*(x(i)-a5)...
             +(1-integral(sinIntegral,0,u(a6,a5,x(i))))...
             .*(a1.*sign(x(i)-a5).*sin(psi0)-...
             (1-a2).*integral(sinIntegral,0,u(a6,a5,x(i))).*(1-cos(psi0)));
        else
            y(i) = a3+a4.*(x(i)-a5);
        end
    end
end

Примечание: Я задал этот вопрос на mathwork.



121
3
задан 27 февраля 2018 в 10:02 Источник Поделиться
Комментарии
1 ответ

Именованная функция объявлена так:

function out = function_name(in)

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

В анонимной функции определяется как:

function_handle = @(p) p

Здесь function_handle это переменная, которая содержит анонимные функции. В других языках это называется лямбда. Эта лямбда может захватывать переменные из ее окружения:

data = 1:10;
function_handle = @(p) p.*data

function_handle теперь содержит копию data. Изменение data или сняв его после создания анонимной функции не влияет на копию data внутри него.

Самое интересное для вас здесь заключается в том, что именованная функция может также собирать данные. Это справедливо только для вложенных функций (которые мы не упомянули выше). Разница между вложенной функции и функции локального является одним жалкие end заявление, его легко пропустить. Это локальная функция:

function out = main(in)
% code ...
function r = local(p)
% code ...

Это идентично:

function out = main(in)
% code ...
end
function r = local(p)
% code ...
end

В end заявления прекращение function являются необязательными.

Это вложенные функции:

function out = main(in)
% code ...
function r = nested(p)
% code ...
end
end

Здесь end заявления являются обязательными. nested находится внутри main. nested также имеет доступ к переменным, объявленным в главном. Например, nested можете использовать in.

main можно также создать функцию ручки nested и вернуть его. Эта функция так же будет указывать на вложенную функцию, и захватить его окружения. Подобно анонимной функции:

function out = main(in)
data = integral(in,0,1);
out = @r;
function r = nested(p)
r = p .* data;
end
end

Теперь, называя main возвращает дескриптор функции nested, которая захватила data вычисленные в main. Вы можете использовать это, чтобы создать функцию обработки, которые можно передать fit. nested будет вашим zeusEquationи главное просто пакет с предвычисленным Интеграл.

Комментарий код

Есть несколько вещей, чтобы отметить о вашем коде:


  • Вы рассчитываете sin(psi0) и 1-cos(psi0) несколько раз внутри петли. psi0 является постоянным в течение этого цикла, и, следовательно, вы должны вычислить эти значения после выхода из цикла.

  • Вы рассчитываете integral(sinIntegral,0,u(a6,a5,x(i))) дважды для каждого x(i). Это дорогостоящая функция, вы должны вычислить его только один раз и повторно использовать результат.

  • for i = 1:max(size(x)) это длинные руки для for i = 1:length(x). Это работает только правильно, в ваш цикл, если x - это вектор. В этом случае, вы можете использовать numel(x) вместо length(x). numel быстрее.

Эти три вышеперечисленных пунктов приведет к:

sinpsi0 = sin(psi0);
cospsi0_1 = 1-cos(psi0);
for i = 1:numel(x)
if u(a6,a5,x(i))~=0
int = integral(sinIntegral,0,u(a6,a5,x(i)));
y(i) = a3 + a4.*(x(i)-a5) ...
+ (1-int) .* (a1.*sign(x(i)-a5).*sinpsi0 ...
- (1-a2).*int.*cospsi0);
else
y(i) = a3 + a4.*(x(i)-a5);
end
end


  • integral должен быть вызван со скалярными ограничения, но другие компоненты могут быть вычислены векторизированный. Можно было бы вычислить только Интеграл в цикле, а остальные без петли.

    Это приводит к:

    int = zeros(size(x));
    for i = find(u(a6,a5,x)~=0)
    int(i) = integral(sinIntegral,0,u(a6,a5,x(i)));
    end
    y = a3 + a4.*(x-a5) ...
    + (1-int) .* (a1.*sign(x-a5).*sin(psi0) ...
    - (1-a2).*int.*(1-cos(psi0)));

    Это должно быть быстрее, но я его не тестировал. (Я предполагаю a1 и как все скаляры?)


  • Вы определяете свою функциюzeusEquation используя varargin, а затем приступить к распаковке varargin массив ячеек в предположении, что все входные аргументы есть. Это правильно в вашей ситуации конечно, но вы могли бы также сделать:

    function y = zeusEquation(psi0,a1,a2,a3,a4,a5,a6,x)

    Таким образом, если zeusEquation называется меньше (или больше!) аргументов, вы получите бессмысленные сообщения об ошибке, а не "Индекс вне границ" ошибка.


3
ответ дан 27 февраля 2018 в 05:02 Источник Поделиться