Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Matlab中从复杂目标函数中求梯度_Matlab_Gradient - Fatal编程技术网

在Matlab中从复杂目标函数中求梯度

在Matlab中从复杂目标函数中求梯度,matlab,gradient,Matlab,Gradient,我在从以下目标函数计算符号梯度时遇到问题: 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 + su

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

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抱怨,因为它试图将函数指针转换为符号表达式,但它不能

在这种情况下,以下方法有效

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]
额外的
重塑
是为了符合梯度作为与
x
尺寸相同的张量的常见解释

编辑 对评论作出回应。如果您想将其与
fmincon
一起使用,从而得到一个同时给出目标值和梯度的函数,那么您可以按照如下方式构造这样一个函数句柄

grad_fun = matlabFunction(g,'Vars',x);
obj_with_grad = @(x) deal(objfun(x), grad_fun(x));
现在你可以在任意点得到目标和梯度。例如,x=一(N,I)


我没有进行测试,但您现在应该能够通过将
fmincon
SpecifyObjectiveGradient'
选项设置为
true
,将
obj_与
fmincon
一起使用
?我想用这个梯度来优化解算器,所以我需要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
将表达式转换为函数句柄。即
grad\u fun=matlabFunction(g,'Vars',x)没有内置的方法将括号添加到字符串表示法AFAIK中。@bnbfreak我更新了答案,以提供我上一次评论的详细信息。
>> [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