Python数值计算(21)——非扭结点三次样条曲线

news2025/1/24 5:27:02

前面介绍到紧固和自然三次样条曲线,这次介绍一下非扭结点三次样条曲线。所谓的非扭结点,是指由于最开始的两个子区间使用插值多项式相同,最后两个子区间所使用的插值多项式也相同,这就会导致x_1,x_{n-1}在这段多项式上起不到扭结点的效果,故而得名not-a-knot。

本篇除了介绍非扭结点的三次样条曲线外,还将三种不同边界条件的三次样条进行了对比分析。

1. 数学知识

这个在前面已经做过介绍,这里再次重复说明一遍,它对我们算法实现具有很大的帮助:

同样的,a_j就是各分段起点的函数值,通过上述方程组求解出每一个c_j以后,可以把d_j,b_j计算出来。

2. 算法实现

和前面紧固,自然三次样条曲线一样,我们用一个类来实现插值算法,以及其他的方法、属性,这样就可以在后续实现方便的多值估算和绘图,事实上,核心的构造函数,只需要在原来熙然样条曲线中做少量修改即可,最终实现代码如下: 

import numpy as np
import matplotlib.pyplot as plt
from numpy.polynomial import Polynomial
from numpy import linalg
from scipy.interpolate import CubicSpline
np.polynomial.set_default_printstyle("unicode")

class kcsIntp:
    __coef=None
    __bpx=None
    __bpy=None
    def __init__(self,x:np.ndarray,y:np.ndarray):
        '''
        非扭结点三次样条曲线
        '''
        n,=x.shape
        h=np.diff(x)
        a=y.copy()
        dy=np.diff(y)
        A=np.zeros((n,n))         
        A[0,0:3]=[-h[1],h[0]+h[1],-h[0]]
        A[-1,-3:]=[-h[n-2],h[n-3]+h[n-2],-h[n-3]]
        B=np.zeros(n)
        for i in range(1,n-1):
            A[i,i-1:i+2]=[h[i-1],2*(h[i-1]+h[i]),h[i]]
            B[i]=3*dy[i]/h[i]-3*dy[i-1]/h[i-1]
        c=linalg.solve(A,B)
        d=np.zeros(n)
        b=np.zeros(n)
        for j in range(n-1):
            d[j]=(c[j+1]-c[j])/3/h[j]
            b[j]=dy[j]/h[j]-h[j]/3*(2*c[j]+c[j+1])
        self.__coef=np.array([a,b,c,d])[:,:-1].T
        self.__bpx=x.copy()
        self.__bpy=y.copy()

    def __call__(self,w):
        n,=w.shape
        ret= np.zeros(n)
        for i in range(n):
            if self.__bpx[0]>=w[i]:
                ret[i]=self.__bpy[0]
                continue
            if self.__bpx[-1]<=w[i]:
                ret[i]=self.__bpy[-1]
                continue
            j=0
            while self.__bpx[j]<w[i]:
                j+=1
            cp=self.__coef[j-1,:]
            p=Polynomial([0])
            for t in range(len(cp)):
                p+=cp[t]*Polynomial([-self.__bpx[j-1],1])**t
            ret[i]=p(w[i])
        return ret
    
    @property
    def c(self):
        '''
        如果提供的是n+1个点对,则系数是shape为(n,4)的ndarray
        每一行就是一个分段区间的参数,依次记作a,b,c,d
        则该区间的样条曲线就是y=a+b*(x-xj)+c*(x-xj)**2+d*(x-xj)**3
        其中0<=j<=n-1    
        '''
        return self.__coef
    @property
    def x(self):
        return self.__bpx

3. 算法测试

采用非扭结点三次样条插值,在[0,4]上,对函数f(x)=e^x进行拟合,假设我们知道x=0,1,2,3,4点处的函数值,以及在x=0x=4时的导数值,绘制原函数曲线,以及拟合后的曲线,代码如下:

x=np.array([0,1,2,3,4])
y=np.exp(x)
 
X=np.linspace(0,4,100)
Y=np.exp(X)
plt.plot(X,Y,'r')
 
S=kcsIntp(x,y)
Y1=S(X)
plt.plot(X,Y1,'b-.')
 
plt.grid()
plt.show()

