在Python中重写SAS优化



我试图在Python中重写类似于以下SAS优化代码的东西。代码的目标是找到最适合某些经验数据的连续分布(在本例中为正态分布)的参数。我对Python很熟悉,但对SAS很陌生。

proc nlin data=mydata outest=est METHOD=MARQUARDT SMETHOD=GOLDEN SAVE;
parms m = -1.0 to 1.0 by 0.1
s = 1.0 to 2.0 by 0.01;
bounds -10<m<10;
bounds 0<s<10;
model NCDF = CDF('NORMAL',XValue,m,s);
run;

在Python中,我有这样的设置:

import pandas as pd
from scipy import stats
from scipy.optimize import minimize
def distance_empirical_fitted_cdf( params: list, data: pd.Series ):
m,s = params
empirical_cdf = ( data / 100 ).cumsum()
cost = 0
for point in range( 10 ):
emprical_cdf_at_point = empirical_cdf.iloc[ point ]
fitted_cdf_at_point = stats.norm.cdf( x = point, loc = m, scale = s )
cost += ( fitted_cdf_at_point - empirical_cdf_at_point ) ** 2 
return cost
result = minimize( distance_empirical_fitted_cdf, x0=[0,1.5], args=(distribution),
bounds=[(-10,10),(0,10)] )
fitted_m, fitted_s = result.x
在大多数情况下,我现在拥有的代码使我非常接近现有代码的输出,但并非全部。理想情况下,我可以让它们匹配或尽可能接近,并理解为什么它们不匹配。

据我所知,有两个差异的来源。首先,SAS代码能够获取一组可能的起始值(在本例中,m的范围为-1到1,s的范围为0到10)来初始化参数。在Python中有等价的吗?

其次,SAS代码具体使用了Marquardt优化方法和黄金步长搜索方法。我能找到的唯一引用Marquardt方法的Python代码是scipy.optimize。leastrongquares with method="lm",但这不支持边界(并且与我尝试不带边界时的scipy.optimize.minimize相比要远得多)。

我能找到的唯一引用黄金步长搜索方法的Python代码是scipy.optimize。Golden,但是文档说这是为了最小化一个变量的函数,似乎也不支持边界。

任何关于使Python输出更接近SAS输出的见解将非常感激,谢谢!

没有答案,因为对于为什么(或如何)这两组代码产生不同的结果仍然没有定论。因此,随着更多信息的引入,这可能会发生变化。但与此同时,这里有一些可能有用的观察,但太多了,不能全部放在评论部分。

算法

SAS所称的马夸特方法更常被称为Levenberg-Marquardt算法(至少对我来说),缩写为LMA或LM。

范围

LMA的数学没有定义为处理边界,这就是为什么在scipy中没有提供绑定选项。

scipy.optimize.leastsq中使用的Levenberg-Marquardt算法的minpack1实现没有明确支持参数的边界,并期望能够充分探索任何参数的可用值范围。简单地放置硬约束(即,当值超过期望的界限时重置值)会阻止算法确定偏导数,并导致不稳定的结果。

结果的差异可能从这里产生,这取决于SAS决定如何处理所提供的边界参数。SAS可能会忽略提供的绑定值,重新运行直到找到边界内的解决方案,或者完全使用其他方法。

另一个可能的原因是在您提供的范围之外存在更好的解决方案。然后SAS将其解决方案限制在范围内,但python没有,反之亦然。这导致一个代码返回一个在边界内的局部最小值,而另一个代码返回一个更好的(可能是全局的)超出边界的最小值。

然而,我找不到在哪里(NLIN的SAS文档)解释这是如何处理的,所以这仍然是不确定的。

步长搜索

请注意,NLIN过程的SMETHOD用于搜索最优步长。

从SAS文档中阅读SMETHOD是不清楚的,步长是什么?正是,但我相信在这种情况下,它可以指"阻尼参数"lambda.

由于该参数对LMA的性能非常重要,因此确定该参数的不同方法也可能影响收敛性(从而影响最终结果)


同样,所有这些都取决于两个结果的差异。

如果两个结果明显不同(完全不同的输出CDF),那么可能只有一个CDF与实际数据匹配。与实际数据不匹配的代码可能是做错了什么,需要仔细检查。

相关内容

  • 没有找到相关文章

最新更新