简介雷达辐射源在线核聚类分选MATLAB代码面向雷达信号处理、电子侦察及相关专业研究人员针对复杂电磁环境下多目标信号难以实时准确分选的问题提供一套基于核映射与聚类算法的在线分选实现。压缩包共7个m文件整体仅4KB代码结构紧凑涵盖信号生成、数据预处理、核聚类、类别更新与删除等关键环节便于理解算法流程并快速嵌入自有系统。该实现采用核技巧将低维不可分信号映射到高维特征空间结合K均值或谱聚类进行分组可提升辐射源识别准确率。用户只需输入雷达数据程序即可自动完成滤波、映射、聚类与结果展示适合算法验证、课程设计及科研对比。目前已有1164人学习下载是研究雷达辐射源分选技术的一份实用参考资料。1. 雷达辐射源在线核聚类分选为什么比离线难做雷达辐射源在线核聚类分选核心是把截获到的脉冲描述字PDW按辐射源身份实时聚类难点全在“在线”两个字。离线场景下你可以把一整段脉冲流收齐反复迭代聚类直到收敛在线场景里脉冲一批批到达簇数未知且会随时间增加或消失同一部雷达还会因为频率捷变、模式切换在特征空间里分裂成多个子簇线性聚类基本分不开。核聚类把特征隐式映射到高维空间能刻画这种非线性边界但核方法本身依赖历史样本做距离计算搬到流式场景就必须解决缓存、增量更新和簇生命周期管理。本文给一套不依赖任何工具箱的 MATLAB 实现包含仿真 PDW 脉冲流生成、在线核聚类主循环、簇合并/过期清理以及两个能直接用的分选评估指标。适合做电子侦察算法仿真、信号分选预研的工程师或者正在把离线聚类算法改成流式版本的开发者。代码可以整段复制运行参数和坑都写在对应章节里。2. 核聚类怎么用进辐射源分选PDW 特征与在线聚类选型2.1 分选问题的输入PDW 脉冲描述字辐射源分选也叫去交织输入是侦察接收机对截获脉冲形成的 PDW 记录。一条典型的 PDW 包含载频 RF、脉宽 PW、到达角 DOA、到达时间 TOA、脉幅 PA 等参数。其中 RF、PW、DOA 是辐射源身份最直接的刻画TOA 一般留到后续做重频模式估计聚类分选这一步通常不把它作为特征。于是每个脉冲对应一个三维特征向量 x(rf, pw, doa)分选就变成把混在一起的脉冲流按辐射源分成若干组每组对应一部雷达。实际信号里这组特征并不干净。频率捷变雷达的 RF 会在中心频率附近跳变同一部雷达在不同搜索/跟踪模式下的 PW 完全不同DOA 受多径和测向误差影响呈现多峰分布。也就是说一个辐射源在特征空间中不是紧凑的高斯团而是由多个分离子簇组成的非线性结构。用欧氏距离做线性聚类比如经典 k-means会把同一个辐射源的不同子簇硬切开或者把两部 RF 相近的雷达并成一个簇。核聚类的动机就在这里。RBF 核 κ(x, y)exp(-‖x-y‖²/(2σ²)) 把样本隐式映射到高维核空间在高维空间中原本交叉的子簇可能变成线性可分。对雷达辐射源分选来说核方法不需要预先知道每部雷达的参数调制规律只要核宽度 σ 和簇数给得合理就能拟合出 RF 捷变、模式跳变这类非线性边界。2.2 在线核聚类要做什么缓存、距离与簇心更新普通核 k-means 是批处理算法每次迭代都要计算所有样本两两之间的核矩阵然后重新分配每个样本到最近的核簇心。这个流程在离线没问题在线场景下一是不允许反复扫描历史数据二是脉冲流的分布会随时间漂移——一部雷达关机后它的簇应该被遗忘新开机一部雷达时又要能立刻形成新簇。在线核聚类最常见的做法是给每个簇保留一个固定容量的缓存样本集合用缓存样本的核均值来近似簇心在核空间中的像。设簇 c 的缓存为集合 S_c簇心的像为 φ(x) 在 S_c 上的平均。新样本 x 到该簇心的核距离平方可以展开成d² κ(x,x) (1/n²)·ΣΣ_{i,j∈S_c} κ(x_i,x_j) - (2/n)·Σ_{i∈S_c} κ(x,x_i)第一项是常数第二项是簇内核值平均记为 inner可以在簇结构里维护第三项是样本到缓存所有点的核值平均。整个距离计算只需要遍历缓存不需要全局核矩阵这让流式处理成为可能。在线更新也围绕这个公式展开样本被分配进簇后把它加进缓存同时增量更新 inner缓存超限时丢弃最旧样本再增量扣掉它的贡献。这样簇心像就一直由最近若干个样本决定天然带了一个滑动窗口式的遗忘机制。簇的增删则由新簇阈值、合并阈值和过期清理控制。这套方案在工程实现上只依赖基础矩阵运算不需要统计工具箱给 MATLAB 落地留出了很大的自由度。3. 用 MATLAB 把在线核聚类跑起来仿真数据与核心函数3.1 生成仿真 PDW 脉冲流先写一个仿真数据生成函数模拟 3 部雷达的脉冲流。第 1 部雷达 RF 中心 9.2 GHz、PW 1.0 μs、DOA 35°第 2 部雷达 RF 中心 9.8 GHz、PW 1.8 μs、DOA 55°第 3 部雷达 RF 中心 10.4 GHz、PW 0.7 μs、DOA 60°。前两部雷达 RF 距离比较近第三部还加了 30% 概率的正负跳变用来模拟频率捷变造成的非线性子簇。每批 40 个脉冲共 50 批最后混入 5% 的杂散噪声脉冲真实类别用 0 标记。function [batchX, batchY] genRadarStream() % 仿真生成在线到达的雷达PDW脉冲流 % 输出 batchX: 1xB cell每个cell是 n_b x 3 的特征矩阵列为[RF, PW, DOA] % batchY: 1xB cell每个cell是 n_b x 1 的真实辐射源编号0为杂散脉冲 rng(42); nBatch 50; batchSize 40; noiseRatio 0.05; centerRF [9.2, 9.8, 10.4]; centerPW [1.0, 1.8, 0.7]; centerDOA [35, 55, 60]; nRadar numel(centerRF); batchX cell(nBatch,1); batchY cell(nBatch,1); for b 1:nBatch X zeros(batchSize,3); y zeros(batchSize,1); row 0; for r 1:nRadar n floor(batchSize/nRadar); % 频率捷变30%概率在中心值上再叠一个随机符号跳变 rf centerRF(r) 0.3*randn(n,1) ... 0.4*(rand(n,1)0.7).*sign(randn(n,1)); pw centerPW(r) 0.15*randn(n,1); doa centerDOA(r) 2.0*randn(n,1); X(row1:rown,:) [rf, pw, doa]; y(row1:rown) r; row row n; end % 杂散噪声脉冲 nNoise floor(batchSize*noiseRatio); if nNoise 0 X(row1:rownNoise,:) [8.52.0*rand(nNoise,1), ... 0.31.2*rand(nNoise,1), 3050*rand(nNoise,1)]; y(row1:rownNoise) 0; row row nNoise; end idx randperm(row); batchX{b} X(idx,:); batchY{b} y(idx); end end这个函数把整个仿真流切成 50 个 batch符合在线处理的输入形式。这里刻意让第 2 和第 3 部雷达的 DOA 中心仅差 5°加上测向噪声后有重叠第 1 和第 2 部雷达 PW 有明显区分但 RF 捷变会让线性边界失效。这样生成的仿真数据能直接暴露线性聚类的问题。3.2 核距离计算与簇结构设计簇结构我用 MATLAB struct 数组表示每个簇包含四个字段X 是缓存样本矩阵n 是当前样本数inner 是簇内核值平均lastSeen 记录最后被命中的 batch 序号。inner 字段对应公式里的 (1/n²)·ΣΣκ维护好它距离计算每次只需要算样本到缓存的一行核值。function d2 kernelDist(x, cl, sigma2) % 样本x与簇结构cl在RBF核空间的距离平方 % d2 k(x,x) cl.inner - 2*mean_u k(x,u) if cl.n 0 d2 inf; return; end Kxv exp(-sum((cl.X - x).^2, 2)/sigma2); d2 1 - 2*mean(Kxv) cl.inner; endsigma2 传的是 2σ²这是 RBF 核的常量提前算好避免重复除法。距离计算的核心是 exp(-‖x-cache‖²/sigma2)矩阵写法一次算出样本到缓存所有点的核值mean 后代入展开式。如果簇缓存为空距离返回 inf让主循环直接走新建分支。样本加入簇时需要增量维护 inner。加入新样本 y 后新的核值总和等于旧总和加 2 倍新旧交叉核值之和再加 1自己到自己的核值为 1再除以新的 n 平方。缓存超限丢弃最旧样本 x_old 时从总和里减去 2 倍 x_old 与剩余样本的交叉核值之和再减 1同时 n 减 1。function cl addToCluster(cl, x, M, sigma2, b) % 新样本x加入簇cl并增量维护inner缓存超过M时丢弃最旧样本 oldN cl.n; if oldN 0 cl.X x; cl.n 1; cl.inner 1; cl.lastSeen b; return; end Kxv exp(-sum((cl.X - x).^2, 2)/sigma2); newSum cl.inner * oldN^2 2*sum(Kxv) 1; cl.n oldN 1; cl.inner newSum / cl.n^2; cl.X [cl.X; x]; if size(cl.X,1) M xold cl.X(1,:); remX cl.X(2:end,:); Kold exp(-sum((remX - xold).^2, 2)/sigma2); oldSum cl.inner * cl.n^2; newSum oldSum - 2*sum(Kold) - 1; cl.n cl.n - 1; cl.inner newSum / cl.n^2; cl.X remX; end cl.lastSeen b; end这段函数体现了在线核聚类最关键的增量更新。每次加入新样本只减少量 O(M·d) 的核值计算而不是重算整个缓存核矩阵。丢弃最旧样本后inner 仍然对应剩余缓存样本的精确核距离分母不会累积误差。M 的典型值是 20太小会让簇心像只能记住最近 20 个脉冲太大则每个样本的距离计算都会变慢。3.3 主循环分配、新建、合并与过期清理主脚本按 batch 顺序读入仿真脉冲流每批先按物理范围归一化特征到 [0,1]然后逐样本计算到所有现有簇的核距离。最近距离小于 thNew 就归入该簇并更新否则以该样本为种子新建一个簇。每 5 个 batch 做一次簇合并和过期清理。% demo_online_radar_cluster.m 主脚本 clear; clc; [batchX, batchY] genRadarStream(); % 归一化边界按侦察接收机先验物理范围设置 xmin [8.0, 0.3, 30]; xmax [12.0, 2.5, 90]; sigma 0.3; sigma2 2*sigma^2; % RBF核宽度 M 20; % 每簇样本缓存上限 thNew 0.15; % 核距离超过阈值 - 新建簇 thMerge 0.03; % 簇心核距离阈值 - 合并 expire 8; % 连续8批未命中 - 删除 clusters struct(X,{}, n,{}, inner,{}, lastSeen,{}); allLabels cell(numel(batchX),1); for b 1:numel(batchX) Xb (batchX{b} - xmin) ./ (xmax - xmin); labels zeros(size(Xb,1),1); for i 1:size(Xb,1) x Xb(i,:); best 0; dmin inf; for k 1:numel(clusters) d2 kernelDist(x, clusters(k), sigma2); if d2 dmin dmin d2; best k; end end if best 0 dmin thNew labels(i) best; clusters(best) addToCluster(clusters(best), x, M, sigma2, b); else clusters(end1).X x; %#okAGROW clusters(end).n 1; clusters(end).inner 1; clusters(end).lastSeen b; labels(i) numel(clusters); end end allLabels{b} labels; if mod(b, 5) 0 clusters mergeClusters(clusters, thMerge, sigma2, M); clusters removeExpired(clusters, b, expire); fprintf(batch %d: 当前簇数 %d\n, b, numel(clusters)); end end归一化边界 xmin/xmax 用的是侦察接收机先验范围不是统计得到的最小最大值这保证了特征流里即使后续出现更大范围的新雷达归一化尺度也不会被历史数据带偏。主循环的逻辑是最朴素的在线分配先找最近簇够近就归入不够近就开新簇。注意这里没有遍历所有样本重新分配旧样本符合在线聚类的流式约束。合并函数用簇心核距离判断两个簇是否来自同一辐射源。两个簇心的核距离平方等于 inner_a inner_c 减去 2 倍跨簇核值平均这一步只需要两个簇的缓存就能算。合并后如果缓存超过 M就只保留最近 M 行避免缓存无界增长。过期清理的逻辑更简单一个簇连续 expire 个 batch 都没有新样本命中就认为这部雷达已经关机直接删除。function clusters mergeClusters(clusters, thMerge, sigma2, M) % 贪心合并按簇心核距离从小到大合并每个簇最多参与一次 K numel(clusters); merged false(1,K); newList struct(X,{}, n,{}, inner,{}, lastSeen,{}); for a 1:K if merged(a), continue; end bestC 0; bestD inf; for c a1:K if merged(c), continue; end Xa clusters(a).X; Xc clusters(c).X; D sum(Xa.^2,2) sum(Xc.^2,2) - 2*(Xa*Xc.); D(D0)0; crossMean mean(mean(exp(-D/sigma2))); d2 clusters(a).inner clusters(c).inner - 2*crossMean; if d2 bestD bestD d2; bestC c; end end if bestC 0 bestD thMerge cl clusters(a); cl.X [clusters(a).X; clusters(bestC).X]; cl.n size(cl.X,1); D sum(cl.X.^2,2) sum(cl.X.^2,2) - 2*(cl.X*cl.X.); D(D0)0; cl.inner mean(mean(exp(-D/sigma2))); cl.lastSeen max(clusters(a).lastSeen, clusters(bestC).lastSeen); if cl.n M cl.X cl.X(end-M1:end,:); cl.n M; D sum(cl.X.^2,2) sum(cl.X.^2,2) - 2*(cl.X*cl.X.); D(D0)0; cl.inner mean(mean(exp(-D/sigma2))); end newList(end1) cl; %#okAGROW merged([a bestC]) true; else newList(end1) clusters(a); %#okAGROW merged(a) true; end end clusters newList; end function clusters removeExpired(clusters, bNow, expire) % 连续expire个batch没有被命中的簇直接删除 keep false(1,numel(clusters)); for k 1:numel(clusters) keep(k) (bNow - clusters(k).lastSeen) expire; end clusters clusters(keep); endmergeClusters 用跨簇核均值代替传统质心距离是核空间里的严格度量不会因为缓存里样本数量不同而偏向小簇。这里故意每 5 批才检查一次合并而不是每样本都做是为了避免 O(K²) 的合并扫描拖垮在线吞吐。等到主循环结束你可以用 labels 和真实类别作图检查分选效果能看到三个主要辐射源各自形成完整簇杂散脉冲被分散到边界上的小簇里。4. 参数标定与分选效果评估关键参数和两个指标4.1 四个核心参数的标定顺序在线核聚类有四个参数直接决定分选结果核宽度 σ、新簇阈值 thNew、缓存上限 M、过期代数 expire。调参顺序不能乱我一般先固定 M 和 expire再单独标 σ 和 thNew最后回头调 M。四个参数的失效表现各不相同可用下面这张表做对照参数符号归一化后建议范围调大的后果调小的后果RBF核宽度sigma0.1 ~ 1.0所有簇心距离趋近0簇全部合并任意两个点都像“远邻”每个脉冲都成新簇新簇阈值thNew0.05 ~ 0.3漏掉新开机的雷达新样本强塞进旧簇杂散脉冲也被开簇簇数量暴涨缓存上限M10 ~ 50距离计算变慢旧样本遗忘过慢簇心漂移剧烈雷达一个模式切换就被拆成多簇过期代数expire5 ~ 15关机雷达的僵尸簇长期滞留偶尔丢个 batch 就误删正常簇标定 σ 最直接的依据是看距离分布。先用一批不带噪声的仿真数据跑一遍记录每个样本到最近簇的核距离σ 的取值范围应该让正常归属样本的距离集中在 0.01~0.2 之间。σ 太大时距离普遍趋近 0thNew 怎么调都分不开σ 太小时正常样本的距离也在 0.5 以上每个点都触发新建。对归一化后的三维 PDW 特征0.25~0.35 是个合理起点。thNew 的标定要在 σ 固定后做。它本质上是你对“一个新辐射源离已知簇要多远才算新”的容忍度。我习惯先设一个较大的 thNew 让主循环跑完看簇总数再逐渐减小直到簇总数突然上涨的点就是临界值取临界值的 1.2 倍左右作为工作点。这样既不会漏簇也不会被噪声带偏。4.2 分选效果评估一对一匹配准确率与 ARI评估在线分选结果不能直接拿 labels 和真实编号逐位比较因为第 2 个聚类簇可能对应第 3 部雷达聚类的簇编号是任意的。准确率的正确做法是先把簇和真实类别做一对一匹配再统计正确率。下面的 matchAccuracy 用带约束的贪心匹配保证一个真实类别最多被一个簇认领ARI调整兰德指数则不依赖标签命名直接度量两个划分的相似度是更稳健的指标。function acc matchAccuracy(labels, truth) % 一对一贪心匹配聚类簇与真实类别计算分选准确率 ids unique(labels); K numel(ids); T max(truth); C zeros(K, T1); for i 1:K for t 0:T C(i,t1) sum(labelsids(i) trutht); end end total 0; Ctmp C; for iter 1:K [v, idx] max(Ctmp(:)); if v 0, break; end [i, j] ind2sub(size(Ctmp), idx); total total v; Ctmp(i,:) -1; Ctmp(:,j) -1; % 同一簇/同一真值不可复用 end acc total / numel(labels); end function ari adjRandIndex(labels, truth) % 调整兰德指数不受簇编号命名影响的分选一致性指标 n numel(labels); C full(sparse(labels, truth, 1)); nij C .* (C-1) / 2; si sum((sum(C,2)).*(sum(C,2)-1)/2); sj sum((sum(C,1)).*(sum(C,1)-1)/2); sij sum(nij(:)); tt n*(n-1)/2; ari (sij - si*sj/tt) / (0.5*(sisj) - si*sj/tt); end在主脚本末尾加上评估循环每 10 个 batch 对最近 10 个 batch 的脉冲做一次滑窗评估。滑窗评估能看出聚类性能是否随时间退化而不是只给一个全局平均分。% 每10个batch做一次滑窗评估 nB numel(batchX); for b 10:10:nB lb vertcat(allLabels{b-9:b}); tr vertcat(batchY{b-9:b}); acc matchAccuracy(lb, tr); ari adjRandIndex(lb, tr); fprintf(batch %3d: 分选准确率%.2f, ARI%.2f\n, b, acc, ari); end用默认参数跑完整段仿真准确率通常在 0.9 以上ARI 在 0.85 左右。如果你发现准确率不低但 ARI 明显低说明有某个辐射源被拆成了多个子簇一对一匹配会强行把它们映射到不同类别而同一真实类别内的分割在 ARI 里会被扣分。这时候应该先调合并阈值而不是调新簇阈值。4.3 在线调参的注意点在线场景的调参有个容易忽略的差别离线调参可以对整段数据反复实验在线系统只能看着当前窗口调。仿真阶段我的做法是“离线滚动调参”——先整段跑一遍收集所有 batch 的 labels 和距离统计然后离线微调参数重跑最后再用固定参数做一次真正的在线前向推理。这样既能看到参数对全局分选的影响又不会在真实运行时反复改参数。调参时不要同时动 σ 和 thNew两个参数在距离阈值上的作用是强耦合的同时改会分不清是哪个参数引起的簇数变化。先固定 σ 找到 thNew再小幅调整 σ 看簇数稳定性两个参数交替标定两轮基本就能收敛到一组可用值。5. 在线核聚类分选的常见问题与排查5.1 特征没归一化核函数“失灵”现象σ 从 0.1 试到 5分选准确率始终上不去甚至正常样本之间的核距离比杂散脉冲还大。原因PDW 里三个特征量纲差距太大。RF 在 9~10 GHzPW 在 0.5~2 μsDOA 在 30~70°欧氏距离几乎被 DOA 的数值差主导。RBF 核里的 ‖x-y‖² 算出来PW 的 0.1 μs 差异在 DOA 的 10° 差异面前可以忽略核函数的相似度完全由最大数值的特征决定。解决先做固定物理范围的 min-max 归一化再进入核距离计算。接收机本身知道自己的测频范围、测向范围和脉宽测量范围用这些标称范围归一化即可不要用流式统计的均值方差否则范围外的新雷达样本会把归一化尺度带偏。我前面主脚本里的 xmin/xmax 就是这么设的。5.2 簇数虚增杂散脉冲引发“新建簇雪崩”现象运行到第 20 个 batch 时簇数已经超过 60而真实辐射源只有 3 部大量簇里只有一两个样本。原因杂散噪声脉冲和干扰脉冲离所有已知簇的核距离都远thNew 一宽松就直接触发新建簇。噪声脉冲在特征空间里均匀分布每来一个都可能开一个新簇而这些簇之后几乎没有后续样本命中既影响距离比较效率也会在评估时被误认为辐射源。解决给新建簇加一个“观察期”不要一出现就转正。可以给簇结构加一个 pendingN 字段新建簇先标记为临时簇只有累计命中超过 5 个样本才参与合并和距离比较否则只是在等待期内做累积。另一个办法是把 thNew 从临界值往上调 20%让少量噪声点直接归到最近的大簇里去代价是微弱噪声点会把簇心稍微带偏。工程上我倾向于两者结合thNew 适当放大同时对临时簇做最小样本数过滤。5.3 距离计算越跑越慢缓存和核矩阵失控现象前 20 个 batch 每批处理时间还能接受跑到 40 批以后明显卡顿延迟从几十毫秒涨到几百毫秒。原因两个地方失控。一是某个簇的缓存样本没有被 M 限制住内部核矩阵重算或者 inner 没有增量维护导致距离计算退化成 O(M²)。二是临时簇太多每个样本都要和全部 K 个簇做一次距离计算当 K 从 3 涨到 100单样本延迟线性恶化。解决缓存超限要通过 addToCluster 里的丢最旧逻辑严格截断合并后的缓存也要重新截断到 M。簇数量控制要靠 expire 删除和合并检查同时给每个样本增加一个候选簇预筛先用 RF、DOA 两个特征做粗略的区间过滤只有落在候选范围内的簇才计算核距离核聚类本质上是精细判定不应该承担全局搜索的任务。我通常会把“粗筛候选簇数”限制在 5 个以内在线吞吐能稳定提升数倍。5.4 簇心追不上雷达参数跳变现象某部雷达在第 30 个 batch 切换工作模式RF 中心跳变了 0.6 GHz之后的脉冲被反复开新簇又合并稳定下来需要十多个 batch。原因在线簇心像完全由缓存里最近 M 个样本决定跟踪能力其实不差。但合并检查间隔太长或者 M 设置得偏大时旧模式的样本还留在缓存里把簇心钉在两个模式之间导致新模式脉冲持续距离超阈值。解决把合并检查从每 5 批缩短到每 2 批代价是集群合并扫描频率升高。另一种做法是让缓存带时间衰减权重——丢弃样本时优先丢弃离当前时间最远的而不是单纯丢最旧前面的 addToCluster 丢最旧已经实现了时间遗忘但 M 较大时反应偏慢。雷达参数快变的场景建议 M 取 10~15让簇心像大约只保留最近 10~15 个脉冲的记忆模式切换基本能在 2 个 batch 内收敛。5.5 评估结果和真值对不上标签错位现象分选准确率算出来只有 30%但看聚类图明显三个辐射源分得很清楚。原因评估代码直接把聚类簇编号和真实辐射源编号做了逐位相等比较。在线聚类过程中簇的编号会随新建、合并、删除而变化第 5 号簇可能上一批还是第 2 部雷达这批合并后已经变成第 3 部雷达。编号是逻辑标识不是身份标识。解决任何在线聚类评估都必须先做簇-真值匹配再算准确率。matchAccuracy 和 adjRandIndex 这两个函数一个做一对一映射一个完全绕开标签命名问题用它们就能避开这个坑。注意 matchAccuracy 虽然带约束贪心但严格场景应该用匈牙利算法做全局最优匹配尤其是当簇数很多、两个簇同时对一个真值类别都超过 50% 时贪心可能选错映射方向ARI 此时更可靠。6. 进阶用离线重标定验证在线簇结构在线聚类有一个始终让人不放心的点簇心像一直在被增量更新你怎么确认它没有慢慢“跑偏”我习惯每隔一段窗口做一次离线核 k-means 重标定用同样的归一化特征、同样的核参数把最近一段时间的脉冲重新离线聚类然后和在线结果做一致性对比。这个技巧不需要改动在线主循环只把当前的簇数量作为候选 K跑一个有限的批处理核 k-means。function consistency offlineRefitCheck(winX, onlineLabels, sigma, Krange) % 离线重标定用批处理核K均值重分最近窗口与在线结果比较ARI n size(winX,1); D sum(winX.^2,2) sum(winX.^2,2) - 2*(winX*winX.); D(D0)0; Kmat exp(-D/(2*sigma^2)); bestARI 0; for K Krange rng(7); label randi(K, n, 1); % 随机初始化 for it 1:20 dist zeros(n,K); for k 1:K mk find(labelk); if isempty(mk) dist(:,k) inf; else dist(:,k) 1 - 2*mean(Kmat(:,mk),2) ... mean(mean(Kmat(mk,mk))); end end [~, label] min(dist, [], 2); end ari adjRandIndex(label, onlineLabels); bestARI max(bestARI, ari); end consistency bestARI; end调用时取最近 10 个 batch 的归一化特征拼接成 winXKrange 用在线簇数的上下各 1 个值比如在线当前有 4 个簇就试 3、4、5。如果 bestARI 超过 0.9说明在线缓存的簇结构和离线全量聚类高度一致分选是可信的如果低于 0.85说明在线簇心漂移明显优先调 M 和合并阈值而不是盲目加大 thNew。这个离线重标定还有一个用处给新簇确认身份。在线新出现一个簇时可以用离线重标定的结果回看一眼如果这个新簇在离线结果里被拆散进多个大簇它多半是杂散脉冲如果离线结果里它独立成簇才值得在后续 batch 中保留并持续观察。我每次跑完仿真都会保留最后一批的簇缓存用它做一次重标定再下结论分选指标看得见簇结构也经得起复核。希望这套代码和调参路径能帮你在雷达辐射源在线分选上少走几步弯路。本文还有配套的精品资源点击获取