4参数逻辑曲线拟合

huangapple go评论63阅读模式
英文:

4-parameter logistic curve fit

问题

我正在尝试使用scipy对来自科学试验的数据执行4参数 logistic (4PL) 曲线拟合。目标是获得一个与我通常使用的软件结果密切匹配的拟合曲线。

不幸的是,曲线的下部拟合效果不佳,如下图所示。

4参数逻辑曲线拟合

我还尝试了在对x值应用log10变换后创建拟合,但只得到一条直线而不是曲线拟合。

4参数逻辑曲线拟合

以下是我的当前代码:

import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize as opt
from scipy.optimize import curve_fit

conc = np.array([300000, 70376.8, 16509.6, 3873.0, 908.6, 213.1, 50.0, 11.7])

ref = np.array([7.11469e+05, 2.16006e+05, 5.81840e+04, 1.39850e+04,
                3.21300e+03, 8.76000e+02, 2.54000e+02, 1.16000e+02])

# 4PL曲线方程
def func(xdata, a, b, c, d): 
    return ((a-d)/(1.0+((xdata/c)**b))) + d

# 计算示例权重为1/y^2
weights = 1 / (ref **2)

# 设置边界
amin = 50 
bounds = ([ amin, -np.inf, -np.inf , -np.inf], [np.inf, np.inf, np.inf, np.inf])

# 初始参数
a = min(ref) * 0.9
d = max(ref) * 1.1
b = 1
c = (d-a)/2    
initial_guess = [a, b, c, d] 
print('初始参数:', initial_guess)

# 执行曲线拟合
params, params_covariance = curve_fit(func, conc, ref, p0=initial_guess, method='trf',sigma=weights, bounds=bounds, maxfev=100000)
print('参数:', params)

# 从拟合曲线生成y值
x_fit = np.arange(min(conc), max(conc), 8) 
y_fit = func(x_fit, *params)

# 绘制原始数据和拟合曲线
plt.scatter(conc, ref , label='加权数据')
plt.plot(x_fit, y_fit, label='拟合曲线')
plt.xscale('log')
plt.yscale('log')
plt.xlabel('X')
plt.ylabel('Y')
plt.legend()
plt.show()
英文:

I am trying to perform a 4-parameter logistic (4PL) curve fit with scipy on data from a scientific assay. The goal is to get a fit that closely matches the results of the software I normally use.

Unfortunately, the lower part of the curve does not fit well, as shown in this figure.

4参数逻辑曲线拟合

I also tried to create a fit after applying a log10 transform to the x values, but I only get a straight line instead of a curve fit.

4参数逻辑曲线拟合

Below is my current code:

import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize as opt
from scipy.optimize import curve_fit

conc = np.array([300000, 70376.8, 16509.6, 3873.0, 908.6, 213.1, 50.0, 11.7])

ref = np.array([7.11469e+05, 2.16006e+05, 5.81840e+04, 1.39850e+04,
                3.21300e+03, 8.76000e+02, 2.54000e+02, 1.16000e+02])

# 4pl curve equation
def func(xdata, a, b, c, d): 
    return ((a-d)/(1.0+((xdata/c)**b))) + d

# Calculate example weights as 1/y^2
weights = 1 / (ref **2)

#set bounds
amin = 50 
bounds = ([ amin, -np.inf, -np.inf , -np.inf], [np.inf, np.inf, np.inf, np.inf])


# initial params
a = min(ref) * 0.9
d = max(ref) * 1.1
b = 1
c = (d-a)/2    
initial_guess = [a, b, c, d] 
print('Initial params:', initial_guess)


# # Perform the curve fit
params, params_covariance = curve_fit(func, conc, ref, p0=initial_guess, method='trf',sigma=weights, bounds=bounds, maxfev=100000)
print('params:', params)


# Generate y values from the fitted curve
x_fit = np.arange(min(conc), max(conc), 8) 
y_fit = func(x_fit, *params)

# # Plot the raw data and the fitted curve
#plt.scatter(conc_mlt, ref, label='Raw data')
plt.scatter(conc, ref , label='Weighted Data') #s=weights*100??
plt.plot(x_fit, y_fit, label='Fitted Curve')
plt.xscale('log')
plt.yscale('log')
plt.xlabel('X')
plt.ylabel('Y')
plt.legend()
plt.show()

答案1

得分: 1

我目前不确定如何使用scipy来改进你的低值拟合。然而,如果你不需要使用特定的拟合函数,你可以考虑使用numpy.polyfit等其他选项。以下是一个示例,以防这对你有用:

import numpy as np
import matplotlib.pyplot as plt

conc = np.array([300000, 70376.8, 16509.6, 3873.0, 908.6, 213.1, 50.0, 11.7])

ref = np.array([7.11469e+05, 2.16006e+05, 5.81840e+04, 1.39850e+04,
                3.21300e+03, 8.76000e+02, 2.54000e+02, 1.16000e+02])

## Trying NumPy Polyfit
np_fit = np.poly1d(np.polyfit(np.log(conc), np.log(ref), deg=4))
x_npfits = np.logspace(1, 6)
y_npfits = []
for i in x_npfits:
    y_npfits.append(np.exp(np_fit(np.log(i))))

plt.figure()
plt.scatter(conc, ref , label='Weighted Data')
plt.plot(x_npfits, y_npfits)
plt.xscale('log')
plt.yscale('log')
plt.grid("both")
plt.show()

生成:

4参数逻辑曲线拟合

英文:

I'm currently unsure of how to improve the fit of your lower values using scipy. However, if you don't require the use of your specific fitting function, you could potentially look at options like numpy.polyfit. Here is an example in case this could work for you:

import numpy as np
import matplotlib.pyplot as plt

conc = np.array([300000, 70376.8, 16509.6, 3873.0, 908.6, 213.1, 50.0, 11.7])

ref = np.array([7.11469e+05, 2.16006e+05, 5.81840e+04, 1.39850e+04,
                3.21300e+03, 8.76000e+02, 2.54000e+02, 1.16000e+02])

## Trying NumPy Polyfit
np_fit = np.poly1d(np.polyfit(np.log(conc), np.log(ref), deg=4))
x_npfits = np.logspace(1, 6)
y_npfits = []
for i in x_npfits:
    y_npfits.append(np.exp(np_fit(np.log(i))))

plt.figure()
plt.scatter(conc, ref , label='Weighted Data')
plt.plot(x_npfits, y_npfits)
plt.xscale('log')
plt.yscale('log')
plt.grid("both")
plt.show()

Produces:

4参数逻辑曲线拟合

huangapple
  • 本文由 发表于 2023年6月16日 00:22:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76483686.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定