让我在这里以一个故事为开头谨慎说几句话。很久以前,刚开始时我和一个伙伴一起工作。他有一个目标很杂乱的优化问题要解决。他的解决方案是生成分析导数以进行优化。
我看到的问题是这些衍生物很讨厌。它们是使用Macsyma生成的,并转换为fortran代码,每个都有数十条连续语句。实际上,Fortran编译器对此感到不安,因为它超出了连续语句的最大数量。尽管我们找到了一个可以解决该问题的标志,但还有其他问题。
在长表达式中,正如CA系统通常生成的那样,存在大量减法抵消的风险。计算很多大数,却发现它们全部互相抵消而产生一个小数。
实际上,与使用有限差分的数字生成的导数相比,分析生成的导数实际上通常更昂贵。n个变量的梯度所花费的成本可能是评估目标函数的成本的n倍以上。(您可能能够节省一些时间,因为许多术语可以在各种派生词中重复使用,但这也将迫使您进行仔细的手工编码,而不是使用计算机生成的表达式。而且任何时候编写令人讨厌的数学代码表达式,则出错的可能性并不小。请确保验证这些导数的准确性。)
我的故事的重点是这些CA生成的表达式都有其自身的问题。有趣的是,我的同事实际上为这个问题的复杂性感到骄傲,他显然解决了一个非常困难的问题,因为代数是如此讨厌。我不认为他认为的是,代数是否实际上在计算正确的东西,执行得是否准确以及执行得是否有效。
如果我当时是这个项目的资深人士,我会读给他看一下暴动。他的骄傲让他使用了可能不必要复杂的解决方案,甚至没有检查基于有限差分的梯度是否足够。我敢打赌,我们可能花了一个星期的时间来运行此优化程序。至少,我会建议他仔细测试所产生的渐变。准确吗?与有限差分导数相比,精度如何?实际上,今天周围有一些工具也会在其导数预测中返回误差的估计值。对于我在MATLAB中编写的自适应微分代码(派生),这确实是正确的。
测试代码。验证派生词。
但是在执行任何此操作之前,请考虑是否可以选择其他更好的优化方案。例如,如果您正在进行指数拟合,则很有可能使用分区的非线性最小二乘法(有时称为可分离的最小二乘。我认为这是Seber和Wild在他们的书中使用的术语。)就是将参数集分为本征线性和本征非线性。使用仅对非线性参数有效的优化。假定那些参数是“已知的”,则可以使用简单的线性最小二乘法来估计固有线性参数。该方案将减少优化中的参数空间。由于您无需查找线性参数的起始值,因此它使问题更加可靠。它减小了搜索空间的维数,因此使问题运行得更快。我再次提供一个用于此目的的工具,但仅限于MATLAB中。
如果您确实使用分析导数,则对它们进行编码以重用术语。这可以节省大量时间,并且实际上可以减少错误,从而节省您自己的时间。但是,然后检查那些数字!
codegen
其中的包,因为它可以为每个或所有表达式自动生成紧凑而有效的C或Fortran代码。