【问题标题】:Find gradient from complicated objective function in Matlab在 Matlab 中从复杂的目标函数中找到梯度
【发布时间】:2018-05-14 02:51:36
【问题描述】:

我在从以下目标函数计算符号梯度时遇到问题:

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”。如何使这段代码有效?

【问题讨论】:

    标签: matlab gradient


    【解决方案1】:

    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 定义为

    >> 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));
    

    现在您可以在任意点获得目标和梯度。例如在 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' 选项设置为true 来使用obj_with_gradfmincon

    【讨论】:

    • 你有没有把 x1_1 变成 x(1,1) 的想法?我想将此梯度用于优化求解器,因此我需要 x(1) 而不是 x1。
    • 你可以把 x 做成你想要的任何大小。我通过I 制作了N 以匹配您的索引方案。在你的 objfun x 中至少需要有 N*I 条目。将x 的声明更改为x = sym('x', [N*I, 1]);,使x 成为列向量。
    • 我的意思是梯度结果显示像 x1, x2, x3。由于我在 fmincon 上使用这些变量,您是否有任何解决方案可以使它们成为 x(1)、x(2)、x(3)(带有附加括号)而无需手动更改?非常感谢您的帮助。
    • 您可以使用matlabFunction 将表达式转换为函数句柄,如果这是您所要求的。 IE。 grad_fun = matlabFunction(g,'Vars',x); 没有内置方法可以将括号添加到字符串表示 AFAIK。
    • @bnbfreak 我更新了答案以提供我上一条评论的详细信息。
    猜你喜欢
    • 1970-01-01
    • 2011-10-28
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-16
    • 2017-01-03
    相关资源
    最近更新 更多