【问题标题】:Minimize Function in MatlabMatlab中的最小化函数
【发布时间】:2013-07-30 15:34:26
【问题描述】:

我希望最小化(使用 fmincon 或类似功能)以下函数:

function Difference= myfun3(wk,omega,lambda,Passetcovar,tau,PMat,i,Pi,Q)
  wcalc=inv(lambda* Passetcovar)*inv(inv(tau * Passetcovar)+ PMat(i,:)'*inv(omega)*PMat(i,:))*(inv(tau * Passetcovar)*Pi+ PMat(i,:)'*inv(omega)*Q(i,:));
  Difference=sum((wk-wcalc).^2);
end

wkwcalc 是 列向量,其中 wk 已知且 wcalc 由上述等式给出。

如何通过将Omega 更改为Omega >0 来最小化Difference

  • lambda- 标量
  • Passetcovar-
  • tau - 标量
  • PMat-
  • Omega- 标量
  • Q-
  • Pi-

【问题讨论】:

  • 您通常需要对函数进行一些处理,以确保局部最小值实际上是全局最小值(例如,函数是凸函数)。是这样吗?
  • “最小化 f”是什么意思,它不是标量吗?
  • 抱歉,是的,它是一个标量 @Dennis Jaheruddin。
  • 调用变量 diff 是一个非常糟糕的主意,因为这会与 matlab 中非常有用的工具 - diff 发生冲突。大写的 D 将防止直接的名称冲突,但它仍然是一种糟糕的风格,因为这可能会在以后的某个时候让您感到困惑。
  • 另外,你应该告诉我们这些数组的形状,因为我敢打赌(有信心)最小化可以使用线性代数而不是最小化器来完成。但是,除非我确切地知道你在做什么,否则我不会努力写出来。

标签: matlab function optimization


【解决方案1】:

首先,sigma 是行向量吗?如果不是,那么f 也是一个向量。你在尝试多目标优化吗?那么fminsearch 将无济于事。

其次,在使用之前阅读fminsearch的文档。 f 应该是将输入向量映射到标量的函数。另外,它需要一个起点x0

因此,编写一个函数f,它接收omega 并返回一个标量目标函数值。另外,找出一个可行的x0(即omega的起始值)。

第三,fminsearch 不允许约束。你可以通过让f 返回Infomega <= 0 时的东西来破解它。我会推荐fmincon

你的函数应该是这样的。确保所有其他变量,如 PMap,tau 等。可全球访问。否则,您需要anonymous function 才能传递给fminsearch

obj = f(omega)
wcalc=inv(lambda* sigma)*inv(inv(tau * sigma)+ PMap(i,:)'*inv(Omega)*PMap(i,:))*(inv(tau * sigma)*pi+ PMap(i,:)'*inv(Omega)*Q(i,:));
obj = sigma*(wk-wcalc).^2;

然后使用fmincon。假设您有一个 omega 的起始值。

fmincon(f,omega,[],[],[],[],0,Inf);

添加了[],因为我们只想使用此表单从下方绑定您的解决方案。

x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub)

你的f是这样的吗?

obj = f(omega,PMap,sigma,.....)

...... 代表所有其他变量。那么就可以通过如下方式使用anonymous functions了。

g = @(omega)f(omega,PMap,sigma,.....);

现在您可以在fminconfminsearch 中使用g

【讨论】:

  • 谢谢。我不一定需要使用 fminsearch。我已尝试按照您为 fmincom 描述的那样设置问题,但出现错误。我需要单独保存一些零件吗?
  • 如果 f 是向量,fmincon 是否处理 f?
  • @Mary:不。如果您的目标函数返回一个向量,那么您就是在进行多目标优化。 fminconfminsearch等做单目标优化。
  • 我已按照您的指示提出:sigma=cell2mat(Passetcovar); function wcalc = f(x); lambda=3.07; wcalc= inv(lambda* sigma)*inv(inv(tau * sigma)+ PMap(i,:)'*inv(x)*PMap(i,:))*(inv(tau * sigma)*pi+ PMap(i,:)'*inv(x)*Q(i,:)); Diff=sum((wk-wcalc).^2). 然后我使用fmincon(f,x,[],[],[],[],0,Inf); 调用它,但出现以下错误。 @Jacob我无法弄清楚为什么......有什么想法吗?非常感谢
  • 错误是此上下文中不允许函数定义。
【解决方案2】:

您通常需要对函数进行一些处理,以确保局部最小值实际上是全局最小值(例如,函数是凸函数)。是这样吗?

假设是这样,或者您只是想找到一个局部最小值,请考虑以下示例:

clear all
close all
clc

f = @(x) (x+3).^2;

x = linspace(-5,5,100);
y = f(x);
plot(x,y);

ymin = fminsearch(f, 0);
printf('Local min found at: %f\n', ymin);

显示一个简单的图形并打印:

本地最小值:-3.000000

请注意,您必须指定搜索的起点。在这种情况下,我使用了 0。当你只给 fminsearch 一个参数时,它期望参数是一个结构,它看起来不像你正在使用的结构。

来自help fminsearch

