我的首个python的合集啊~~  完全给自己看啊 不喜喷了也不里你

一、一维插值

对现有数据进行拟合或插值是数学分析中常见的方式。

  • 通过分析现有数据,得到一个连续的函数(也就是曲线);或者更密集的离散方程与已知数据互相吻合,这个过程叫做拟合
  • 通过已知的、离散的数据点,在范围内推求新数据点的过程或方法则叫做插值

简单来说,插值与拟合最大的区别就是,插值所获得的曲线一定要通过数据点,而拟合需要的是总体上最接近的结果。

python合集1_ci

所以说要实现插值算法,我们的目标是通过给定的x值和y值,创建一个函数y=f(x),可以在该函数中插入想要的任何值a并获得相应的值y=f(a)。

例如给定x=[0:5:5],y=x^2,在python中画出散点图为

import numpy as np
import matplotlib.pyplot as plt
x_data = np.linspace(0,5,5)
y_data = x_data**2
plt.scatter(x_data,y_data)
plt.show()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

python合集1_拟合_02

 假如我们想获取x=2的值,可以看到图中没有对应的数据点,因此无法直接获得,所以需要用到插值,而最简单的插值方式为线性插值,就是通过直线连接数据点。

python合集1_插值_03

这样通过scipy.interpolate.interp1d()的函数即可进行一维插值。

from scipy.interpolate import interp1d
x_data = np.linspace(0,5,5)
y_data = x_data**2
y_f = interp1d(x_data, y_data, 'linear')
print(y_f(2))
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

通过上述代码使用线性插值,运行代码后求出x=2时y的值为4.375,由于线性插值是通过相邻两点的连线来进行插值,无法考虑到其他数据点,我们都知道x=2时y=x^2的值为4,这里的插值结果明显有问题。

于是使用2次多项式的方式进行插值,可以得到y(2)=4

y_f = interp1d(x_data, y_data,'quadratic')
x = np.linspace(0,5,100)
y = y_f(x)
plt.plot(x,y,'--')
plt.show()
print(y_f(2))
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

python合集1_插值_04

上述案例的数据较为简单,我们可以轻易地判断插值后的数据是否准确,但是对于复杂的数据,选择合适的插值方式就变得十分重要。 

 

二、二维插值

一维插值就是一维插值就是给出y=f(x)上的点(x1,y1),(x2,y2),…,(xn,yn),由此求出y=f(x)在点xa处的值ya的值。

在此基础上进行扩展,二维插值就是给出z=f(x,y)上的点(x1,y1,z1),…,(xn,yn,zn),由此求出在(xa,ya)处求出za的值。

使用Scipy中的interpolate.interp2d函数可以实现二维插值。

class scipy.interpolate.interp2d(x, y, z, kind='linear', copy=True, 
bounds_error=False, fill_value=None)
  • 1.
  • 2.

定义数据点坐标的数组。如果这些点位于规则网格上,x 可以指定列坐标,y 可以指定行坐标,例如:

x = [0,1,2];  y = [0,3]; z = [[1,2,3], [4,5,6]]
  • 1.

否则,x 和 y 必须指定每个点的完整坐标,例如:

x = [0,1,2,0,1,2];  y = [0,0,0,3,3,3]; z = [1,4,2,5,3,6]
  • 1.

如果 x 和 y 是多维的数组,则会在使用前将它们展平。

我们使用以下代码绘图进行示例:

import numpy as np
from scipy.interpolate import interp2d
import matplotlib.pyplot as plt
x = np.linspace(0, 4, 13)
y = np.array([0, 2, 3, 3.5, 3.75, 3.875, 3.9375, 4])
X, Y = np.meshgrid(x, y)
Z = np.sin(np.pi*X/6) * np.exp(Y/3)
x2 = np.linspace(0, 4, 65)
y2 = np.linspace(0, 4, 65)
f1 = interp2d(x, y, Z, kind='cubic')
Z2 = f1(x2, y2)
f2 = interp2d(x,y,Z,kind='linear')
Z3 = f2(x2,y2)
fig, ax = plt.subplots(nrows=1, ncols=3)
ax[0].pcolormesh(X, Y, Z,cmap='rainbow')
X2, Y2 = np.meshgrid(x2, y2)
ax[1].pcolormesh(X2, Y2, Z2,cmap='rainbow')
X3, Y3 = np.meshgrid(x2, y2)
ax[2].pcolormesh(X3, Y3, Z3,cmap='rainbow')
ax[0].set_title('origin')
ax[1].set_title('cubic')
ax[2].set_title('linear')
plt.show()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

可以通过图片对比各插值方式的区别。

python合集1_插值_05

 

三、几种一维插值方式对比

使用python的scipy库可进行一维插值,并且对比了线性(linear)和二次多项式(quadratic)两种方法,这里主要来介绍一下scipy.interpolate.interp1d函数的其他插值选项。

首先,interp1d函数由以下部分所组成

