我正在尝试使用梯度下降法在N个参数中找到一个函数的最小值。然而,我希望在参数绝对值之和限制为1(或<=1,无关紧要)的条件下进行操作。因此,我使用了拉格朗日乘数法,所以如果我的函数是f(x),我将最小化f(x) + lambda * (g(x)-1),其中g(x)是对参数绝对值之和的平滑近似。
据我所知,这个函数的梯度只有在g(x)=1时才会为0,因此寻找局部最小值的方法应该能找到我的函数的最小值,同时满足我的条件。问题是,这种增加使我的函数变得无界,导致梯度下降法不断找到越来越大的lambda和越来越大的参数(绝对值),从而无法收敛。
目前我正在使用Python的scipy库中的CG(共轭梯度法)实现,所以我非常希望得到一些建议,这些建议不需要我自己重写或调整CG代码,而是使用现有的方法。
回答:
问题在于使用拉格朗日乘数法时,临界点不会出现在拉格朗日函数的局部最小值处——它们出现在鞍点上。由于梯度下降算法旨在寻找局部最小值,当你给它一个带约束的问题时,它无法收敛。
通常有三种解决方案:
- 使用能够找到鞍点的数值方法,例如牛顿法。然而,这些方法通常需要梯度和Hessian的解析表达式。
- 使用惩罚方法。在这里,你在成本函数中添加一个额外的(平滑的)项,当约束得到满足(或接近满足)时,该项为零,当约束不满足时,该项非常大。然后你可以像往常一样运行梯度下降法。然而,这通常具有较差的收敛特性,因为它需要进行许多小的调整以确保参数满足约束条件。
- 不是寻找拉格朗日函数的临界点,而是最小化拉格朗日函数梯度的平方。显然,如果拉格朗日函数的所有导数都为零,那么梯度的平方将为零,并且由于某物的平方永远不可能小于零,你将找到与通过极值化拉格朗日函数相同的结果。然而,如果你想使用梯度下降法,那么你需要拉格朗日函数梯度平方的梯度表达式,这可能并不容易获得。
就我个人而言,我会选择第三种方法,如果获取拉格朗日函数梯度平方的解析表达式太困难,我会数值地找到它的梯度。
另外,你在问题中没有完全说明清楚——你是使用梯度下降法,还是CG(共轭梯度法)?