运行效果如下:

可以看到,贴合程序较自然三次样条曲线还是要高一些,这种方式也通常是在不知道端点处的导数信息情况下,推荐的拟合方式。

4. 现有工具包

在scipy的工具包中,scipy.interpolate.CubicSpline类可以完成三次样条曲线的插值功能,构造函数原型如下:

class CubicSpline(x, y, axis=0, bc_type='not-a-knot', extrapolate=None)

其中x,y是拟合点,主要的区别是bc_type,该参数决定了边界条件,使用'not-a-knot'值时,就是非扭结点三次样条曲线,这个参数也是默认的,所实现的拟合效果与第3节中相同,可以通过系数对比确认这一点:

print(sp.c)
'''
[[ 0.48231853  0.48231853  2.66162144  2.66162144]
 [ 0.02929062  1.47624622  2.92320182 10.90806614]
 [ 1.20667268  2.71220952  7.11165756 20.94292553]
 [ 1.          2.71828183  7.3890561  20.08553692]]
'''
print(S.c)
'''
[[ 1.          1.20667268  0.02929062  0.48231853]
 [ 2.71828183  2.71220952  1.47624622  0.48231853]
 [ 7.3890561   7.11165756  2.92320182  2.66162144]
 [20.08553692 20.94292553 10.90806614  2.66162144]]
'''

同样的,系数的组织方式不同,具体细节见前两个章节。

5. 不同类型三次样条曲线的对比

前面根据三种不同边界条件,以下将三种边界条件所构造的分段多项式,对比其1阶,二阶和三阶导数。实现代码如下:

import numpy as np
import matplotlib.pyplot as plt
from numpy.polynomial import Polynomial
from numpy import linalg
from scipy.interpolate import CubicSpline

x=np.array([0,1,2,3,4])
y=np.exp(x)

spc=CubicSpline(x,y,bc_type=((1, 1), (1, np.exp(4))))
spn=CubicSpline(x,y,bc_type='natural')
spk=CubicSpline(x,y)

fig,ax=plt.subplots(2,2)
X=np.linspace(0,4,100)
Yc0=spc(X)
Yn0=spn(X)
Yk0=spk(X)
# 拟合函数
ax[0,0].plot(X,Yc0,'r')
ax[0,0].plot(X,Yn0,'g')
ax[0,0].plot(X,Yk0,'b')
ax[0,0].set_title('order-0')
ax[0,0].grid()

# 拟合函数一阶导
Yc1=spc.derivative(1)(X)
Yn1=spn.derivative(1)(X)
Yk1=spk.derivative(1)(X)
ax[0,1].plot(X,Yc1,'r')
ax[0,1].plot(X,Yn1,'g')
ax[0,1].plot(X,Yk1,'b')
ax[0,1].set_title('order-1')
ax[0,1].grid()

# 拟合函数二阶导
Yc2=spc.derivative(2)(X)
Yn2=spn.derivative(2)(X)
Yk2=spk.derivative(2)(X)
ax[1,0].plot(X,Yc2,'r')
ax[1,0].plot(X,Yn2,'g')
ax[1,0].plot(X,Yk2,'b')
ax[1,0].set_title('order-2')
ax[1,0].grid()

# 拟合函数三阶导
Yc3=spc.derivative(3)(X)
Yn3=spn.derivative(3)(X)
Yk3=spk.derivative(3)(X)
ax[1,1].plot(X,Yc3,'r')
ax[1,1].plot(X,Yn3,'g')
ax[1,1].plot(X,Yk3,'b')
ax[1,1].set_title('order-3')
ax[1,1].grid()
plt.show()

对比图如下:

上图中,红色、绿色和蓝色分别表示的是紧固、自然和非扭结点三次样条曲线,order为0~3分别表示0阶,1阶,2阶和3阶导数。可以看到:

1. 拟合曲线在一阶导数上仍旧是光滑的,在二阶导数上是连续的,但是在三阶导数上就存在跳跃了,不过,在每个子区间内,其导函数值保持恒定,这些都是三次样条曲线应该具有的基本特征。

2. 对于非扭结点三次样条曲线,可以看到在右下图中,前两个子区间的三阶导数值是相同的,而另外两种三次样条曲线则不具备这一特性。

3. 由于紧固三次样条曲线使用了更多的原函数信息,因此,其1阶,2阶的趋势基本上和原函数f(x)=e^x保持一致,而自然三次样条曲线在二阶导数中的表现是最差的,在三阶导数中也产生了较大的振动。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1977965.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

E26.【C语言】练习:打印整数二进制的奇数位和偶数位

获取一个整数二进制序列中所有的偶数位和奇数位&#xff0c;分别打印出二进制序列 要会打印奇或偶序列&#xff0c;先学会打印二进制序列 下面我的这篇文章的代码稍作修改即可 E24.【C语言】练习&#xff1a;求一个整数存储在内存中的二进制中1的个数&#xff08;两种方法&a…

一键体验Detectron2框架中的所有预训练模型

Detectron2是由Facebook AI Research (FAIR)推出的基于PyTorch的模块化物体检测库&#xff0c;发布于2019年10月10日。该平台原是2018年推出的Detectron的第二代版本&#xff0c;它完全重写于maskrcnn-benchmark&#xff0c;并采用了PyTorch语言实现。与原版相比&#xff0c;De…

(五)activiti-modeler 编辑器初步优化

最终效果: 1..首先去掉顶部的logo,没什么用,还占用空间。 修改modeler.html文件,添加样式: <style type="text/css"> #main-header{display: none; } #main{padding: 0px; } </style> 2.左边组件选择区域太宽了,一般用不到那么宽。 修改editor…

Linux驱动入门实验班day03-GPIO子系统概述

3.通用框架1——最简单方式1&#xff1a;执行命令cat /sys/kernel/debug/gpio查看串口信息 gpio4对应的下列 方式2&#xff1a; 对于按键GPIO4_14:对应第四组第14个引脚 gpiochip3 ,从96开始&#xff0c; 9614110&#xff1b;

如何获取公网IP

前言 有些时候我们需要获取电脑或者服务器的公网 IP&#xff0c;例如我们访问的目标地址需要限制 IP 白名单或者限制访问来源&#xff0c;又或者我们使用了代理&#xff0c;想试试有没有生效。要获取公网 IP 无法从电脑或服务器的本地配置中获取&#xff0c;如 ipconfig&#…

利用 Angular 发挥环境的力量

一.介绍 您是否曾想过如何在不同的环境中为同一应用设置不同的颜色、标题或 API 调用&#xff1f;可以肯定的是&#xff0c;生产 API 和测试 API 是不同的&#xff0c;应谨慎使用。部署时&#xff0c;我们不会在项目的所有地方手动更改所有 API 调用。不应这样做&#xff0c;因…

基于Yolov8面部七种表情检测与识别C++模型部署

表情识别 七种表情识别是一个多学科交叉的研究领域&#xff0c;它结合了心理学、认知科学、计算机视觉和机器学习等学科的知识和技术。 基本概念 表情的定义&#xff1a;表情是人们在情绪体验时面部肌肉活动的结果&#xff0c;是人类情感交流的基本方式之一。基本表情理论&a…

matplotlib显示opencv读取的图片颜色异常,BGR转RGB的两种方式:cv2.cvtColor与img[:,:,::-1]

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

github添加ssh密钥,通过ssh方式推送代码

左手编程&#xff0c;右手年华。大家好&#xff0c;我是一点&#xff0c;关注我&#xff0c;带你走入编程的世界。 公众号&#xff1a;一点sir&#xff0c;关注领取python编程资料 很多人在使用github的时候&#xff0c;如果还是使用https的方式推送代码的话&#xff0c;可能会…

《LeetCode热题100》---<5.①普通数组篇五道>

本篇博客讲解LeetCode热题100道普通数组篇中的五道题 第一道&#xff1a;最大子数组和&#xff08;中等&#xff09; 第二道&#xff1a;合并区间&#xff08;中等&#xff09; 第一道&#xff1a;最大子数组和&#xff08;中等&#xff09; 法一&#xff1a;贪心算法 class So…

「文件加密软件精选」13个惊艳无比的软件推荐请查收!

