数学建模-用scipy.optimize的模块的curve_fit函数实现曲线的非线性最小二乘法拟合


这里我们用经典的人口预测模型来进行函数的使用说明

美国人口预测模型

栗题:

利用下表给出的近两个世纪的美国人口统计数据(以百万为单位),建立人口预测模型,最后用它估计2010年美国的人口.

年份17901800181018201830184018501860
人口3.95.37.29.612.917.123.231.4
年份18701880189019001910192019301940
人口38.650.262.976.092.0106.5123.2131.7
年份195019601970198019902000
人口150.7179.3204.0226.5251.4281.4

建模与求解

记 x ( t ) 为 第 t 年 的 人 口 数 量 , 设 人 口 年 增 长 率 r ( x ) 为 x 的 线 性 函 数 , r ( x ) = r − s x 记x(t)为第t年的人口数量,设人口年增长率r(x)为x的线性函数,r(x)=r-sx x(t)tr(x)x线,r(x)=rsx
自 然 资 源 与 环 境 条 件 所 能 容 纳 的 最 大 人 口 数 为 x m , 即 当 x = x m 时 , 增 长 率 r ( x m ) = 0 自然资源与环境条件所能容纳的最大人口数为x_m,即当x=x_m时,增长率r(x_m)=0 xm,x=xm,r(xm)=0 可 得 r ( x ) = r ( 1 − x x m ) , 建 立 l o g i s t i c 人 口 模 型 : x ( t ) = x m 1 + ( x m x 0 − 1 ) e − r ( t − t 0 ) 可得r(x)=r(1-\frac{x}{x_m}),建立logistic人口模型:x(t)=\frac{xm}{1+(\frac{xm}{x0}-1)e^{-r(t-t0)}} r(x)=r(1xmx),logistic:x(t)=1+(x0xm1)er(tt0)xm

参数估计

  1. 非线性最小二乘法

把 上 表 中 的 第 1 个 数 据 作 为 初 始 条 件 , 利 用 余 下 的 数 据 拟 合 式 ( 8.23 ) 中 的 参 数 x m 和 r 把上表中的第1个数据作为初始条件,利用余下的数据拟合式(8.23)中的参数x_m 和r 1(8.23)xmr

在我的资源里面数据已经用pandas处理过Pdata8_10_1.txt.

用python进行拟合

import numpy as np
from scipy.optimize import curve_fit
a=[]; b=[];
with open("Pdata8_10_1.txt") as f:    #打开文件并绑定对象f 使用with执行文件操作不用担心资源的释放问题,python会在合适的时间将其自动释放
    s=f.read().splitlines()  #返回每一行的数据
for i in range(0, len(s),2):  #读入奇数行数据
    d1=s[i].split("\t")
    for j in range(len(d1)):
        if d1[j]!="": a.append(eval(d1[j]))  #把非空的字符串转换为年代数据
for i in range(1, len(s), 2):  #读入偶数行数据
    d2=s[i].split("\t")
    for j in range(len(d2)):
        if d2[j] != "": b.append(eval(d2[j])) #把非空的字符串转换为人口数据
c=np.vstack((a,b))  #构造两行的数组
x=lambda t, r, xm: xm/(1+(xm/3.9-1)*np.exp(-r*(t-1790))) #用匿名函数表示我们前面算出的函数表达式
bd=((0, 200), (0.1,1000))  #约束两个参数的下界和上界
popt, pcov=curve_fit(x, a[1:], b[1:], bounds=bd)
print(popt); print("2010年的预测值为:", x(2010, *popt))#*parameters表示接受一个放有多个元素的元组

输出:

[2.73527906e-02 3.42441912e+02]
2010年的预测值为: 282.67978310482215

scipy.optimize curve_fit函数

大家可以看到,整个代码中最核心的就是scipy.optimize模块中的curve_fit函数,下面我们就来详解一下它.

def curve_fit(f, xdata, ydata, p0=None, sigma=None, absolute_sigma=False,
              check_finite=True, bounds=(-np.inf, np.inf), method=None,
              jac=None, **kwargs):
    """
函数作用: Use non-linear least squares to fit a function, f, to data.

我们只研究里面几个重要的参数能够方便我们进行使用:
f:

callable
    The model function, f(x, ...).  It must take the independent
    variable as the first argument and the parameters to fit as
    separate remaining arguments.
    f就是我们需要拟合的函数 这没什么好说的,一般都是用匿名函数进行定义

xdata:

xdata : An M-length sequence or an (k,M)-shaped array for functions with k predictors
    The independent variable where the data is measured.
    可以看到x需要传入一个有k个需要预测的变量且有长度为M的数据的数组 
    而这里我们只有t,需要拟合r和xm,所以在上面代码中因为我们只能传入一个变量的数据 也就是时间t 所以我们的K是1 也就是一维数组

ydata:

ydata : M-length sequence
    The dependent data --- nominally f(xdata, ...)
    因为是函数的值(也就是y的值)所以必须是一维数组了
    需要注意的是这里的长度必须和x的长度一样,原因都懂吧

bounds

bounds : 2-tuple of array_like, optional
    Lower and upper bounds on parameters. Defaults to no bounds.
    Each element of the tuple must be either an array with the length equal
    to the number of parameters, or a scalar (in which case the bound is
    taken to be the same for all parameters.) Use ``np.inf`` with an
    appropriate sign to disable bounds on all or some parameters.
    w
    
    这里我们有几个需要拟合的参数就传入几个有两个值的数组组合成一个元组,格式就像上面的代码一样
    bd=((0, 200), (0.1,1000)) 

还有几个参数例如sigma等就是拟合的方式的问题,这个涉及到数学知识,这里我们就不多赘述.

返回值:

popt : array
    Optimal values for the parameters so that the sum of the squared
    residuals of ``f(xdata, *popt) - ydata`` is minimized
pcov : 2d array
    The estimated covariance of popt. The diagonals provide the variance
    of the parameter estimate. To compute one standard deviation errors
    on the parameters use ``perr = np.sqrt(np.diag(pcov))``.

    How the `sigma` parameter affects the estimated covariance
    depends on `absolute_sigma` argument, as described above.

    If the Jacobian matrix at the solution doesn't have a full rank, then
    'lm' method returns a matrix filled with ``np.inf``, on the other hand
    'trf'  and 'dogbox' methods use Moore-Penrose pseudoinverse to compute
    the covariance matrix.

返回值就两个,主要关注第一个

  1. f(xdata, *popt) - ydata 我们传入一个参数的数据,其返回的就是使得y最小的剩下的参数的值组成一个数组

  2. 第二个返回的协方差 同样涉及到数学知识,不多说

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值