如何使用scipy.optimize.curve_fit()函数返回的结果计算决定系数R2

问题引入

当我们需要对一批数据做曲线拟合的时候,来自python的scipy包下的curve_fit()函数往往是一个不错的选择,但curve_fit()函数返回的结果只有拟合曲线的参数popt和参数的估计协方差pcov(etismatated covarianve of popt)[1]。而作为回归模型重要的衡量参数——决定系数R2,并没有作为函数的返回结果直接提供。(函数的具体使用参见官方doc)

接下来将解说如何利用curve_fit()函数返回的结果来计算R2

背景知识

决定系数R2的定义

先放一段维基百科中的定义[2]

In statistics, the coefficient of determination, denoted R2 or r2 and pronounced "R squared", is the proportion of the variation in the dependent variable that is predictable from the independent variable(s).

翻译到中文就是:

在统计学中,决定系数(记作R2r2)是用于度量因变量的差异中可由自变量解释的部分所占的比例。

我们一般使用决定系数来判断回归模型的解释力,通俗一点说就是决定系数越高的模型,拟合度越高。

决定系数R2的计算

定义一个数据集包括y1,,ynn个观测值,相应的经过模型拟合后的结果f1,,fn,同时定义残差为ei=yifi。[2]

y¯为观测值的均值,定义如下:

(1)y¯=1ni=1nyi

于是(拟合结果与)数据集的差异可以用以下两个平方和公式来衡量:

  • 总体平方和(与数据的方差成正比)

    (2)SStot=i(yiy¯)2

  • 残差平方和

    (3)SSres=i(yifi)2=iei2

由此,决定系数的最常用的定义如下:

(4)R2=1SSresSStot

在理想状态下,模型拟合的结果和观测值正好完全一致,这样就能计算得到SSres=0R2=0。作为基准,如果模型一直拟合出结果为y¯,那么其R2=0。具有比此基准更差的预测结果的模型,其R2将为负值。

解决问题

示例数据

首先定义一个待拟合的数据集。

y=x的基础上,给每个y随机加减[2,2]内的任意值,由此构建出示例数据,代码如下:

import numpy as np

# define func: y=ax+b
def func(x, a, b):
    x = np.array(x)
    return a * x + b

X = range(0, 50) # x
y = func(X, a=1, b=0) # baseline function: y=x
res = np.random.uniform(low=-2.0, high=2.0, size=len(X))
y = [y[i] + res[i] for i in range(0, len(y))]

绘制出散点图如下:

image

使用curve_fit()函数做拟合

在示例数据和之前定义的函数基础上,我们对数据做拟合,代码实现如下:

from scipy.optimize import curve_fit

popt, pcov = curve_fit(func, X, y)

拟合出的函数图像如下:

image

根据公式计算拟合曲线的决定系数

依照前面的公式,我们可以将决定系数的计算分为以下几步:

  1. 计算均值
  2. 计算总体平方和
  3. 计算残差平方和
  4. 计算决定系数

代码实现如下[3]:

import numpy as np

mean = np.mean(y)  # 1.y mean
ss_tot = np.sum((y - mean) ** 2)  # 2.total sum of squares
ss_res = np.sum((y - func(X, *popt)) ** 2)  # 3.residual sum of squares
r_squared = 1 - (ss_res / ss_tot)  # 4.r squared

我们将前面的结果和计算出的决定系数绘制到同一张图中:

image

参考

[1] scipy.optimize.curve_fit — SciPy v1.6.3 Reference Guide

[2] Coefficient of determination - Wikipedia

[3] python - Getting the r-squared value using curve_fit - Stack Overflow

posted @   Minerw  阅读(7769)  评论(0编辑  收藏  举报
编辑推荐:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示
主题色彩