X = fminsearch(PROBLEM) finds the minimum for PROBLEM. PROBLEM is a
    structure with the function FUN in PROBLEM.objective, the start point
    in PROBLEM.x0, the options structure in PROBLEM.options, and solver
    name 'fminsearch' in PROBLEM.solver. The PROBLEM structure must have
    all the fields.

您可能想要这种用法:

X = fminsearch(FUN,X0) starts at X0 and attempts to find a local minimizer 
    X of the function FUN.  FUN is a function handle.  FUN accepts input X and 
    returns a scalar function value F evaluated at X. X0 can be a scalar, vector 
    or matrix.

【讨论】:

    【解决方案3】:

    由于您有一个相当复杂的函数,并且只想改变 1 个标量,我会说:考虑使用蛮力。

    这是一个如何做的例子(假设所有必需的变量都已定义)。

    rangeMin = 0;
    rangeMax = 10; %Put an assumed upper bound for Omega here
    stepNumber = 10000;
    Omega = linspace(rangeMin, rangeMax, stepNumber);
    result = Inf(size(Omega))
    for t = 1:length(Omega)
        wcalc(t)=inv(lambda* sigma)*inv(inv(tau * sigma)+ PMap(i,:)'*inv(Omega(t))*PMap(i,:))*(inv(tau * sigma)*pi+ PMap(i,:)'*inv(Omega(t))*Q(i,:));
    end
    
    wcalcMin = min(wcalc)
    OmegaMin = find(wcalc == wcalcMin)
    

    如果你想看看这个函数实际上是什么样子,你现在可以做

    plot(wcalc)
    

    如果您看到没有极端的尖峰,并且函数温和地接近局部最小值(而不是在那里跳跃),这可能是一个不错的方法。

    如果您对函数行为感到满意,您可以通过将rangeMinrangeMax 设置为仅评估您感兴趣的区域来提高准确性。如果您对行为不满意,可以尝试增加stepNumber 是否有帮助。

    【讨论】:

    • 如果您投反对票,请发表评论。我确实使用了禁忌词 brute force 但请注意,这是一种非常普遍适用的方法,甚至能够处理多目标优化。此外,它相对稳健,不会陷入局部最小值。
    【解决方案4】:

    这个目标并没有那么复杂。但是你写的看起来很复杂。

    首先,欧米茄是一个标量!为什么要写 inv(omega)?除以 omega 是一个更好的主意,因为它不会涉及反函数的开销。

    接下来,tau 是一个已知的常数标量,Passetcovar 也是如此。为什么每次调用函数时都要计算矩阵的逆矩阵 (tau*Passetcovar)?不仅如此,您还可以在一行中计算相同的逆矩阵三次。学习预先计算这些东西。它将为您节省很多时间和很多麻烦。

    不管怎样,你对 inv 很着迷。它在一行中被调用了 6 次,而且大多数调用都是多余的。

    让我们重写你的那一行。首先,预先计算 inv(Passetcovar),将整个事情传递到您的目标中,因此您只需执行一次。

    注意基本身份:

    inv(k*A) = inv(A)/k
    

    这对任何非零标量 k 都有效。

    IP = inv(Passetcovar);
    

    同样,不要在每次调用目标函数时重复 inv(Passetcovar) 的计算。相反,在开始优化之前计算一次。

    所以计算变得更容易阅读:

    wcalc = IP./lambda*inv(IP./tau + PMat(i,:)'*PMat(i,:)/omega)*(IP*Pi./tau + PMat(i,:)'*Q(i,:)/omega);
    

    编辑:

    最后我们知道 Pi 是一个向量。我想它必须是一个 8x1 向量,以便数组乘法符合。

    我们可以通过分解一些常数并在方便的地方插入括号来节省更多的除法和乘法。请注意,通过首先计算矩阵*向量乘法,然后乘以 IP,我们将 8x8 * 8x8 乘法转换为 8x8 X 8x1 乘法。对于像这样的小数组,差别并不大,但值得记住这个想法。

    wcalc = IP*(inv(IP + tau*PMat(i,:)'*PMat(i,:)/omega)*(IP*Pi + PMat(i,:)'*Q(i,:)/omega*tau))/(lambda*tau^2);
    

    目标是最小化 wcalc 和 wk 之间的平方和,服从正 omega。这现在是一个标量。

    我建议先绘制函数,只是为了了解它的形状,看看什么可能是 omega 的一个好的起始值。因此,通过在 myfun 周围包装一个函数句柄,ezplot 将很好地绘制绘图,这里对于 omega 的范围为 [0,100]。如果不合理,请选择您自己的 omega 上限。

    ezplot(@(omega) myfun3(wk,omega,lambda,Passetcovar,tau,PMat,i,Pi,Q),[0,100])
    

    因此,简单的解决方案是使用 fminbnd,为上限提供一些合理但足够大的值。 fminbnd 的一个好处是它不需要起始值。您需要为 omega 选择一个合理的上限。关键是,使用旨在最小化标量函数的工具。不需要像 fmincon 这样的通用优化器,需要一个起始值。

    finalomega = fminbnd(@(omega) myfun3(wk,omega,lambda,Passetcovar,tau,PMat,i,Pi,Q),[0,100])
    

    您也可以使用文件交换中的fminsearchbnd。它可以最小化仅受下限约束的函数,但 fminsearchbnd 需要 omega 的起始值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多