资讯动态

CC算法同时估计延迟时间与嵌入维数:混沌时间序列重构的Matlab实现

发布时间:2026/9/10 4:22:11 来源:尧图企业网站定制
简介面向使用Matlab开展混沌时间序列相空间重构的本硕博学生与科研人员这份仿真资源包围绕CC算法求解延迟时间与嵌入维数这一关键问题提供可直接运行的仿真代码及配套演示录像。rar压缩包共含8个文件以6个m文件构成主运行脚本与多个子函数分别实现关联积分、S_ave与S_cor统计量计算并结合Lorenz混沌系统示例验证算法辅以txt说明文件和avi操作录像整包仅338KB部署轻量。已有802人浏览学习适用于课程设计、毕业设计以及科研入门便于自主仿真练习或课堂辅助教学。通过观看操作录像并运行主脚本可快速掌握在Matlab 2021a及以上环境中的正确运行方式逐步理解CC算法求延迟时间和嵌入维数的统计构造与计算流程文件结构清晰主脚本与子函数分离方便按模块阅读与二次开发为后续相空间重构和混沌预测研究提供扎实基础。1. 用CC算法同时定出延迟时间与嵌入维为什么比自相关法和假近邻法更省事做混沌时间序列预测时第一步通常是相空间重构而重构质量几乎完全由延迟时间τ和嵌入维数m决定。自相关函数能给出τ但和嵌入维数完全脱钩假近邻法能算m却对噪声敏感、计算量也不小。CC算法C-C方法用关联积分构造统计量在一条时间序列上同时估计τ和时间窗τ_w(m-1)τ省掉两套方法之间的手工对齐。这套Matlab工程给出了从Lorenz系统生成数据、计算统计量到绘制三条判定曲线的完整链路还带操作录像适合需要把Takens嵌入定理落到实验数据上的本科生、研究生和做信号分析与预测的工程师。阅读前需要理解三件事什么是关联积分、三个统计量的几何含义、以及为什么最优τ在S_avg第一个零点和ΔS_avg第一个极小值之间。2. 关联积分与统计量S(m,N,r,t)CC算法的理论底座2.1 为什么自相关和假近邻法会打架自相关函数度量的是线性相关性。对Lorenz这类强非线性系统x(t)与x(tτ)的线性相关系数会快速衰减到接近零取第一次过零或跌到1/e的位置作为τ得到的往往是一个偏小的值。结果就是重构出的轨道还没有充分展开点云挤在对角线附近。假近邻法从几何角度找m它检查嵌入维增加时哪些近邻关系是“假”的问题在于阈值Rt和A设多少没有统一标准不同阈值给出的m差别很大。CC算法的思路是把这两个问题合并成一个先找延迟时间窗τ_w再从τ_w倒推m。这样两条曲线之间的主观对齐就消失了替换成一套统计量的极值判读规则。需要明确的是CC算法的代价是计算量。它对每一个候选t都要计算多个m和r下的关联积分复杂度大约是O(Tmax × 4 × nr × N²)N是序列长度。这套包里的correlative_integral.m就是整个工程的性能瓶颈后面章节会绕回来讲它怎么优化。2.2 关联积分C(m,N,r,t)的定义与计算关联积分度量的是重构后的m维相空间里两点距离小于r的比例。形式化地说C(m,N,r,t) 2 / (N_t(N_t−1)) × Σ_{ij} H(r − ||X_i − X_j||)其中H是Heaviside阶跃函数X_i是延迟向量。范数的选择有讲究CC算法原始论文里用的是最大模sup norm因为最大模在低维下计算快且对r的依赖更平滑不容易出现欧氏距离下关联积分为零的稀疏区间。实现上不复杂但双层求和很容易写慢。function C correlative_integral(xs, m, r, t) % xs已经标准化的时间序列 % m嵌入维数 % r距离阈值 % t时间间隔同时也是延迟步长 N length(xs); idx 1 : t : N - (m-1)*t; % 保证最后一个延迟向量不越界 n length(idx); if n 2 C 0; return; end X zeros(n, m); % 相空间矩阵每行是一个延迟向量 for k 1:m X(:, k) xs(idx (k-1)*t); end cnt 0; total n * (n-1) / 2; for i 1:n-1 d max(abs(X(i1:n, :) - X(i, :)), [], 2); % 最大模距离 cnt cnt sum(d r); end C cnt / total; end这里把xs拆成n个m维延迟向量循环里对每个参考点i计算它和后续所有点的最大模距离。total就是点对数n(n−1)/2这一步是标准组合数公式。注意在这里t同时承担了两个角色一方面用于生成子序列的采样间隔另一方面又作为延迟步长参与向量构建。r的单位和xs保持一致因此建议先把xs标准化成零均值单位方差这样r取σ的倍数时数值稳定。2.3 三个统计量的构造与判读给定t后CC方法把原始序列按起始位置拆成t个子序列然后对每个子序列计算关联积分再跨子序列平均。在此基础上构造几个统计量。下表把这套包的三个核心输出整理清楚统计量构造要点判读规则估计参数S_avg(t)在m2…5、rσ/2…2σ范围内平均S(m,N,r,t)第一个零点延迟时间τΔS_avg(t)S对r的最大值与最小值之差再对m取平均第一个局部极小值延迟时间τS_cor(t)S_avg(t) ΔS_avg(t)全局最小值时间窗τ_w(m−1)τ我一般先找ΔS_avg的第一个极小值作为τ。如果S_avg的第一个零点位置和它差得不超过2个采样点那就更放心。τ_w由S_cor取全局最小的那个t给出嵌入维数m round(τ_w / τ 1)。如果两个τ位置打架以ΔS_avg的极小值为准因为零点对噪声更敏感容易提前穿越。得到m后还要再想想CC算法给出的m是“上界意义上的推荐值”它依赖时间窗如果τ_w本身估计偏小m也会被压低。所以实操里我会把CC算法的m作为初值再和假近邻法交叉验证一次。3. Matlab工程结构拆解从Lorenz时间序列到Runme_CCMethod.m3.1 文件清单与调用关系这套工程的核心文件不多但函数之间的调用链很容易看乱先给一张清单文件角色被谁调用Runme_CCMethod.m主入口组织整个计算流程并绘图手动运行LorenzDifEqn1.m生成Lorenz系统x分量时间序列Runme_CCMethod.mCal_S_ave.m对t1…T_max逐点计算三个统计量序列Runme_CCMethod.mCal_S.m给定单个t计算该t下的S_avg和ΔS_avgCal_S_ave.mcorrelative_integral.m计算关联积分C(m,N,r,t)Cal_S.mCal_psd.m计算功率谱密度辅助判断主周期手动调用fpga和matlab.txt记录定点化移植的要点备忘阅读Cal_S.m被Cal_S_ave.m套在循环里correlative_integral.m又被Cal_S.m套在多层循环里。这个三层嵌套决定了运行时间对Tmax极其敏感。3.2 Runme_CCMethod.m的主流程骨架主脚本的逻辑不复杂核心是对t从1扫描到Tmax然后从统计量曲线里定位极值点。% Runme_CCMethod.m 主流程骨架 clear; close all; clc; N 5000; % 时间序列长度太小统计涨落大 x LorenzDifEqn1(N); % 生成Lorenz x分量序列 x (x - mean(x)) / std(x); % 标准化r的取值有了统一参考 Tmax 200; % 最大滞后时间经验取N/10量级 s_avg zeros(1, Tmax); ds_avg zeros(1, Tmax); for t 1:Tmax [s_avg(t), ds_avg(t)] Cal_S_ave(x, t); end sc_avg abs(s_avg) ds_avg; tau1 find(s_avg(2:end) .* s_avg(1:end-1) 0, 1); % 零点相邻变号 tau2 min(find(diff(ds_avg) 0)); % 第一个极小值 [~, I] min(sc_avg); tw I; % S_cor全局最小 m round(tw / tau2 1); fprintf(tau %d, m %d, tw %d\n, tau2, m, tw);代码里tau1和tau2分别是两条曲线的判读结果实际打印时我会把tau1也打出来对照。find(s_avg(2:end).*s_avg(1:end-1)0,1)是在找相邻两个点的乘积首次变负的位置等价于过零。diff(ds_avg)0第一次出现的位置对应曲线从下降转上升的那个点也就是极小值。这里有个边界问题第一个极小值如果出现在t1基本属于序列太短或噪声太大需要增加N而不是继续调参数。3.3 Lorenz系统数据生成LorenzDifEqn1.m这个函数生成的是标准Lorenz吸引子的x分量。Lorenz系统状态方程是dx/dtσ(y−x)、dy/dtx(ρ−z)−y、dz/dtxy−βz。经典参数组合有两套一套是σ10、ρ28、β8/3另一套是σ16、ρ45.92、β4。CC算法原始论文里用后者做过验证因为吸引子折叠更明显。包里具体用哪套参数打开函数就看得到这里给出一个兼容写法function x LorenzDifEqn1(N, dt) % N输出序列长度 % dt数值积分步长 if nargin 2, dt 0.01; end x zeros(1, N); y zeros(1, N); z zeros(1, N); sigma 16; rho 45.92; beta 4.0; % 经典C-C验证参数 x(1) 1; y(1) 1; z(1) 1; for k 1:N-1 x(k1) x(k) sigma*(y(k)-x(k))*dt; y(k1) y(k) (x(k)*(rho-z(k))-y(k))*dt; z(k1) z(k) (x(k)*y(k)-beta*z(k))*dt; end end这里用的是欧拉积分精度一般但生成统计量用足够了。如果发现生成的序列发散发散第一步不是改算法而是把dt从0.01降到0.001看看吸引子是否恢复有界结构。初值取(1,1,1)后前几百点仍处于暂态严谨的做法是让LorenzDifEqn1多算MN点把前M点丢弃再输出M常见取值是500。主脚本里接上x x(501:end)再做标准化避免暂态污染统计量。3.4 Cal_S_ave与Cal_S的配合方式Cal_S_ave.m遍历tCal_S.m专注于单次计算。后者内部会让m取2、3、4、5r取σ/2、σ、2σ构造出S(m,r,t)矩阵。function [s_t, ds_t] Cal_S(x, t) % 对固定t在m和r两个维度上做小规模采样 sigma std(x); ms 2:5; rs sigma * [0.5, 1, 2]; S zeros(length(ms), length(rs)); for mi 1:length(ms) m ms(mi); for ri 1:length(rs) r rs(ri); C2 correlative_integral(x, m, r, t); C1 correlative_integral(x, 1, r, t); S(mi, ri) C2 - C1^m; end end s_t mean(S(:)); % 对m和r求平均 ds_t max(S(:)) - min(S(:)); % S对r的最大差值 endC1^m要注意这里用的是矩阵幂标量形式表达的是关联积分的自乘不是按元素乘。S(m,r,t)反映的是嵌入m维和嵌入1维时序列在尺度r上的结构差异。如果系统是确定性混沌这个差异会随t呈现规律性波动如果是纯噪声S值会在零附近无结构跳动。这也是为什么观察ΔS_avg曲线有没有清晰极小值比直接看数值本身更能说明问题。4. 运行配置与排错录像操作里没明说的坑4.1 路径、版本和入口文件摘要里强调过几点照做能避开大部分启动即报错的情况。Matlab有个坏习惯当前文件夹窗口指向哪函数解析就从哪开始。很多同学下载解压后直接在命令行敲Runme_CCMethod结果Matlab报“未定义函数或变量Cal_S_ave”。这个报错的直接原因就是当前文件夹不在工程目录下子函数根本不在搜索路径里。正确方式是先用cd把目录切到解压后的文件夹再把整个文件夹加入路径cd(你的解压路径/CC算法求延迟时间和嵌入维数); addpath(genpath(pwd)); Runme_CCMethodMatlab 2021a及以上版本都支持这套操作。录像里应该也是先做这两步再点运行的看录像时注意观察左侧的当前文件夹窗口不是只看编辑器里的光标。运行入口只能是Runme_CCMethod.m双击子函数文件直接运行会得到参数不足或结果空白的报错因为这些函数依赖主脚本传入的x、t自身没有默认参数兜底。4.2 常见报错与现象对照现象直接原因处理方式提示Cal_S_ave未定义工程路径未加入Matlab搜索路径cd到工程目录并addpath关联积分结果是NaN序列里有NaN或inf标准化时std0检查LorenzDifEqn1输出的数据长度和数值范围ΔS_avg曲线没有明显极小值序列太短统计涨落大N提高到至少3000或对多次运行结果取平均S_cor最小值落在搜索边界上Tmax设得太小真正的最优时间窗还没出现把Tmax从200增大到500再观察程序“卡住”超过10分钟嵌套循环复杂度O(Tmax×m×r×N²)减小N或Tmax改用向量化距离统计LorenZ序列直接发散到inf积分步长过大dt从0.01降到0.0014.3 计算时间优化参数上限怎么设对5000点序列Tmax200意味着关联积分函数被调用200×4×32400次每次内部又是O(N²)的循环。在2021a版本上跑完整流程大约要几分钟到十几分钟取决于机器单核性能。我在复现时会先做一轮快速扫描用Tmax50、r取2个值粗跑确认统计量曲线形态正常再拉长到200精算。这样出问题时不用等全量跑完才看到结果。向量化是另一个常用手段correlative_integral.m里的内层循环可以改成矩阵距离计算D abs(X - permute(X, [3 2 1])); % n x m x n 的距离张量 D max(D, [], 2); % 压缩成 n x n 的最大模距离 C (sum(sum(tril(D r, -1)))) / (n * (n-1) / 2);距离张量在n500时是500×500×1的浮点矩阵内存可接受n超过2000就别这么写了内存直接膨胀。折中方案是把外层循环保留内部用向量化减法替代第二层循环。我一般把N控制在3000到5000既保证统计稳定性又让单次实验在可接受的等待时间内。操作录像看的时候注意一个细节录像是先展示短序列的快速结果再演示全量计算避免观看者误以为几十秒就能出完整结果。命令行里的进度没有专门显示长时间无输出不一定是死机可以先在Cal_S_ave.m里临时加一行fprintf(t%d\n, t)确认循环在推进。4.4 结果可信度的快速检查跑完后命令行会打印三个数τ、m、τ_w。对Lorenz系统数据τ大体落在10到16之间m在4左右τ_w在40到70之间。如果m算出来是1或大于8先别急着改算法回看两个位置一是标准化时是否用了全局std二是第一个极小值检测是否落在了序列起点附近。大量经验表明τ_w/τ的结果落在3到4附近时m4基本就是可靠值。若结果超出这个范围用下面这段脚本定位问题figure; subplot(3,1,1); plot(s_avg); title(S\_avg); subplot(3,1,2); plot(ds_avg); title(Delta S\_avg); subplot(3,1,3); plot(sc_avg); title(S\_cor);三条曲线肉眼看一下S_avg如果整体向正向漂移而不是围绕零波动说明系统尚未稳定ΔS_avg如果有多个差不多深度的极小值取第一个还是第五个需要结合功率谱主周期来定而不是机械地取第一个。5. 用相空间重构质量反推参数CC算法结果的验证技巧5.1 重构吸引子是否“摊开”把τ和m代回延迟向量重构在三维投影下看吸引子的展开程度。τ取CC算法结果附近的值分别用τ/2、τ、2τ画三张散点图。τ太小轨道挤在xy直线附近说明嵌入窗还没拉开τ太大点云会呈现无结构的弥散噪声被放大。这一步虽然不涉及数值指标但在判断CC算法输出是否自洽时最直观。5.2 功率谱与FNN交叉验证Cal_psd.m用FFT计算功率谱找到主峰周期T。理想情况下τ约为T的1/4到1/3。如果CC算法给出的τ远小于这个区间通常是Tmax选小了。假近邻法给出的m如果比τ_w/τ1大2以上说明时间窗估计偏小重新检查S_cor曲线是否真的取到了全局最小而不是落入第一个局部极值。5.3 加噪稳定性测试时间序列预测场景里数据几乎总是带噪的。对Lorenz序列叠加高斯白噪声再重跑CC算法观察τ和m的漂移是判断统计量是否稳健的常规做法rng(42); % 固定随机种子保证重复实验之间可比 x_noisy x 0.1 * sigma_x * randn(size(x)); % 把x_noisy替换进Runme_CCMethod.m里的x变量重新运行主脚本噪声标准差从0.05σ_x逐步加到0.3σ_x如果τ的漂移不超过2个采样点m不变说明当前序列长度下统计量是稳的。漂移过大时优先检查序列长度而不是怀疑算法本身。注意每次叠加噪声前都要重置rng否则两次实验之间的差异混入了随机采样的样本误差无法定位算法自身的敏感度。这些验证做完CC算法的结果才算真正可用。把τ和m代回到后续的预测模型之前值得花两分钟跑完这一整套检验。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价