Python 数学建模——傅里叶变换时间序列分析

文章目录

    • 前言
    • 原理
    • Python 库函数实现
      • 单周期函数
      • 多周期函数
      • 真实数据挑战

前言

  在数学建模过程中,得到一个序列 x 1 , ⋯   , x n x_1,\cdots,x_n x1,,xn,我们首先要进行数据分析,其中就包括分析数据的周期性。这里的周期性不是数学上严格的周期性,即不必 x i x_i xi 严格等于 x i + T x_{i+T} xi+T,大致相等就可以。
  比如下面是 1700 − 1988 1700-1988 17001988 年间,每一年太阳黑子数量的记录图。太阳黑子数量随着时间是否有一定的周期性?

  光看图片的话,太阳黑子几乎都是在 5 5 5 年内持续增长,随后 5 5 5 年内持续下降,周而复始,大概有一个 10 10 10 年的周期。但是光肉眼看还是太主观了,有没有系统一点的办法?
  傅里叶变换是将时域数据 f ( x ) f(x) f(x) 变换到频域 F ( j ω ) F(\mathrm j\omega) F(jω) 的变换法,根据数据在频域的图象 F ( j ω ) F(\mathrm j\omega) F(jω) 的极大值,我们可以轻松看出 f ( x ) f(x) f(x) 有哪些主要的频率分量。而这些分量就对应 f ( x ) f(x) f(x) 主要的周期。
  本文主要介绍傅里叶变换时间序列分析的 Python 实现,对其原理不过多讲述,可以参考其他文献。

原理

傅里叶变换时间序列分析的用途:可以用来找时间序列的周期,或者主观地观察到了周期后,可以用这个理论验证一下。找到周期后,可以联系问题情境解释原因。如果需要用到 Prophet 的话,还可添加自定义周期性(add_seasonality,详见Python 数学建模——Prophet 时间序列预测_多变量prophet-CSDN博客)。

  傅里叶变换分为连续傅里叶变换(CFT)和离散傅里叶变换(DFT)。由于计算机中只能存储离散信号,计算 CFT 非常不方便,实际都是用的离散傅里叶变换,也称快速傅里叶变换(FFT): y k = ∑ n = 0 N − 1 e − 2 π j k n / N x n {{y}_{k}}=\sum_{n=0}^{N-1}{{{e}^{-2\pi\mathrm jkn/N}}}{{x}_{n}} yk=n=0N1e2πjkn/Nxn  其中 y 1 , ⋯   , y n y_1,\cdots,y_n y1,,yn x 1 , ⋯   , x n x_1,\cdots,x_n x1,,xn 的离散傅里叶变换。

Python 库函数实现

单周期函数

  调用 Python 库函数scipy.fft.fft, scipy.fft.fftfreq可以很好地进行傅里叶变换:

import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, fftfreq
import pandas as pd

N = 400
T = 1.0 / 1000

# 生成一个周期为 1/114 的正弦函数
x = np.linspace(0, N*T, N, endpoint = False)
y = np.sin(114 * 2 * np.pi * x)

# z 是对序列进行离散傅里叶变换的结果,abs 对复数取模
z = np.abs(fft(y))

