簡體   English   中英

SciPy.optimize.least_squares() 5PL曲線優化問題

[英]SciPy.optimize.least_squares() 5PL Curve Optimization problems

我正在嘗試編寫一個腳本,它將采用 x 和 y 值的輸入數組並將它們擬合到 5-PL 曲線(由等式 F(x) = D+(AD)/((1+(x/C )^B)^E))。 然后我希望能夠使用預測曲線獲取給定的 y 值並從曲線中推斷出 x 值,由方程 F(y) = C(((AD)/(-D+y))^ (1/E)-1)^(1/B)。

下面的答案修復了之前的錯誤,但是貼合度還是很差。 我介紹了一個打印 function ,其中有幾個 y 值在整個范圍內輸入到 curve_fit 中,它在整個范圍內產生幾乎完全相同的 x 值。 有什么想法可能發生在這里嗎?

編輯:對於現在看的人來說,問題似乎是我對 B 的估計。在大多數情況下,山坡應該在 -1 和 1 之間,而不是數千。 這使得估計太遠了。

import numpy as np
import scipy.optimize as sp


def logistic5(x, A, B, C, D, E):
    '''5PL logistic equation'''
    log = D + (A-D)/(np.power((1 + np.power((x/C), B)), E))
    return log


def residuals(p, y, x):
    '''Deviations of data from fitted 5PL curve'''
    A, B, C, D, E = p
    err = y - logistic5(x, A, B, C, D, E)
    print(err)
    return err


def log_solve_for_x(curve, y):
    '''Returns the estimated x value for the provided y value'''
    A, B, C, D, E = curve
    return C*(np.power((np.power(((A-D)/(-D+y)), (1/E))-1), (1/B)))


# Toy data set
x = np.array([130, 38, 15, 4.63, 1.41])
y = np.array([9121, 1987, 1017, 343, 117])

# Set initial guess for parameters
A = np.amin(y)  # Min asymptote
D = np.amax(y)  # Max asymptote
B = (D-A)/(np.amax(x)-np.amin(x))  # Steepness
C = (np.amax(x)-np.amin(x))/2  # inflection point
E = 1  # Asymmetry factor

# Optimize curve for initial parameters
p0 = [A, B, C, D, E]
# set bounds for each parameter
pu = []
pl = []
for p in p0:
    pu.append(p*1.5)
    pl.append(p*0.5)
print(pu)
print(pl)
print("Initial guess of parameters is: ", p0)
curve = sp.least_squares(fun=residuals, x0=p0, args=(y, x), bounds=(pl, pu))
curve = curve.x.tolist()
print("Optimized curve parameters are: ", curve)

# Predict x values based on given y
y = [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000]
for sample in y:
    solve = log_solve_for_x(curve, sample)
    print("Predicted X value for y =", sample, " is: ", solve)

您的曲線不是為任何參數值定義的。 但是您沒有為least_squares提供該信息。 在某些時候,求解器會進入一個不允許的區域並卡在那里從residuals中獲取 nans,並且您會收到有關無效功率的消息。 你有微不足道的權力,可能只是設置E>=0, B>=0 但是您的基礎並非微不足道。 您要么需要切換到支持通用約束的求解器(例如scipy.optimize.minimize )並添加base >=0的約束,要么以其他方式將搜索限制在允許的域,例如:

pu = []
pl = []
for p in p0:
    pu.append(p*1.5)
    pl.append(p*.5)

curve = sp.least_squares(fun=residuals, x0=p0, args=(y, x), bounds=(pl, pu))

您也可以嘗試修復它適用於任何參數的殘差,例如將 nan 替換為與初始猜測的距離。 但它可能效率低下。


為了改善擬合結果,您可以嘗試更好的初始點或多起點或兩者兼而有之。

A = np.amin(y)  # Min asymptote
D = np.amax(y)  # Max asymptote
B = (D-A)/np.amax(x)*10  # Steepness
C = np.amax(x)/10  # inflection point
E = 0.001  # Asymmetry factor

p0 = [A, B, C, D, E]
print("Initial guess of parameters is: ", p0)
pu = []
pl = []
for p in p0:
    pu.append(p*1.5)
    pl.append(p*.5)

best_cost = np.inf
for i in range(100):
    for i in range(5):
        p0[i] = np.random.uniform(pl[i], pu[i])

    curve = sp.least_squares(fun=residuals, x0=p0, args=(y, x), bounds=(pl, pu))
    print(p0, curve.cost)
    if best_cost > curve.cost:
        best_cost = curve.cost
        curve_out = curve.x.tolist()
print("Optimized curve parameters are: ", curve_out)

plt.plot(x, y, '.')

xx = np.linspace(0, 150, 100)
yy = []
for x in xx:
    yy.append(logistic5(x, *curve_out))

plt.plot(xx, yy)
plt.show()

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM