首页/文章/ 详情

matlab实现泰勒级数&傅里叶级数拟合

4月前浏览8013

 本文摘要(由AI生成):

本文讨论了泰勒公式和傅里叶级数的区别与联系。泰勒公式用于描述简单函数的局部性质,但对于复杂函数则无法完全替代原函数。文章通过实战案例比较了泰勒级数和傅里叶级数在表示同一函数时的差异,展示了傅里叶级数在表示其他函数时的功能。文章强调了级数与多项式的区别,并指出级数替代函数的形式不是唯一的,傅里叶级数是一种特殊形式的函数展开。


    What is taylor formula?

    泰勒中值定理:若函数f(x)在含有x0的某个开区间内具有直到(n 1)阶的导数,那么对于任一x∈(a,b),有:

图片

ζ为x0与x之间的某个值,f(x)称为n阶泰勒公式,其中:

图片

称为n次泰勒多项式,它与f(x)的误差:

图片

称为泰勒余项。

    通俗地讲解,泰勒公式也称泰勒展开式。是用一个函数在某点的信息,描述其附近取值的公式。如果函数足够平滑,在已知函数在某一点的各阶导数值的情况下,泰勒公式可以利用这些导数值来做系数,构建一个多项式近似函数,求得在这一点的邻域中的值。

    泰勒公式的实际应用就是用一个多项式函数去逼近一个给定的函数(即尽量使多项式函数图像拟合给定的函数图像),注意,逼近的时候一定是从函数图像上的某个点展开。如果一个非常复杂函数,想求其某点的值,直接求无法实现,这时候可以使用泰勒公式去近似的求该值,这是泰勒公式的应用之一。泰勒公式在机器学习中主要应用于梯度迭代。

    过冷水在学习过程中曾经出现过一个误解,“认为多项式拟合思想是基于泰勒公式”this is error!

多项式拟合是用一个多项式展开去拟合包含数个分析格点的一小块分析区域中的所有观测点,得到观测数据的客观分析场。展开系数用最小二乘拟合确定。

    泰勒公式多项式系数由逼近点导数确定,泰勒公式是从某一点展开,即时假设该点是原点也不可以认为是多项式拟合。拟合&和逼近,喜欢抠字眼的人能够给你讲的很清楚。

    多项式一般是用于拟合一些列点尽可能的让点落在多项表示的函数上,泰勒公式是用多项式表示一个函数式,可用于求解数值积分。过冷水之前的一篇推文就把这个概念给弄混了。

现在给实际演示一下,用两种不同方法表示下例函数:

    可以看出三种方法计算的积分值相近,这也说明了Monte Carlo的两种不同计算路径得到的计算值都是可信的。学习的越是深入才能更加清晰的感受到自己所了解的知识的浅薄程度,如果有人问我如何衡量Monte Carlo方法的计算精度,昨天的我会说用平方来比较啊!今天的我就不会这么说,我会给你普及置信区间的概念。和你聊置信水平。这就是日日学习,日日精进。今天学一点Monte Carlo,明天学一点正态分布的评估方法,菲尔兹将指日可待 

    上述过过程实际展现了求平均数的两种不同表述方法。两个公式自然而然就联系起来了,用一个公式计算另一个公式的相关参数。这个过程你都感觉不到统计力学的身影,这就是Monte Carlo的另一种思想。

    过冷水之前以为的Monte Carlo算法是通过随机撒点求所求区域占规则形状的面积比值然后用规则面积*比值即为所求面积面积。我们来实战演示一下两种思路求积分的具体过程。

图片

图片

计算结果:

图片