信息安全是企业生存与发展的基石。 一次不慎的数据泄露&#xff0c;就可能给企业带来难以估量的损失。因此&#xff0c;文件加密成为了保护企业核心资产的重要手段。 某日&#xff0c;两位员工小李和小张在茶水间闲聊&#xff1a; “你知道吗&#xff1f;最近公司开始推广文…

飞浆OCR模型训练详细教程

目录 飞浆使用文档一 环境查看1.1 Python 环境1.2 版本选择1.3 飞浆测试 二 数据集的标准备2.1 PPOCRLabelv22.1.1 安装 PaddlePaddle2.1.2 安装与运行 PPOCRLabel2.1.3 数据集划分 三 PaddleOCR 的环境搭建3.1 环境搭建3.2 模型下载 四 模型训练4.1 检测模型训练4.2 识别模型训…

萱仔环境记录——git的安装流程

最近由于我有一个大模型的offer&#xff0c;由于我只在实验室的电脑上装了git&#xff0c;我准备在自己的笔记本上本地安装一个git&#xff0c;也给我的一个师弟讲解一下git安装和使用的过程&#xff0c;给我的环境安装章节添砖加瓦。 github是基于git的一个仓库托管平台。 g…

用Python实现亚马逊Amazon高性能爬虫采集销量信息

用Python实现亚马逊Amazon高性能爬虫采集销量信息 引言 亚马逊作为全球最大的电商平台&#xff0c;拥有丰富的商品种类和庞大的用户基数。因此&#xff0c;采集亚马逊的销量信息对于市场分析、竞争对手研究以及运营优化有着重要的作用。本文将详细介绍如何用Python实现高性能的…

机械学习—零基础学习日志(高数20——洛必达法则)

零基础为了学人工智能&#xff0c;真的开始复习高数 这里讲解一个历史&#xff0c;洛必达法则其实并不是洛必达想出来的&#xff0c;洛必达整理了第一本微积分的书籍&#xff0c;是真正的知识传播者。洛必达法则是洛必达从伯努利哪里买过来的&#xff0c;并结合了莱布尼兹的论…

本地部署 Llama-3-EvoVLM-JP-v2

本地部署 Llama-3-EvoVLM-JP-v2 0. 引言1. 关于 Llama-3-EvoVLM-JP-v22. 本地部署2-0. 克隆代码2-1. 安装依赖模块2-2. 创建 Web UI2-3.启动 Web UI2-4. 访问 Web UI 0. 引言 Sakana AI 提出了一种称为进化模型合并的方法&#xff0c;并使用该方法创建大规模语言模型&#xff…

数论——线性同余方程、扩欧求解线性同余方程、线性组合、原根求解

线性同余方程 线性同余方程是形如 的方程&#xff0c;其中a 、b、m 为给定的整数&#xff0c;x 是未知整数。 扩欧求解线性同余方程 void mod_slover(int a, int b, int n) {int d, x, y, x0;d extend_gcd(a, n, x, y);if (b % d ! 0)cout << "no answer";…

联邦学习研究综述【联邦学习】

文章目录 0 前言机器学习两大挑战&#xff1a; 1 什么是联邦学习&#xff1f;联邦学习的一次迭代过程如下&#xff1a;联邦学习技术具有以下几个特点&#xff1a; 2 联邦学习的算法原理目标函数本地目标函数联邦学习的迭代过程 3 联邦学习分类横向联邦学习纵向联邦学习联邦迁移…

科普文:微服务之Spring Cloud OpenFeign服务调用调用过程分析

概叙 Feign和OpenFeign的关系 其实到现在&#xff0c;至少是2018年之后&#xff0c;我们说Feign&#xff0c;或者说OpenFeign其实是一个东西&#xff0c;就是OpenFeign&#xff0c;是2018.12 Netflix停止维护后&#xff0c;Spring cloud整合Netflix生态系统的延续。后面其实都…

ComfyUI-BrushNet(局部重绘)节点安装及效果、模型下载及详细使用方法✨

&#x1f35c;背景介绍 ComfyUI 中BrushNet的节点已经发布了三个月左右的时间了&#xff0c;后来陆续更新了更多的功能和模型接入&#xff0c;整体效果看起来还是不错的。这个节点随着能力的更新&#xff0c;接入了更多的模型&#xff0c;而每个模型默认的名字又比较相似&…