正确的方法显然取决于您的数据和模型。然而,将曲线强制为某种形状的一种方法是在拟合过程中使用权重:
import numpy as np
from scipy.optimize import curve_fit
from matplotlib import pyplot as plt
#simulate the data
def func_exp(x, a, b, c, d):
return a * (1 - b* np.exp(-c*x)) + d
np.random.seed(123456789)
n=400
time_real = np.linspace(0, 5000, n)
temp_real = func_exp(time_real, 21, 0.7, 0.001, 63) + np.random.random(n)
n_measured = int(n*0.5)
time_measured = time_real[:n_measured]
temp_measured = temp_real[:n_measured]
#curve fitting a logarithmic function on the data
def func_log(x, a, b, c, d):
return a * np.log(b * (x+c)) + d
#without weights
expected_coefs_log = [3, 1, 1, 1]
popt_noweight, pcov = curve_fit(func_log, time_measured, temp_measured, expected_coefs_log)
print(popt_noweight)
#artificial weights emphasizing points at a later time point
sigma_coefs_log = np.linspace(5, 0.01, len(time_measured))
popt_weight, pcov = curve_fit(func_log, time_measured, temp_measured, p0=expected_coefs_log, sigma=sigma_coefs_log)
print(popt_weight)
#graphic representation
plt.scatter(time_real, temp_real, c="orange", marker=".", label="expected data")
plt.scatter(time_measured, temp_measured, color="red", marker=".", label="measured data")
plt.plot(time_real, func_log(time_real, *popt_noweight), color="blue", label="fit, no weight")
plt.plot(time_real, func_log(time_real, *popt_weight), color="green", label="fit, weight")
plt.legend()
plt.show()
样本输出:

但是,如果您期望一个平台期(在您的问题中没有解释为什么您认为“想要的函数”应该是正确的),对数模型可能只是错误的函数类型,正如我们在初始部分的权衡中所看到的那样现在不太适应数据。