class scipy.interpolate.interp1d(x, y, kind='linear', axis=- 1, 
copy=True, bounds_error=None,fill_value=nan, assume_sorted=False)
  • 1.
  • 2.
  • x为一维数组
  • y可以是N维数组,但y 沿插值轴的长度必须等于 x 的长度
  • kind表示插值的方式(默认为‘linear’),包括 ‘linear’, ‘nearest’, ‘nearest-up’, ‘zero’, ‘slinear’, ‘quadratic’, ‘cubic’, ‘previous’, or ‘next’.
    “zero”、“linear”、“quadratic”和“cubic”是指零、一、二或三阶的样条插值;
    ‘previous’ 和 ‘next’ 只是返回该点的上一个或下一个值
    'nearest-up' 和 'nearest' 在对半整数(例如 0.5、1.5)进行插值时有所不同,“nearest-up”向上取整,“nearest”向下取整。
  • axis用于指定沿其进行插值的 y 轴。默认为最后一个y轴。
  • copy(布尔类型)如果为 True,则该类函数创建 x 和 y 的内部副本。如果为 False,则使用对 x 和 y 的引用。默认是True。
  • bounds_error(布尔类型)如果为 True,则在任何时候尝试对 x 范围之外的值进行插值时都会引发 ValueError(需要外插)。如果为 False,则为越界值分配 fill_value。默认情况下会报错,除非fill_value="extrapolate"。
  • fill_value,如果是 ndarray(或浮点数),则此值将用于填充数据范围之外的请求点。如果未提供,则默认值为 NaN。类数组必须正确广播到非插值轴的尺寸。如果是双元素元组,则第一个元素用作 x_new < x[0] 的填充值,第二个元素用于 x_new > x[-1]。任何不是 2 元素元组的东西(例如,列表或 ndarray,无论形状如何)都被视为一个类似数组的参数,用于两个边界,如下所示,上面 = fill_value,fill_value。使用二元素元组或 ndarray 需要 bounds_error=False。

我们使用下述代码绘图进行对比


import numpy as np
from scipy.interpolate import interp1d
import pylab
A, nu, k = 10, 4, 2
def f(x, A, nu, k):
    return A * np.exp(-k*x) * np.cos(2*np.pi * nu * x)
xmax, nx = 0.5, 8
x = np.linspace(0, xmax, nx)
y = f(x, A, nu, k)
f_nearest = interp1d(x, y,'nearest')
f_linear  = interp1d(x, y,'linear')
f_cubic   = interp1d(x, y,'cubic')
f_next    = interp1d(x, y, 'next')
x2 = np.linspace(0, xmax, 100)
pylab.plot(x, y, 'o', label='data points')
pylab.plot(x2, f(x2, A, nu, k), label='exact')
pylab.plot(x2, f_nearest(x2), label='nearest')
pylab.plot(x2, f_linear(x2), label='linear')
pylab.plot(x2, f_cubic(x2), label='cubic')
pylab.plot(x2, f_next(x2), label='next')
pylab.legend(loc=1)
pylab.show()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.

python合集1_拟合_06

可以通过上图对比各插值方式与原函数(exact)的曲线区别。

 

四、曲线拟合

在处理数据时经常需要进行曲线拟合,在拟合过程中我们采用了插值的思想。

对于给定的数据x=[...]和y=[...],插值的目的是找到参数β的最优集合,使函数

python合集1_ci_07

能够与原数据最为相似。

  • 其中一种方法是通过调整β使:

  • 能够最小化,这种方法称之为最小二乘法。
  • 如果yi的值有相应的误差,那么使下式最小化
  • 称之为β的最大似然估计。在给定xi与yi的情况下,这样得到的β值最为准确。

我们给定以下随机数据点并绘制散点图:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy.optimize import curve_fit
x_data = np.array([0.        , 0.15789474, 0.31578947, 0.47368421, 0.63157895,
       0.78947368, 0.94736842, 1.10526316, 1.26315789, 1.42105263,
       1.57894737, 1.73684211, 1.89473684, 2.05263158, 2.21052632,
       2.36842105, 2.52631579, 2.68421053, 2.84210526, 3.        ])
y_data = np.array([  2.95258285,   3.49719803,  -2.1984975 ,  -4.88744346,
        -7.41326345,  -8.44574157, -10.01878504, -13.83743553,
       -12.91548145, -16.41149046, -14.93516299, -13.42514157,
       -14.12110495, -17.6412464 , -16.1275509 , -17.11533771,
       -15.66076021, -12.48938865, -11.33918701, -11.70467566])
plt.scatter(x_data,y_data)
plt.show()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

python合集1_python_08


 我们使用下式的模型进行拟合:

python合集1_python_09

我们需要求解出符合上述数据点的最优的a、b、c的值,需要在python中:

(1)需要定义模型方程;

(2)使用scipy库中的curve_fit函数,使用该函数时需要定义一个β的初始值,对于一些复杂的模型,初始值决定了函数能否顺利运算。

下面定义函数并进行拟合

def fitfun(x, a, b, c):
    return a*(x-b)**2 + c
popt, pcov = curve_fit(fitfun, x_data, y_data, p0=[3,2,-16])
  • 1.
  • 2.
  • 3.

其中:

popt为我们定义的函数fitfun的最佳参数。

pcov为协方差矩阵,用于给定误差。

接下来我们就可以绘制出拟合好的曲线

a, b, c = popt
x_model = np.linspace(min(x_data), max(x_data), 100)
y_model = fitfun(x_model, a, b, c)
plt.scatter(x_data,y_data)
plt.plot(x_model,y_model, color='r')
plt.show()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

python合集1_ci_10