IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python 插值求包络线 -> 正文阅读

[Python知识库]python 插值求包络线

在这里插入图片描述
SciPy 是 Python 里处理科学计算 (scientific computing) 的包,使用它遇到问题可访问它的官网 (https://www.scipy.org/). 去找答案。 在使用 scipy 之前,需要引进它,语法如下:

import scipy

这样你就可以用 scipy 里面所有的内置方法 (build-in methods) 了,比如插值、积分和优化。

numpy.interpolatenumpy.integratenumpy.optimize

但是每次写 scipy 字数有点多,通常我们给 scipy 起个别名 sp,用以下语法,这样所有出现 scipy 的地方都可以用 sp 替代。

import scipy as sp

SciPy 是建立 NumPy 基础上的,很多关于线性代数的矩阵运算在 NumPy 都能做,因此就不重复在这里讲了

插值

给定一组 (xi, yi),其中 i = 1, 2, …, n,而且 xi 是有序的,称为「标准点」。插值就是对于任何新点 xnew,计算出对应的 ynew。换句话来说,插值就是在标准点之间建立分段函数 (piecewise function),把它们连起来。这样给定任意连续 x 值,带入函数就能计算出任意连续 y 值。
在 SciPy 中有个专门的函数 scipy.interpolate 是用来插值的,首先引进它并记为 spi。

import scipy.interpolate as spi

简单例子

用 scipy.interpolate 来插值函数 sin(x) + 0.5x。

基本概念

首先定义 x 和函数 f(x):

x = np.linspace(-2 * np.pi, 2 * np.pi, 11)	
f = lambda x: np.sin(x) + 0.5 * x	
f(x)
array([-3.14159265, -1.56221761, -1.29717034, -1.84442231, 
       -1.57937505, 0.         , 1.57937505, 1.84442231,
        1.29717034, 1.56221761, 3.14159265])

接下来介绍 scipy.interpolate 里面两大杀器:splrep 和 splev。两个函数名称都是以 spl 开头,全称 spline (样条),可以理解这两个函数都和样条有关。不同的是,两个函数名称以 rep 和 ev 结尾,它们的意思分别是:

  • rep:representation 的缩写,那么 splrep 其实生成的是一个「表示样条的对象」
  • ev:evaluation 的缩写,那么 splev 其实用于「在样条上估值」
    splrep 和 splev 像是组合拳 (one two punch)
  • 前者将 x, y 和插值方式转换成「样条对象」tck
  • 后者利用它在 xnew 上生成 ynew

一图胜千言:
在这里插入图片描述
接下来仔细分析一下 tck。

tck = spi.splrep( x, f(x), k=1 )	
tck

在这里插入图片描述
tck 就是样条对象,以元组形式返回,tck 这名字看起来很奇怪,实际指的是元组 (t, c, k) 里的三元素:

  • t - vector of knots (节点)
  • c - spline cofficients (系数)
  • k - degree of spline (阶数)
    对照上图,tck 确实一个元组,包含两个 array 和一个标量 1,其中
  1. 第一个 array 是节点,即标准点,注意到一开始 x 只有 11 个,但现在是 13 个,首尾都往外补了一个和首尾一样的 x
  2. 第二个 array 是系数,注意它就是 y 在尾部补了两个 0
  3. 标量 1 是阶数,因为在调用 splrep 时就把 k 设成 1
    注:前两个 array 我只是发现这个规律,但解释不清楚为什么这样。它和 matlab 里面的 spline() 的产出不太一样,希望懂的读者可以留言区解释一下。
    虽然解释不清楚前两个 array,那就把 tck 当成是个黑匣子 (black-box) 直接用了。比如可用 PPoly.from_spline 来查看每个分段函数的系数。
pp = spi.PPoly.from_spline(tck)	
pp.c.T
array([[ 1.25682673, -3.14159265],
       [ 1.25682673, -3.14159265],
       [ 0.21091791, -1.56221761],
       [-0.43548928, -1.29717034],
       [ 0.21091791, -1.84442231],
       [ 1.25682673, -1.57937505],
       [ 1.25682673, 0. ],
       [ 0.21091791, 1.57937505],
       [-0.43548928, 1.84442231],
       [ 0.21091791, 1.29717034],
       [ 1.25682673, 1.56221761],
       [ 1.25682673, 3.14159265]])

tck 的系数数组里有 13 个元素,而上面数组大小是 (12, 2),12 表示 12 段,2 表示每段线性函数由 2 个系数确定。
把 x 和 tck 丢进 splev 函数,我们可以插出在 x 点对应的值 iy。

iy = spi.splev( x, tck )	
iy

用 Matplotlib 来可视化插值的 iy 和原函数 f(x) 发现 iy 都在 f(x) 上。Matplotlib 是之后的课题,现在读者可忽略其细节。
在这里插入图片描述
在这里插入图片描述
除了可视化,我们还可以用具体的数值结果来评估插值的效果:

np.allclose(f(x), iy)	
np.sum((f(x) - iy) ** 2) / len(x)
True
0.0

第一行 allclose 的结果都是 True 证明插值和原函数值完全吻合,第二行就是均方误差 (mean square error, MSE),0.0 也说明同样结果。
上面其实做的是在「标准点 x」上插值,那得到的结果当然等于「标准点 y」了。这种插值确实意义不大,但举这个例子只想让大家
4. 明晰 splrep 和 splev 是怎么运作的
5. 如何可视化插出来的值和原函数的值
6. 如何用 allclose 来衡量插值和原函数值之间的差异

正规例子

上面在「标准点 x」上插值有点作弊,现在我们在 50 个「非标准点 xd」上线性插值得到 iyd。

xd = np.linspace( 1.0, 3.0, 50 )	
iyd = spi.splev( xd, tck )	
print( xd, '\n\n', iyd )

在这里插入图片描述
密密麻麻的数字啥都看不出来,可视化一下把。
在这里插入图片描述
在这里插入图片描述
这插得是个什么鬼?红色插值点在第二段和深青色原函数差别也太远了吧 (MSE 也显示有差异)。

np.sum((f(xd) - iyd) ** 2) / len(xd)
0.011206417290260647

问题出在哪儿呢?当「标准点 x」不密集时 (只有 11 个),分段线性函数来拟合 sin(x) + 0.5x 函数当然不会太好啦。那我们试试分段三次样条函数 (k = 3)。

tck = spi.splrep( x, f(x), k=3 )iyd = spi.splev( xd, tck )

可视化一下并计算 MSE 看看
在这里插入图片描述

np.sum((f(xd) - iyd) ** 2) / len(xd)
1.6073247177220542e-05

视觉效果好多了!误差小多了!


定义信号

import numpy as np
t = np.arange(0, 0.3, 1/20000.0)
x = np.cos(2*np.pi*1000*t) * (np.cos(2*np.pi*20*t) + np.cos(2*np.pi*8*t) + 3.0)

可视化
在这里插入图片描述
用极大值极小值方法计算信号的包络

import scipy as sp
import scipy.interpolate as spi
peak_id_up, peak_property_up = signal.find_peaks(x)
print(peak_id)
print(x[peak_id])
print(peak_property)
peak_id_down, peak_property_down = signal.find_peaks(-x)

tck_up = spi.splrep(n[peak_id_up], x[peak_id_up],k=3)
iy_up = spi.splev(n,tck_up)

tck_down = spi.splrep(n[peak_id_down],x[peak_id_down], k=3)
iy_down = spi.splev(n,tck_down)

plt.plot(x ,'k')
plt.plot(nt[peak_id_up], x[peak_id_up], 'ro')
plt.plot(nt[peak_id_down],x[peak_id_down],'go')
plt.plot(nt, iy_up,'r-',label = 'up')
plt.plot(nt,iy_down,'g-',label ='down')
plt.legend()
# plt.plot(y_new)

在这里插入图片描述

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-03-24 00:30:34  更:2022-03-24 00:31:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 20:56:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码