3

我正在尝试提取满足某个均值和方差的 Weibull 分布参数(形状“k”和尺度“lambda”)。在这个例子中,均值是 4,方差是 8。这是一个 2-unknowns 和 2-equations 类型的问题。

由于该算法适用于 Excel 2010 的 GRG Solver,因此我确信它与我构建问题的方式有关,或者可能与我正在使用的库有关。我对优化库不太熟悉,所以请告诉我错误在哪里。

下面是脚本:

from scipy.optimize import fmin_cg
import math

def weibull_mu(k, lmda):                  #Formula can be found on wikipedia
    return lmda*math.gamma(1+1/k)
def weibull_var(k, lmda):                 #Formula can be found on wikipedia
    return lmda**2*math.gamma(1+2/k)-weibull_mu(k, lmda)**2

def min_function(arggs):
    actual_mean = 4                          # specific to this example
    actual_var = 8                           # specific to this example
    k = arggs[0]
    lmda = arggs[1]
    output = [weibull_mu(k, lmda)-(var_wei)]
    output.append(weibull_var(k, lmda)-(actual_var)**2-(actual_mean)**2)
    return output

print fmin(min_function, [1,1])

这个脚本给了我以下错误:

[...]
  File "C:\Program Files\Python27\lib\site-packages\scipy\optimize\optimize.py", line 278, in fmin
    fsim[0] = func(x0)
ValueError: setting an array element with a sequence.
4

2 回答 2

4

据我所知,min_function返回一个多维列表,但fminfmin_cg确实希望目标函数返回一个标量,如果我没记错的话。

如果您正在搜索两个方程问题的根,我想您最好应用函数。据我所知,scipy没有为向量函数提供任何通用优化器。

于 2012-06-28T13:48:18.087 回答
2

感谢 Anders Gustafsson 的评论(谢谢),我设法让它工作。如果仅返回一个标量,则此脚本现在可以工作(在这种情况下,我使用了最小二乘法)。此外,通过将优化函数更改为“fmin_l_bfgs_b”来添加边界(再次感谢 Anders Gustafsson)。

我只更改了与问题相关的 min_function 定义。

from scipy.optimize import fmin_l_bfgs_b
import math

def weibull_mu(k, lmda):
    return lmda*math.gamma(1+1/k)
def weibull_var(k, lmda):
    return lmda**2*math.gamma(1+2/k)-weibull_mu(k, lmda)**2

def min_function(arggs):
    actual_mean = 4.                    # specific to this example
    actual_var = 8.                     # specific to this example
    k = arggs[0]
    lmda = arggs[1]
    extracted_var = weibull_var(k, lmda)
    extracted_mean = weibull_mu(k, lmda)
    output = (extracted_var - actual_var)**2 + (extracted_mean - actual_mean)**2
    return output

print fmin_l_bfgs_b(min_function, best_guess, approx_grad = True, bounds = [(.0000001,None),(.0000001,None)], disp = False)

注意:请随时将此脚本用于您自己或专业用途。

于 2012-06-28T15:20:16.843 回答