2014-04-03 17 views
4

我使用scipy的curvefit模塊來擬合函數,並想知道是否有辦法告訴它唯一可能的條目是整數而不是實數?任何想法,以另一種方式做到這一點?使用整數輸入的曲線擬合Python 3.3

+0

我所能想到的是一個約束'p%1',但我不確定這會使解算器的行爲如何。 – askewchan

回答

2

在其一般形式中,整數規劃問題是NP-hard(請參見here)。有一些有效的啓發式算法或近似算法來解決這個問題,但都不能保證一個確切的最佳解決方案。

在scipy中,您可以對整數係數執行網格搜索,並在給定整數係數的實參數上使用curve_fit。至於網格搜索。 scipy具有brute功能。

例如,如果y = a * x + b * x^2 + some-noise其中a必須是整數,這可能工作:

  1. 生成一些測試數據與a = 5b = -1.5

    coef, n = [5, - 1.5], 50 
    xs = np.linspace(0, 10, n)[:,np.newaxis] 
    xs = np.hstack([xs, xs**2]) 
    noise = 2 * np.random.randn(n) 
    ys = np.dot(xs, coef) + noise 
    
  2. 其中給出的整數係數擬合的函數實際係數採用curve_fit方法:

    def optfloat(intcoef, xs, ys): 
        from scipy.optimize import curve_fit 
        def poly(xs, floatcoef): 
         return np.dot(xs, [intcoef, floatcoef]) 
        popt, pcov = curve_fit(poly, xs, ys) 
        errsqr = np.linalg.norm(poly(xs, popt) - ys) 
        return dict(errsqr=errsqr, floatcoef=popt) 
    
  3. 其中給出的整數係數的函數,使用了上述功能,以優化浮動係數,並返回錯誤:

    def errfun(intcoef, *args): 
        xs, ys = args 
        return optfloat(intcoef, xs, ys)['errsqr'] 
    
  4. 使用scipy.optimize.brute找到最佳整數係數和呼叫optfloat用優化最小化errfun整係數來找到最佳的實係數:

    from scipy.optimize import brute 
    grid = [slice(1, 10, 1)] # grid search over 1, 2, ..., 9 
    # it is important to specify finish=None in below 
    intcoef = brute(errfun, grid, args=(xs, ys,), finish=None) 
    floatcoef = optfloat(intcoef, xs, ys)['floatcoef'][0] 
    

使用這種方法,我得到[5.0, -1.50577]的最佳係數,這對於整數係數是精確的,並且對於實係數足夠接近。

0

一般來說,答案是否定的:scipy.optimize.curve_fit()和leastsq()是基於它的,並且(AFAIK)scipy中的所有其他解算器都是嚴格遵守浮點數的。

您可以嘗試增加epsfcn的值(其默認值爲numpy.finfo('double')。eps〜2.e-16),它將用作所有變量的初始步驟問題。基本的問題是,擬合算法將調整一個浮點數,如果你這樣做

int_var = int(float_var) 

和算法的變化,從1.0至1.00000001 float_var,它會看到在結果沒有差異,並決定該值不實際上並沒有改變擬合度量。

另一種方法是爲具有浮點參數「tmp_float_var」是自由地擬合算法調整,但然後在目標函數使用

int_var = int(tmp_float_var/numpy.finfo('double').eps) 

作爲你的整數變量的值。這可能需要稍微調整,並可能有點不穩定,但應該起作用。