syms x
f1=((x.^4.*exp(x))./(exp(x)-1).^2);
%泰勒公式在0点展开
f2=taylor(f1,x,'ExpansionPoint',0,'Order',7);
%在五点展开
f3=taylor(f1,x,'ExpansionPoint',5,'Order',7);
%泰勒公式在8点展开
f4=taylor(f1,x,'ExpansionPoint',8,'Order',7);
%多项式拟合
x=linspace(0.1,10,100);
y1=(x.^4.*exp(x))./(exp(x)-1).^2;
p=polyfit(x,y1,6);
f5= p(1)*x.^6   p(2)*x.^5   p(3)*x.^4  p(4)*x.^3   p(5).*x.^2   p(6).*x p(7);
figure1 = figure;
% 创建 subplot1
subplot1 = subplot(2,3,1,'Parent',figure1);
hold(subplot1,'on');
h1=ezplot(f1,[0,10]);
set(h1,'Color','r','LineWidth',2);
text('Parent',subplot1,'FontSize',12,'Interpreter','latex','String',' $f_1=\frac{{x}^{4} {exp}({x})}{({exp}({x}) - {1})^{2}}$','Position',[2.04663212435233 0.642142934709296 0]);
xlabel('{x}');
title('原函数');
xlim(subplot1,[0 10]);
ylim(subplot1,[-0.503063977246079 5.39061349763272]);
box(subplot1,'on');
set(subplot1,'LineWidth',1.5);
% 创建 subplot2
subplot2 = subplot(2,3,2,'Parent',figure1);
hold(subplot2,'on');
h2=ezplot(f2,[0,10]);
set(h2,'Color','b','LineWidth',2);
xlabel('$$f_2=f(0) f^{1}(0)x ...\frac{f^{7}(0)x^7}{7!}$$','Interpreter','latex');
title('泰勒公式x_0=0,七次展开');
text(5,2,' 2');
xlim(subplot2,[0 10]);
ylim(subplot2,[-174.382571609797 2791.21109645392]);
box(subplot2,'on');
set(subplot2,'LineWidth',1.5,'ZGrid','on');
% 创建 subplot3
subplot3 = subplot(2,3,3,'Parent',figure1);
hold(subplot3,'on');
h3=ezplot(f3,[0,10]);
set(h3,'Color','g','LineWidth',2);
xlabel('$$f_3=f(5) f^{1}(5){(x-5)} ...\frac{f^{7}(5){(x-5)^7}}{7!}$$','Interpreter','latex');
title('泰勒公式x_0=5,7次展开');
text(5,2,' 1');
xlim(subplot3,[0 10]);
ylim(subplot3,[0.921374829561043 5.28031508945495]);
box(subplot3,'on');
set(subplot3,'LineWidth',1.5);
% 创建 subplot4
subplot4 = subplot(2,3,4,'Parent',figure1);
hold(subplot4,'on');
h4=ezplot(f4,[0,10]);
set(h4,'Color','c','LineWidth',2);
xlabel('$$f_4=f(8) f^{1}(8){(x-8)} ...\frac{f^{7}(8){(x-8)^7}}{7!}$$','Interpreter','latex');
title('泰勒公式x_0=8七次展开');
xlim(subplot4,[0 10]);
ylim(subplot4,[-26.6703291235615 6.65080265872201]);
box(subplot4,'on');
set(subplot4,'LineWidth',1.5);
% 创建 subplot5
subplot5 = subplot(2,3,5,'Parent',figure1);
hold(subplot5,'on');
plot(x,f5,'Parent',subplot5,'LineWidth',2,'Color',[0 0 0]);
text('Parent',subplot5,'Interpreter','latex','String','$$f5=p_1x^6 ....p_6x^1 p_7$$','Position',[1.58031088082902 0.571428571428571 0]);
title('多项式六次拟合');
text(5,2,'5');
box(subplot5,'on');
set(subplot5,'LineWidth',1.5);
% 创建 subplot6
subplot6 = subplot(2,3,6,'Parent',figure1);
hold(subplot6,'on');
plot(x,f5,'Parent',subplot6,'LineWidth',2,'Color',[0 0 0]);
h3=ezplot(f3,[0,10])
set(h3,'Color','g','LineWidth',2)
h1=ezplot(f1,[0,10])
set(h1,'Color','r','LineWidth',2)
xlabel('{x}');
title('多项式、泰勒公式比较');
xlim(subplot6,[0 10]);
ylim(subplot6,[0.921374829561043 5.28031508945495]);
box(subplot6,'on');
set(subplot6,'LineWidth',1.5);

    计算可知多项式能够很好的替换原函数,泰勒公式在三个点处,用七次展开都不能很好的吻合原函数,是不是泰勒公式不好啊?我做的判断能够表示实际结果吗?我又做了如下工作:

图片

源代码:

syms x
f1=(x.^4.*exp(x))./(exp(x)-1).^2;
%泰勒公式在0点展开
f2=taylor(f1,x,'ExpansionPoint',0,'Order',7);
%泰勒公式在5点展开
f3=taylor(f1,x,'ExpansionPoint',5,'Order',10);
%多项式拟合
x=linspace(-50,50,500);
y1=(x.^4.*exp(x))./(exp(x)-1).^2;
p=polyfit(x,y1,10);
f4=p(1)*x.^10 p(2)*x.^9 p(3)*x.^8   p(4)*x.^7   p(5)*x.^6  p(6)*x.^5   p(7).*x.^4  p(8)*x.^3 p(9)*x.^2 p(10)*x.^1   p(11);
figure1 = figure;
axes1 = axes('Parent',figure1);
hold(axes1,'on');
h1=ezplot(f1,[-50,50]);
set(h1,'Color','r','LineWidth',2,'DisplayName','$$f_1=\frac{{x}^{4} {exp}({x})}{({exp}({x}) - {1})^{2}}$$');
h2=ezplot(f2,[-50,50]);
set(h2,'Color','b','LineWidth',2,'DisplayName','$$f_2=f(0) f^{1}(0)x ...\frac{f^{7}(0)x^7}{7!}$$');
h3=ezplot(f3,[-50,50]);
set(h3,'Color','g','LineWidth',2,'DisplayName','$$f_3=f(5) f^{1}(5){(x-5)} ...\frac{f^{10}(5){(x-5)^10}}{10!}$$');
% 创建 plot
plot(x,f4,'DisplayName','$$f_4=p_1x^{10} ....p_{10}x^1 p_{11}$$','LineWidth',2,'Color',[0 0 0]);
xlabel('{x}');
title('多项式拟合和泰勒级数展开比较');
xlim(axes1,[-50 50]);
ylim(axes1,[-1 6]);
box(axes1,'on');
set(axes1,'FontSize',14,'LineWidth',2);
legend1 = legend(axes1,'show');
set(legend1,'Position',[0.637438496065231 0.676591289840403 0.2


    由图可知:当扩大函数区间,多项式拟合就不太适用于该函数。说明了多项式拟合的局限性。泰勒展开式式在某一点附近展开,局部符合程度比较好,随着远离展开点,符合情况较差。

    两种方法各优缺点。不能一有问题就想到多项式拟合,多项式拟合是不能代替原函数或者某种变化趋势的。泰勒公式也只是能够描述简单函数,对于复杂的函数就也不能做到替换原函数,不知道详情的我之前一直以为泰勒公式是可以做到任意替换的,至少理论上是,实际是理论上都不是,这里需要注意的是不同点展开的函数是不一样的。

    过冷水本打算用另一种基数展开式来藐视泰勒级数展开式的局限性的,奈何案例函数太复杂,求不出不出来展开式系数。所以上述案例就没放。

    傅里叶变化大家听得很多,但提到傅里叶级数就不一定了解了,为什么大家一致搞不懂傅里叶变化是什么?因为没搞懂什么是傅里叶级数。过冷水现在就带你弄明白什么是傅里叶级数。傅里叶级数是一种特殊形式的函数展开。一个函数按泰勒展开时,基底函数取1、x2、x3而傅里叶级数展开时基底函数取1,cosx、sinx,cos2x、sin2x.....cosnx、sinnx,傅里叶级数一般情况下表示为:

图片

我们看一个实战案例:

图片

图片

syms x
f1=x*(x-pi)*(x-2*pi);
f2=taylor(f1,x,'ExpansionPoint',0,'Order',7);
[an,bn,f]=fseries(fx,x,12,0,2*pi);%前12项展开
f3=latex(f);%将f转换成latex代码
figure1 = figure;
axes1 = axes('Parent',figure1);
hold(axes1,'on');
h1=ezplot(f1,[0,2*pi]);
set(h1,'LineWidth',4,'LineStyle',':','Color',[1 0 0],'DisplayName','$$f_1=\frac{{x}^{4} {exp}({x})}{({exp}({x}) - {1})^{2}}$$');
h2=ezplot(f2,[0,2*pi]);
set(h2,'LineWidth',3, 'Color',[0 0 1],'DisplayName','$$f_2=f(0) f^{1}(0)x ...\frac{f^{7}(0)x^7}{7!}$$');
h3=ezplot(f,[0,2*pi]);
set(h3,'LineWidth',1,'Color',[0.929411768913269 0.694117665290833 0.125490203499794],'DisplayName','$$f_3=a_0 \sum_{n=1}^{12}{(a_ncosx b_nsinnx)}$$');
xlabel('{x}');
title('傅里叶级数和泰勒级数展开比较');
xlim(axes1,[-2 8]);ylim(axes1,[-10 14]);
box(axes1,'on');
set(axes1,'FontSize',14,'LineWidth',2);
legend1 = legend(axes1,'show');
set(legend1,'Interpreter','latex');

傅里叶级数函数

function [an,bn,f]=fseries(fx,x,n,a,b)
%傅里叶级数展开
%an为fourier余弦项系数
%bn为fourier正弦项系数
%f为展开表达式
if nargin==3
    a=-pi;
    b=pi;
end
l=(b-a)/2;
if a b
    fx=subs(fx,x,x l a);
end
an=int(fx,x,-l,l)/l;
bn=[];
f=an/2;
for ii=1:n
    ann=int(fx*cos(ii*pi*x/l),x,-l,l)/l;
    bnn=int(fx*sin(ii*pi*x/l),x,-l,l)/l;
    an=[an,ann];
    bn=[bn,bnn];
    f=f ann*cos(ii*pi*x/l) bnn*sin(ii*pi*x/l);
end
if a b
    f=subs(f,x,x-l-a);
end

    用两种不同的级数表示原函数表示,结果较好。说明傅里叶级数表达式有表示其它函数的功能,本期推文过冷水通过复习泰勒级数让大家知道级数和多项式的区别,以及级数替代函数的形式的级数类型不是唯一的。


代码&命令MATLAB求解技术理论科普
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2021-04-30
最近编辑:4月前
过冷水
博士 | 讲师 讨论号:927550334
获赞 359粉丝 183文章 107课程 11
点赞
收藏
作者推荐

¥5 5.0
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习 福利任务 兑换礼品
下载APP
联系我们
帮助与反馈