# fftfreq 根据我们的采样周期和采样点个数,返回对应的频率值序列
# 其返回值按照 0 → 最大正数 → 最小负数 → 0 排列, [:N//2] 取前半部分(正频率)
fx = fftfreq(N, T)[:N//2]

plt.rcParams['font.family'] = 'Euclid'
plt.plot(fx,2.0 / N * z[:N//2])
plt.grid()
plt.show()

  在上面的代码中,我们生成了一个正弦函数 y = sin ⁡ ( 114 × 2 π x ) y=\sin(114\times2\pi x) y=sin(114×2πx),这个函数是一个周期为 T = 1 / 114 T=1/114 T=1/114 的周期函数,因此它具有频率 f = 114 f=114 f=114。代码中, z z z y y y 的离散序列傅里叶变换,最后作图的结果如下所示:

  可以明显地看出,在傅里叶变换之后,频谱图象有一个峰值。理论上,这个峰值对应的频率应该就是 f = 114 f=114 f=114。利用代码print(fx[np.argmax(z)])求出这个极值点是 f 0 = 115 f_0=115 f0=115

关于为什么 f 0 = 115 f_0=115 f0=115 而不是 114 114 114,这是因为程序求出来的 z z z 并不是一个函数,而是函数上的一系列函数值。这些函数值对应的横坐标间隔比较大,影响了 f f f 的精度。

多周期函数

  下面我们尝试 y = sin ⁡ ( 114 × 2 π x ) + sin ⁡ ( 514 × 2 π x ) y=\sin(114\times 2\pi x)+\sin(514\times2\pi x) y=sin(114×2πx)+sin(514×2πx),也就是两个周期函数的叠加,看看能不能同时找出这两个频率分量。

import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, fftfreq
import pandas as pd
from scipy.signal import argrelextrema
N = 500
T = 1.0 / 2500

plt.rcParams['font.family'] = 'Euclid'

# 生成一个周期 1/114 的正弦函数和 1/514 的正弦函数的叠加
x = np.linspace(0, N*T, N, endpoint = False)
y = np.sin(114 * 2 * np.pi * x) + np.sin(514 * 2 * np.pi * x)

# z 是对序列进行离散傅里叶变换的结果,abs 对复数取模
z = np.abs(fft(y))
fx = fftfreq(N, T)
lst = list(zip(fx, 2.0 / N * z))
l = len(fx)
plt.plot(fx[:l//2],2.0 / N * z[:l//2])
plt.plot(fx[l//2:],2.0 / N * z[l//2:])
plt.show()
print(fx[argrelextrema(z,np.greater,order=1)])
# [ 115.  515. -515. -115.]

  作图结果如下所示,通过print(fx[argrelextrema(z,np.greater,order=1)])得出来的极大值点也是 f 1 , 2 , 3 , 4 = 115 , 515 , − 515 , − 115 f_{1,2,3,4}=115,515,-515,-115 f1,2,3,4=115,515,515,115。负频率的出现是因为我们采用傅里叶变换的指数形式,频率值不完全与 114 , 514 114,514 114,514 重合的原因也和上面相同。

真实数据挑战

  上面两个函数都是已知周期,用傅里叶变换去验证,看看 Python 库好不好用,效果真不真。现在给出一个未知周期的函数,让傅里叶变换发挥作用。当然,我们就用之前提到的太阳黑子数据

点击下载路径,Ctrl+S下载太阳黑子数据sunspots.csv表单。

  使用太阳黑子数据sunspots.csv如上图(左)所示。认为它具有一定周期性,编写以下代码分析太阳黑子的周期性,绘制频谱图如上图(右)所示。根据图象可以得出结论,太阳黑子数量在短期内具有大概 10 10 10 天的周期性 f ≈ 0.1 f\approx0.1 f0.1,在长期内具有大概 100 100 100 天的周期性 f ≈ 0.01 f\approx0.01 f0.01

import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, fftfreq
import pandas as pd
from scipy.signal import argrelextrema


df = pd.read_csv("sunspots.csv")
y = df['counts']
y -= y.mean() # 减去均值以消去直流分量

# z 是对序列进行离散傅里叶变换的结果,abs 对复数取模
z = np.abs(fft(y.values))[:N//2]
fx = fftfreq(len(y), 1)[:N//2]
plt.plot(fx,2.0 / N * z)

plt.rcParams['font.family'] = 'Euclid'
plt.show()
# 根据图像找出最尖的那几个峰对应频率
print(fx[argrelextrema(z,lambda x,y: 2.0 / N * x > 13,order=1)])
# [0.01038062 0.08304498 0.0899654  0.10034602]

有关库函数argrelextrema的使用,参见Python 基本库用法:数学建模_数模代码库python-CSDN博客。上面最后一行代码是找出频谱图中纵坐标大于 13 13 13 的点对应的横坐标(频率)。

参考文献:
Fourier Transforms (scipy.fft) — SciPy v1.14.1 Manual
时间序列分析之:傅里叶变换找周期_傅里叶变换去数据周期-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

逆向学习系列(三)adb的使用

由于是记录学习,我就用结合自己的理解,用最通俗的语言进行讲解。 adb是android debug bridge的简写,其作用就是将电脑和手机相连接,用电脑控制手机。 一、adb哪里来 我使用的adb一般都是安装模拟器的时候,模拟器自带…

深入探索Android开发之Java核心技术学习大全

Android作为全球最流行的移动操作系统之一,其开发技能的需求日益增长。本文将为您介绍一套专为Android开发者设计的Java核心技术学习资料,包括详细的学习大纲、PDF文档、源代码以及配套视频教程,帮助您从Java基础到高级特性,再到A…

Basler 相机与LabVIEW进行集成

Basler 提供的相机驱动和 SDK (Software Development Kit) 允许用户通过 LabVIEW 对相机进行控制和图像采集。以下是 Basler 相机与 LabVIEW 集成的几种方式: 1. Baslers Pylon SDK Basler 提供的 Pylon SDK 是一套用于控制 Basler 相机的开发工具包,支…

13 Midjourney从零到商用·实战篇:漫画设计一条龙

大家好,经过前面十三篇文章,相信大家已经对Midjourney的使用非常熟悉了,那么现在我们开始进行实际的项目操作啦,想想是不是有点小激动呀,本篇文章为大家带来Midjourney在漫画制作领域的使用流程,同样也适用于现在短视频…

2024.9.12(k8s环境搭建2)

一、接9.11 19、部署calico的pod 4. 查看容器和节点状态 异常处理: 出现Init:0/3,查看node节点 /var/log/messages是否有除网络异常之外的报错信息 三台机器执行:(更新版本) yum list kernel yum update kernel reb…

基于JavaWeb开发的java+Springboot操作系统教学交流平台详细设计实现

基于JavaWeb开发的javaSpringboot操作系统教学交流平台详细设计实现 🍅 作者主页 网顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联系方式 承接…

云计算实训50——Kubernetes基础命令、常用指令

一、Kubernetes 自动补齐 # 安装自动补齐软件 [rootmaster ~]# yum -y install bash-completion # 临时开启自动补齐功能 [rootmaster ~]# source # 永 久开启自动补齐功能 [rootmaster ~]# echo "source > ~/.bashrc 二、Kubernetes 基础命令 kubectl [command] …

国产化中间件正在侵蚀开源中间件

开源中间件的发展趋势表明,它们将继续在技术创新和生态建设中发挥重要作用,尤其是在云计算、大数据等新兴技术领域。开源中间件如Apache Kafka、RabbitMQ、ActiveMQ和RocketMQ等在市场上有着广泛的应用。它们在技术社区中得到了良好的支持,并…

计算机网络30——Linux-gdb调试命令makefile

1、开始调试 编译时带-g为调试,带调试信息编译后的可执行文件更大 2、进入调试 使用gdb 可执行文件名——进入调试 失败版: 成功版: 3、l命令 l什么都不加——列出10行代码 l 行号——行号的行在中间,向上向下展示10行 4、st…

【经典文献】双边曲面去噪

文章目录 2003 TOG基本思想效果 2003 TOG 2003年,Fleishman等人在TOG上,基于图像双边滤波的思想,将其改造成了可以用在曲面上的双边滤波算法。 Fleishman S, Drori I, Cohen-Or D. Bilateral mesh denoising[M]//ACM SIGGRAPH 2003 Papers.…

Docker本地部署Chatbot Ollama搭建AI聊天机器人并实现远程交互

文章目录 前言1. 拉取相关的Docker镜像2. 运行Ollama 镜像3. 运行Chatbot Ollama镜像4. 本地访问5. 群晖安装Cpolar6. 配置公网地址7. 公网访问8. 固定公网地址 前言 本文主要分享如何在群晖NAS本地部署并运行一个基于大语言模型Llama 2的个人本地聊天机器人并结合内网穿透工具…

大模型教程:使用 Milvus、vLLM 和 Llama 3.1 搭建 RAG 应用

vLLM 是一个简单易用的 LLM 推理服务库。加州大学伯克利分校于 2024 年 7 月将 vLLM 作为孵化项目正式捐赠给 LF AI & Data Foundation 基金会。欢迎 vLLM 加入 LF AI & Data 大家庭!🎉 在主流的 AI 应用架构中,大语言模型&#xff…

基于PHP+MySQL组合开发的在线客服源码系统 聊天记录实时保存 带完整的安装代码包以及搭建部署教程

系统概述 随着互联网技术的飞速发展,企业与客户之间的沟通方式日益多样化,在线客服系统作为连接企业与客户的桥梁,其重要性不言而喻。然而,市场上现有的在线客服系统往往存在成本高、定制性差、维护复杂等问题。针对这些痛点&…

计算机毕业设计 办公用品管理系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…

基于微信小程序的食堂点餐预约管理系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于微信小程序JavaSpringBootVueMySQL的食…

计算机毕业设计 基于SpringBoot框架的网上蛋糕销售系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…

138. 随机链表的复制-LeetCode(C++)

138. 随机链表的复制 题目 给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对…

攻防世界--->re4-unvm-me

做题笔记。 下载 使用在线工具反汇编得到: 分析: 那么,关键点就是,对于md5的解密了。 使用在线工具就行: MD5 在線免費解密 MD5、SHA1、MySQL、NTLM、SHA256、SHA512、Wordpress、Bcrypt 的雜湊 (hashes.com)https://hashes.co…

Unity3D 发布后去除Development Build显示

问题描述: Build后在视野右下角看到“Development Build”白色小字 解决方法: build时不勾选Development Build项 PS: 游戏开发unity杂项知识系列:build时Development Build的作用_unity development build-CSDN博客

Golang | Leetcode Golang题解之第406题根据身高重建队列

题目&#xff1a; 题解&#xff1a; func reconstructQueue(people [][]int) (ans [][]int) {sort.Slice(people, func(i, j int) bool {a, b : people[i], people[j]return a[0] > b[0] || a[0] b[0] && a[1] < b[1]})for _, person : range people {idx : pe…