在 Matlab 中从复杂的 objective 函数中查找梯度

Find gradient from complicated objective function in Matlab

我在使用以下 objective 函数计算符号梯度时遇到问题:

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

但是,出现这个错误"Only anonymous functions and functions without arguments can be converted to sym"。如何使此代码有效?

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 中的所有操作都支持符号变量。对于更复杂的 objective 函数,此方法可能不起作用。

这将 x 定义为 N×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定义为

>> 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 一起使用,这样你就有了一个同时给出 objective 值和梯度的函数,那么你可以按如下方式构造这样一个函数句柄。

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

现在您可以随时获取objective和渐变。例如在 x=ones(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

我没有测试,但现在通过将 fmincon'SpecifyObjectiveGradient' 选项设置为 [=31=,您应该可以将 obj_with_gradfmincon 一起使用].