Найти градиент от сложной целевой функции в Matlab - PullRequest
0 голосов
/ 14 мая 2018

У меня проблема с вычислением символьного градиента из следующей целевой функции:

syms x
gradient(@objfun,x)


function f = objfun(x)

N = 4;
I = 3;
fr = 5;

f_temp = 0;
for n=1:N
    sum2 = 0;
    for i=1:I
        sum1 = fr*(1 - x(n+((i-1)*N)));
        sum2 = sum2 + sum1;  
    end
    f_temp = f_temp + sum2;
end

f = 100*f_temp;                
end

Однако эта ошибка появляется "Только анонимные функции и функции без аргументов могут быть преобразованы в sym". Как сделать так, чтобы этот код работал?

1 Ответ

0 голосов
/ 14 мая 2018

Функция gradient принимает символическое выражение в качестве ввода, а не указатель на функцию.MATLAB жалуется, потому что пытается преобразовать указатель вашей функции в символическое выражение и не может.

В этом случае работает следующее

N = 4; I = 3;
x = sym('x',[N,I]);     % Define a matrix of symbolic variables
f = objfun(x);          % Get symbolic expression for objfun in terms of x

Отказ от ответственности Это работаетпотому что все операции в objfun поддерживаются над символическими переменными.Для более сложных целевых функций этот подход может не работать.

Это определяет x как N -by- I матрицу символических переменных

>> x
x =
[ x1_1, x1_2, x1_3]
[ x2_1, x2_2, x2_3]
[ x3_1, x3_2, x3_3]
[ x4_1, x4_2, x4_3]

и определяет f as

>> f
f = 
6000 - 500*x1_2 - 500*x1_3 - 500*x2_1 - 500*x2_2 - 500*x2_3 - 500*x3_1 - 500*x3_2 - 500*x3_3 - 500*x4_1 - 500*x4_2 - 500*x4_3 - 500*x1_1

Затем мы находим градиент f относительно x равным

>> g = reshape(gradient(f,x(:)), size(x))
g =
[ -500, -500, -500]
[ -500, -500, -500]
[ -500, -500, -500]
[ -500, -500, -500]

Дополнительные reshape должны соответствовать общей интерпретации дляградиент как тензор с теми же размерами, что и x.

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

grad_fun = matlabFunction(g,'Vars',x);
obj_with_grad = @(x) deal(objfun(x), grad_fun(x));

Теперь вы можете получить цельи градиент в любой точке.Например, при х = единицы (N, I);

>> [obj_val, grad_val] = obj_with_grad(ones(N,I))
obj_val =
      0
grad_val =
  -500  -500  -500
  -500  -500  -500
  -500  -500  -500
  -500  -500  -500

Я не тестировал, но теперь вы можете использовать obj_with_grad с fmincon, установив fmincon 's 'SpecifyObjectiveGradient' опция до true.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...