简介面向信号处理、语音分析与通信等方向的学习者这份材料围绕JADE盲源分离算法展开兼顾原理梳理与MATLAB程序实现适合具备一定矩阵运算和统计信号基础、希望动手复现盲分离实验的读者。内容从盲信号分离的基本问题切入说明如何从多路传感器观测的混合信号中恢复未观测源信号并解释“盲”的两层含义进而聚焦JADE借助高阶累积量刻画非高斯性、在源信号统计独立且至多含一个高斯信号的条件下完成分离的思路涉及四阶累积量等核心知识点也提示该方法对源信号非白、非平稳特性未作专门处理便于读者判断适用边界。借助配套程序可对照理解混合信号构造、累积量估计、分离矩阵求解与输出验证等环节。整包为zip格式约426KB文件数量与类型明细未在资源页列出需下载后查看。已有953人学习可作为理解高阶统计量盲源分离方法的参考。1. 从一段双人混叠录音说起JADE 盲源分离算法与 MATLAB 程序能解决什么一段双人对话只用一个麦克风录下来回放时两个声音叠在一起常规滤波很难拆干净。JADE 盲源分离算法给出的思路是不依赖说话人先验也不要求麦克风阵列只利用白化后的四阶累积量矩阵做联合对角化。配套的 MATLAB 程序把中心化、白化、累积量构造、Givens 旋转和性能评估串成一条可跑的链路适合正在做语音分离、故障源识别或阵列信号处理的开发者拿来改参数、换数据。它不解决欠定混叠的全部问题但在观测数不少于源数、源信号统计独立的场景里是一个结构清晰、能照着复现的基线。拿到资源后先跑入口脚本看分离波形再改信号生成函数换数据比一上来啃公式更稳。2. 工程结构与运行环境这套 MATLAB 程序怎么组织这套 JADE 盲源分离 MATLAB 程序不依赖深度学习工具箱核心计算只用到矩阵特征值分解、四阶矩估计和 Givens 旋转。目录按“入口脚本、核心函数、演示数据、评估函数”分开读代码时先看入口再顺着调用链进核心函数不容易迷路。对刚接触盲源分离的开发者来说最怕的是一上来看到一堆累积量张量不知道数据从哪来、到哪去这套结构把数据生成和算法分离切开换数据时只动演示脚本改算法时只动核心函数。2.1 目录树与文件职责资源包里的文件不多但边界划得比较清楚。下面按常见组织方式列出目录结构实际拿到后文件名可能略有差异职责对应即可。jade_matlab/ ├── main_jade.m % 入口脚本生成/加载观测信号调用分离画图 ├── demo_sources.m % 演示信号生成独立源、混合矩阵、可选噪声 ├── jade_core.m % JADE 主流程中心化、白化、累积量、联合对角化 ├── cumulant_matrices.m % 四阶累积量矩阵组构造 ├── joint_diag_givens.m % Givens 旋转联合对角化 ├── eval_separation.m % 相关系数矩阵、性能指标 PI、波形对比 └── data/ └── mixed_demo.mat % 可选保存好的观测数据方便复现main_jade.m是唯一需要直接运行的脚本。它先调用demo_sources.m得到源信号S、混合矩阵A和观测信号X再调用jade_core.m得到分离信号Y和分离矩阵B最后用eval_separation.m算相关系数和 PI。这样分层的好处是想换真实录音只需要把X读进来保证维度是“通道数 × 采样点数”想改白化方式只动jade_core.m前半段想换联合对角化策略只替换joint_diag_givens.m。提示观测矩阵X的维度约定是m × Nm是观测通道数N是采样点数。很多翻车来自把行和列搞反后面白化协方差算出来维度不对报错却出现在累积量函数里。2.2 环境准备与入口参数MATLAB 版本建议 R2018b 及以上基础环境即可。代码里用到eig、sort、reshape、corrcoef这些基础函数不需要额外工具箱。如果要做更漂亮的时频图可以装 Signal Processing Toolbox但分离主流程不依赖它。运行前把当前文件夹切到jade_matlab根目录或者在脚本开头用addpath把子目录加进来。入口脚本常用参数如下参数含义常见取值nSources源信号个数2 或 3先从小规模调nSamples采样点数200010000mixMatrix混合矩阵m × n随机高斯或手工指定snrDb观测信噪比2040 dB先不加噪声maxSweep联合对角化扫描次数3080入口脚本里一般会写这么一段% main_jade.m 开头清理环境并设置路径 clear; clc; close all; addpath(genpath(pwd)); % 基本参数先跑 2 源 2 观测的无噪场景 nSources 2; nSamples 4000; snrDb 30; maxSweep 60; % 生成演示数据S 是 nSources × nSamplesA 是 m × nSources [S, A, X] demo_sources(nSources, nSamples, snrDb); % 调用 JADE 核心 [Y, B, W, Z] jade_core(X, nSources, maxSweep); % 评估并画图 eval_separation(S, Y, A, B, X);这段代码里demo_sources负责造数据jade_core负责分离eval_separation只做评估和可视化。snrDb设成 30 不是必须的刚开始调建议先设成Inf或干脆不加噪声确认无噪场景能分开再逐步加噪声。maxSweep设 60 是保守值联合对角化通常 30 次以内会收敛设大一点不影响结果只是多花一点时间。nSources必须和demo_sources里实际源数一致JADE 主流程需要知道保留几个主成分如果源数未知要先做源数估计不能直接拍脑袋填。2.3 一次完整调用链从 demo_sources 到 eval_separation调用链可以拆成四步。第一步demo_sources生成统计独立的源信号常见做法是正弦、方波、调幅信号和少量高斯噪声的组合。第二步jade_core对观测X做中心化和白化得到白化信号Z并保留白化矩阵W。第三步cumulant_matrices用Z构造四阶累积量矩阵组joint_diag_givens找正交矩阵V使这组矩阵近似对角。第四步分离矩阵B V * W分离信号Y B * X最后归一化并评估。这里有个容易忽略的点jade_core返回的W是白化矩阵维度是n × mV是联合对角化得到的正交矩阵维度是n × n所以B V * W的维度是n × m正好把m个观测压成n个分离通道。如果直接把V和X相乘维度对不上或者出来的是白化域的信号不是原始观测域。评估时用B * A得到全局矩阵再看它是否接近“每行每列只有一个主导元”的置换对角矩阵。这个全局矩阵是判断分离好坏最直接的黑匣子窗口比单看波形更可靠。3. 核心原理拆解从白化到四阶累积量的联合对角化JADE 的完整名字是“基于四阶累积量矩阵联合近似对角化”的盲源分离方法。名字长但拆开看就三件事先把观测白化成各向同性再用四阶累积量把源信号的独立性信息装进一组矩阵最后找同一个正交变换把这组矩阵同时对角化。白化解决二阶相关性联合对角化解决高阶独立性。理解这条主线再看代码就不会被累积量张量吓住。3.1 混合模型与三个假设线性瞬时混合模型写成X A * S N其中X是m × N的观测矩阵S是n × N的源矩阵A是m × n的混合矩阵N是噪声。JADE 要找一个分离矩阵B使Y B * X尽量接近S的某个排列和尺度版本。尺度不确定是盲分离的固有属性源信号乘 2、分离信号乘 0.5波形形状一样算法没法判断谁才是“真实幅度”。排列不确定也一样分离出来的第一行可能是源 2第二行可能是源 1。评估时不能直接按行比对要先做相关系数矩阵再看每行每列的最大值。算法成立通常依赖三个假设源信号统计独立最多一个源是高斯分布观测通道数不少于源数。第一个假设是联合对角化的根基第二个假设是因为高斯信号的二阶统计量已经包含全部信息四阶累积量对高斯源不敏感第三个假设决定白化后能不能保留足够的秩。实际做语音分离时源信号短时独立性能勉强满足但混响和噪声会破坏假设所以 JADE 更适合短时窗、低混响、观测数足够的场景。做故障源识别时如果多个故障源同时出现且统计相关分离效果会明显下降这时候要先做去相关或换更合适的算法。3.2 中心化与白化为什么先做这一步中心化就是每行减去均值X X - mean(X, 2);这一步不改变混合关系只是把一阶矩去掉方便后面用协方差。白化是找一个线性变换W使Z W * X的协方差变成单位阵。常见做法是对观测协方差做特征值分解% 中心化后的观测协方差 Cx (X * X) / size(X, 2); % 特征值分解按特征值从大到小排 [E, D] eig(Cx); [d, idx] sort(diag(D), descend); E E(:, idx); d d(idx); % 只保留前 nSources 个主成分避免噪声子空间参与白化 n nSources; W diag(1 ./ sqrt(d(1:n))) * E(:, 1:n); Z W * X;Cx是m × m的协方差矩阵E的列是特征向量D的对角线是特征值。diag(1./sqrt(d(1:n)))把主成分方向缩放到单位方差E(:,1:n)把观测投影到主成分坐标。两件事合起来就是白化矩阵W。保留前n个主成分而不是全部是因为观测里往往混有噪声子空间噪声方向的白化会把噪声放大后面累积量估计会更抖。白化之后Z的协方差是单位阵混合矩阵A被改写成某个正交矩阵在无噪、源数等于观测数时。这一步把问题从“找任意可逆矩阵”缩小到“找正交矩阵”搜索空间小了很多。但白化只用了二阶统计量它不能保证源信号分开两个白化后的信号仍然可能混在一起只是彼此不相关。JADE 后面的四阶累积量和联合对角化就是在这个正交空间里继续找独立性。注意白化时保留的主成分数n必须和源数一致。填大了会把噪声当源分离波形里出现高频毛刺填小了会丢掉弱源评估时怎么调参数都少一路。3.3 四阶累积量矩阵怎么构造白化后的信号Z是n × N。四阶累积量描述四个分量之间的联合统计关系。对实信号累积量写成Cum(z_i, z_j, z_k, z_l) E[z_i z_j z_k z_l] - E[z_i z_j]E[z_k z_l] - E[z_i z_k]E[z_j z_l] - E[z_i z_l]E[z_j z_k]白化后E[z_i z_j] δ_ij所以后三项变成单位阵的乘积代码里可以用delta简化。把(i,j)当行索引、(k,l)当列索引四阶累积量张量可以重排成n^2 × n^2的矩阵C4。JADE 不直接对C4做对角化而是取它的前n个主特征向量每个特征向量重塑成n × n矩阵得到一组累积量矩阵M(:,:,1) ... M(:,:,n)。这组矩阵承载了源信号的非高斯信息接下来要找同一个正交矩阵把它们同时对角化。function [M, C4] cumulant_matrices(Z) % Z: 白化后的信号n × N [n, N] size(Z); C4 zeros(n^2, n^2); % 逐元素估计四阶矩n 较小时可读性优先 for i 1:n for j 1:n for k 1:n for l 1:n m4 mean(Z(i,:) .* Z(j,:) .* Z(k,:) .* Z(l,:)); delta (ij)*(kl) (ik)*(jl) (il)*(jk); C4((i-1)*n j, (k-1)*n l) m4 - delta; end end end end % 实信号累积量矩阵对称化减少数值误差 C4 (C4 C4) / 2; % 取前 n 个主特征向量重塑成矩阵组 [Vc, Dc] eig(C4); [~, idx] sort(diag(Dc), descend); M zeros(n, n, n); for m 1:n v Vc(:, idx(m)); M(:,:,m) reshape(v, n, n); M(:,:,m) (M(:,:,m) M(:,:,m)) / 2; end end这段代码里m4是四阶矩估计delta是白化后二阶矩的克罗内克项。C4的索引(i-1)*nj对应矩阵位置(i,j)(k-1)*nl对应(k,l)。eig(C4)得到特征向量取前n个最大特征值对应的向量重塑成n × n矩阵。重塑时用列优先和 MATLAB 的reshape默认顺序一致如果换成行优先矩阵组会错位联合对角化后分离波形会乱。M(:,:,m)再做一次对称化是因为有限样本估计会有轻微不对称不对称矩阵进 Givens 旋转容易让角度计算抖。3.4 联合对角化与分离矩阵现在有一组实对称矩阵M_1 ... M_n目标是找正交矩阵V使V * M_k * V对每个k都近似对角。JADE 用 Givens 旋转逐对消去非对角元每次取两个下标(p,q)构造一个 2×2 旋转让这组矩阵在(p,q)位置的非对角平方和下降。扫完所有下标对算一轮多轮扫描直到非对角能量不再明显下降。旋转角不是拍脑袋算的。对每个矩阵取 2×2 子块记d M_k(p,p) - M_k(q,q)a M_k(p,q)。旋转后非对角元可以写成-d/2 * sin(2θ) a * cos(2θ)。要让所有矩阵在这个位置的非对角平方和最小构造 2×2 矩阵H sum_k [ d^2/4, -d*a/2; -d*a/2, a^2 ]取H最小特征值对应的特征向量[x; y]令θ 0.5 * atan2(x, y)就得到这一对下标的最佳旋转角。这个推导在实信号下很稳代码实现也不长。联合对角化完成后V是累积的旋转矩阵分离矩阵B V * W分离信号Y B * X。到这里白化域里的正交混合被V拆开原始观测域里的混合被B拆开。4. 关键代码逐段JADE 主循环与 Givens 旋转实现这一章把核心函数拆开看。读代码时建议按“累积量矩阵构造 → 联合对角化 → 分离矩阵组装”的顺序不要从入口一路跳。每段代码后面都标了输入输出和参数含义改的时候先确认维度再动循环。JADE 的代码量不大但维度和旋转方向很容易写反血泪经验是每改一次白化或旋转先把中间矩阵的尺寸打印出来别等最后画波形才发现不对。4.1 累积量矩阵构造从四阶矩到矩阵组上一章给了cumulant_matrices的完整实现这里补参数和常见改法。输入Z必须是白化后的n × N矩阵n是保留的源数N是采样点数。输出M是n × n × n的三维数组第三维是矩阵编号C4是n^2 × n^2的累积量矩阵调试时可以拿它看特征值分布。如果C4的前几个特征值拉不开说明源信号非高斯性不够或者白化保留的主成分数不对。% 调试片段看 C4 特征值衰减 [Vc, Dc] eig(C4); eigVals sort(diag(Dc), descend); disp(eigVals(1:min(10, length(eigVals))));这段调试代码不参与主流程但很实用。正常场景下前n个特征值应该明显大于后面的噪声特征值如果所有特征值差不多大后面联合对角化得到的V会接近单位阵分离波形和观测波形差不多看起来像“算法没生效”。这时候先别怀疑 Givens 旋转回头查源信号是不是太接近高斯或者采样点是不是太少。四阶累积量的方差对样本长度很敏感N小于 1000 时估计抖动会明显变大常见做法是把N提到 4000 以上或者对信号做分帧累积。提示C4的维度是n^2 × n^2当n3时是 9×9当n5时是 25×25计算量还能接受n再大时四重循环会明显变慢可以把内层循环向量化或者改用kron和矩阵乘法批量算四阶矩。4.2 Givens 联合对角化旋转方向与累积更新联合对角化函数输入矩阵组A输出正交矩阵V和对角化后的矩阵组。下面这版实现按扫描轮次推进每轮遍历所有(p,q)下标对构造H矩阵求旋转角然后更新所有矩阵和累积旋转矩阵。function [V, A] joint_diag_givens(A, maxSweep) % A: n × n × K 的实对称矩阵组 % maxSweep: 最大扫描轮数常用 3080 [n, ~, K] size(A); V eye(n); for sweep 1:maxSweep % 记录本轮开始时的非对角能量 off0 0; for k 1:K Ak A(:,:,k); off0 off0 sum(Ak(:).^2) - sum(diag(Ak).^2); end for p 1:n-1 for q p1:n H zeros(2,2); for k 1:K Ak A(:,:,k); d Ak(p,p) - Ak(q,q); a Ak(p,q); H H [d^2/4, -d*a/2; -d*a/2, a^2]; end % 最小特征向量给出 sin(2θ) 和 cos(2θ) [evec, eval] eig(H); [~, idx] min(diag(eval)); v evec(:, idx); x v(1); y v(2); theta 0.5 * atan2(x, y); c cos(theta); s sin(theta); G [c, -s; s, c]; % 对每个矩阵做 G * A * G for k 1:K Ak A(:,:,k); Ak([p,q], :) G * Ak([p,q], :); Ak(:, [p,q]) Ak(:, [p,q]) * G; A(:,:,k) Ak; end % 累积旋转矩阵 V(:, [p,q]) V(:, [p,q]) * G; end end % 本轮结束后的非对角能量 off1 0; for k 1:K Ak A(:,:,k); off1 off1 sum(Ak(:).^2) - sum(diag(Ak).^2); end % 能量不再下降或已经足够小就提前退出 if off1 1e-10 || abs(off1 - off0) 1e-12 break; end end end这段代码的关键在三个地方。第一H的构造对应上一章的二次型d和a都取当前矩阵的值不能提前算好固定角度。第二矩阵更新顺序是先用G左乘[p,q]行再用G右乘[p,q]列等价于G * Ak * G如果只更新行或只更新列矩阵组不再对称后面eig会出复数。第三V的更新是V(:,[p,q]) V(:,[p,q]) * G累积所有旋转。最终V * M_k * V近似对角所以分离矩阵里用的是V不是V。参数maxSweep不需要设得特别大。实信号下一般 2040 轮就收敛设 60 是留余量。如果设到 200 还看不到非对角能量下降问题通常不在轮数而在输入矩阵组不是同一组源的白化累积量或者C4特征向量取错了。off1 1e-10这个阈值对归一化后的数据合适如果数据幅度很大阈值要相应放大或者先把矩阵组按 Frobenius 范数归一化。4.3 分离矩阵组装与输出归一化jade_core把前面几步串起来返回Y、B、W、Z四个输出。Y是分离信号B是分离矩阵W是白化矩阵Z是白化信号。调试时保留W和Z很有用怀疑白化出错就看Z的协方差是不是接近单位阵怀疑联合对角化出错就看V * M_k * V的非对角元。function [Y, B, W, Z] jade_core(X, nSources, maxSweep) % X: m × N 观测矩阵 % nSources: 源数也是白化保留的主成分数 % maxSweep: 联合对角化最大扫描轮数 [m, N] size(X); % 1. 中心化 X X - mean(X, 2); % 2. 白化保留前 nSources 个主成分 Cx (X * X) / N; [E, D] eig(Cx); [d, idx] sort(diag(D), descend); E E(:, idx); d d(idx); n min(nSources, m); W diag(1 ./ sqrt(d(1:n))) * E(:, 1:n); Z W * X; % 3. 四阶累积量矩阵组 [M, ~] cumulant_matrices(Z); % 4. 联合对角化 [V, ~] joint_diag_givens(M, maxSweep); % 5. 分离矩阵与分离信号 B V * W; Y B * X; % 6. 逐行归一化消除尺度不确定性 for i 1:size(Y,1) scale max(abs(Y(i,:))); if scale 0 Y(i,:) Y(i,:) / scale; end end end第 2 步里n min(nSources, m)是防御性写法防止调用方把源数填得比观测通道还大。白化矩阵W是n × mZ是n × N。第 5 步B V * W是n × mY B * X是n × N。第 6 步逐行除以最大绝对值只解决尺度不解决排列。排列不确定性要靠评估函数里的相关系数矩阵处理不能在这段代码里硬排因为真实场景没有参考源顺序。5. 避坑与排查JADE 跑不出结果时先看这几处JADE 的代码量不大但失败时的表现很像“玄学”有时波形完全没分开有时分出来两路几乎一样有时 PI 指标看着不错但波形明显不对。下面几条是实际调这套 MATLAB 程序时最常见的翻车现场按“现象 → 原因 → 解决”记录遇到问题可以先对照排查。5.1 五个典型翻车现场现象一分离波形和观测波形几乎一样PI 接近 0。原因通常是白化保留的主成分数等于观测通道数但源数小于观测数噪声子空间被当成源参与累积量计算或者C4的前n个特征向量取错矩阵组没有承载源的非高斯信息。解决方法是先把nSources设成真实源数检查d的特征值衰减确认前n个特征值明显大于后面再打印C4的特征值看前n个是否拉得开。如果源信号本身接近高斯四阶累积量会很小这时候换基于二阶或时频域的算法更合适不要硬调 JADE 参数。现象二分离信号出现两路高度相似相关系数矩阵有一行两列都很大。原因可能是联合对角化没有收敛V接近单位阵也可能是累积量矩阵组线性相关旋转时找不到能把它们同时分开的角度。解决方法是把maxSweep提到 100看非对角能量是否继续下降如果下降一点点就停检查joint_diag_givens里H的符号和G的旋转方向。旋转方向写反时非对角能量可能先降后升表现为分离波形越来越乱。另一个常见原因是白化矩阵W的维度写错Z的协方差不是单位阵后面所有矩阵组都偏了。现象三代码报错“矩阵维度不一致”位置在B V * W或Y B * X。原因多半是X的维度约定不统一。有的演示脚本按N × m生成数据转置漏了有的真实录音读进来是N × m直接传给jade_core就会在白化协方差那里出错。解决方法是入口处强制统一成m × N并在jade_core开头加一句维度检查assert(size(X,1) size(X,2), X 应为 通道数 × 采样点数)。真实录音通常采样点远大于通道数这个断言能挡住大部分转置错误。现象四无噪场景能分开加 20 dB 噪声后完全失效。原因不一定是算法抗噪差可能是白化时把噪声方向也保留了。观测协方差的小特征值对应噪声子空间如果nSources设得比真实源数大噪声会被白化成“源”累积量矩阵组里混入噪声的四阶统计量。解决方法是先做源数估计或者按特征值门限截断只保留大于最大特征值 1%5% 的主成分。另一个办法是在白化前做一次预滤波但不要把源信号的有用频带滤掉。加噪后 PI 从 0.9 掉到 0.3 很常见先确认不是维度或源数问题再考虑换稳健累积量。现象五分离波形顺序和源信号对不上评估时怎么比都错。这是排列不确定性不是算法失败。盲分离输出顺序本来就不固定直接按行减源信号会得到很大误差。解决方法是评估前先算corrcoef(S(i,:), Y(j,:))的绝对值矩阵按最大相关系数做匹配再算 PI。如果矩阵里每行每列都有明显主导元说明分离成功只是顺序变了如果矩阵某行有两个相近的大值说明那一路没完全分开。评估函数里建议同时输出相关系数矩阵和匹配后的波形不要只看一个 PI 数字。5.2 排查顺序与验证方法遇到问题建议按固定顺序查不要一上来改联合对角化。第一步查数据维度X是不是m × NS是不是n × NA是不是m × n。第二步查白化Z * Z / N是否接近单位阵如果不是看W的构造和特征值排序。第三步查累积量C4前n个特征值是否明显大于后面矩阵组M是否对称。第四步查联合对角化打印每轮的非对角能量确认它单调下降。第五步才看分离矩阵和波形。验证时可以用一个“已知混合矩阵”的小例子手工设A [1, 0.5; 0.3, 1]源信号用两个不同频率的正弦加一个方波无噪运行。如果这个例子都分不开说明代码链路有问题如果能分开再换随机混合矩阵和真实录音。这个做法相当于给算法留了一颗后悔药每次改白化或旋转先跑固定小例子确认基线没坏再上真实数据。PI 指标不要单独看配合相关系数矩阵和波形图三者一致才算真的分开。注意不要把分离信号的幅度归一化当成“分离成功”的证据。归一化只改变尺度不改变波形相关性如果两路输出仍然高度相似归一化后看起来都像源信号但相关系数矩阵会暴露问题。6. 二次开发从能跑到能改的几条改造路径这套 MATLAB 程序跑通之后二次开发通常围绕三个方向换数据、换源数、换性能。换数据最直接把demo_sources替换成读录音或读传感器数据的函数保持X为m × N先做带通滤波和去均值再进jade_core。换源数要改白化保留的主成分数并补一个源数估计步骤常见做法是看协方差特征值拐点或累积量特征值衰减不要直接拍脑袋填。换性能可以先把cumulant_matrices里的四重循环向量化n 较大时用kron批量算四阶矩再把joint_diag_givens的扫描顺序改成按非对角能量从大到小排收敛会快一些。改造方向改动点验证方法复数信号白化用共轭转置累积量加共轭项用复数正弦混合看Z*Z/N是否单位阵欠定/过定过定先降维欠定需换稀疏或时频方法先确认m n否则不要直接套 JADE在线分块按帧白化累积量做滑动平均对比整段批处理和分块输出的相关系数MEX 加速把四重循环和 Givens 旋转写成 C用同一组数据对比加速前后Y的误差如果要做复数 JADE白化协方差改成X * X / N特征值分解后W用共轭转置累积量公式里的二阶矩项也要带共轭。实信号代码直接搬到复数会漏掉共轭分离波形会出现虚部混叠。欠定场景不要硬套这套程序观测通道少于源数时白化后的正交矩阵维度不够联合对角化最多只能分开m路剩下的源会叠在一起这时候要考虑稀疏成分分析或时频掩蔽。在线分块时每帧都要重新估白化矩阵帧长太短会让累积量抖动常见做法是帧长 2000 点、帧移 1000 点累积量做指数滑动平均。从那以后我每次改盲分离参数都先把白化后的协方差打印出来看一眼再动联合对角化固定小例子跑不过就不碰真实数据。希望帮到你。本文还有配套的精品资源点击获取