Scipy曲线拟合不执行拟合,并引发“无法估计参数的协方差”错误

qlvxas9a  于 2022-12-13  发布在  其他
关注(0)|答案(1)|浏览(184)

我正在尝试用scipy做一个简单的线性曲线拟合,通常这种方法对我来说很好。但是这次由于一个我不知道的原因,它不起作用。
(我怀疑可能是因为这些数字太大了,以至于达到了给定数据类型下可以存储的极限。)
不管是什么原因,这个想法就是要做出这样的情节:

正如你在这里的轴上所看到的,这些数字是一个共同的数量级。然而,这次我试图拟合更大的数据点,数量级为1 E10,为此,我尝试使用以下代码(这里我只展示了制作散点图的代码,然后只拟合一个数据集)。

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

ucrt_T = 2/np.sqrt(3)
ucrt_U = 0.1/np.sqrt(3)
T = [314.1, 325.1, 335.1, 345.1, 355.1, 365.1, 374.1, 384.1, 393.1]

T_to_4th = [9733560790.61, 11170378213.80, 12609495509.84, 14183383217.88, 15900203737.92, 17768359469.96, 19586229219.65, 21765930026.49, 23878782252.31]
ucrt_T_lst = [143130823.11, 158701221.00, 173801148.95, 189829733.26, 206814686.75, 224783722.22, 241820148.88, 261735288.93, 280568229.17]

UBlack = [1.9,3.1, 4.4, 5.6, 7.0, 8.7, 10.2, 11.8, 13.4]

def lin_function(x,a,b):
    return a*x + b

def line_fit_2():
    #Dodanie pozostałych punktów na wykresie
    plt.scatter(UBlack, T_to_4th, color='blue')
    plt.errorbar(UBlack, T_to_4th, yerr=ucrt_T, fmt='o')

    #Seria CZARNA
    VltBlack = np.array(UBlack)
    Tt4 = np.array(T_to_4th)
    popt, pcov = curve_fit(lin_function, VltBlack, Tt4, absolute_sigma=False)
    perr = np.sqrt(np.diag(pcov))
    y = lin_function(VltBlack, *popt)
    #Stylistyka i wygląd wykresu
    #plt.plot(Pressure1, y, '--', color = 'g', label="fit with: $a={:.3f}\pm{:.3f}$, $b={:.3f}\pm{:.3f}$" .format(popt[0], perr[0], popt[1], perr[1]))
    plt.plot(VltBlack, y, '--', color='green')

    plt.ylabel(r'$T^4$ w $[K^4]$')
    plt.xlabel(r'Napięcie termometru U w [mV]')
    plt.legend(['Fit', 'Data points'])
    plt.grid()
    plt.show()

line_fit_2()

如果你运行它,你会发现散点图被创建,但是拟合没有正确执行,因为只有一条水平线被添加。此外,一个错误OptimizeWarning: Covariance of the parameters could not be estimated category=OptimizeWarning)被引发。
我会非常高兴知道我做错了什么或者如何解决这个问题。所有的帮助都很感激!

oprakyz7

oprakyz71#

你的问题已经回答得差不多了,我就证实一下你的怀疑:引发OptimizeWarning的原因是因为底层的优化算法由于较大的参数数而不能正常工作/发散。
解决方法很简单,在使用拟合工具之前缩放输入参数即可。在向x/y轴添加标签时,请记住缩放:

T_to_4th = np.array([9733560790.61, 11170378213.80, 12609495509.84, 14183383217.88, 15900203737.92, 17768359469.96, 19586229219.65, 21765930026.49, 23878782252.31])/10e6
ucrt_T_lst = np.array([143130823.11, 158701221.00, 173801148.95, 189829733.26, 206814686.75, 224783722.22, 241820148.88, 261735288.93, 280568229.17])/10e6

我所做的只是用10e6来除大数字列表。这意味着这些值不再以kPa为单位,而是以兆kPa为单位(现在是GPa)。
若要将整个列表除以相同的值,请先将其转换为numpy数组。
希望这对你有帮助:)

相关问题