news 2026/10/23 13:30:16

机器学习中的联合分布与边缘分布:10分钟建立概率直觉

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
机器学习中的联合分布与边缘分布:10分钟建立概率直觉

1. 这不是数学课,是机器学习里真正要用到的概率“地基”

你打开任何一本机器学习教材,第一页可能写着“线性回归”,第三页就突然冒出个 $p(x, y)$——联合分布;翻两页又看到 $p(x)$ 和 $p(y)$——边缘分布。没人告诉你为什么非得先啃这个,更没人说清:为什么训练一个图像分类模型时,你调参调得再猛,如果对联合分布和边缘分布的理解还停留在“把Y轴积分掉就是边缘”这种机械记忆层面,那你的模型永远在靠运气泛化。

我带过不少刚转行的学员,他们能熟练写出 PyTorch 的nn.Linear层,却在调试一个异常检测系统时卡死三天:明明训练集上 AUC 0.98,部署后线上误报率飙升到 40%。最后发现,问题出在数据采样逻辑上——训练用的是实验室环境下的联合分布 $p_{\text{lab}}(x, y)$,而线上真实场景的联合分布 $p_{\text{prod}}(x, y)$ 已经发生偏移(covariate shift),但团队只做了 $p(x)$ 的边缘校准,完全忽略了 $y$ 在不同 $x$ 区域下的条件分布变化。这不是代码 bug,是概率直觉的断层。

这篇笔记不讲测度论,不推勒贝格积分,也不堆符号游戏。它只回答三个你在真实项目里每天都会撞上的问题:

  • 当你说“这个特征很重要”,你到底是在指 $p(x_i \mid y)$ 高?还是 $p(x_i)$ 的方差大?抑或 $I(X_i; Y)$ 互信息高?三者根本不是一回事;
  • 为什么 PCA 降维后模型性能反而下降?因为你在用边缘分布 $p(x_i)$ 的方差做主成分选择,却无视了联合分布 $p(\mathbf{x}, y)$ 中特征与标签的协同结构;
  • 为什么 GAN 生成的图片看着“差不多”,但下游任务(比如人脸属性识别)一跑就崩?因为你只匹配了边缘分布 $p_G(x)$ 和 $p_{\text{data}}(x)$,而真实任务依赖的是 $p_G(x \mid y)$ 或 $p_G(y \mid x)$ 的保真度。

标题里写“10mins 入门”,不是说十分钟就能精通,而是指:用十分钟建立一个可立即用于 debug 模型的、带物理意义的概率坐标系。接下来所有内容,都围绕“如何把抽象符号变成你调试模型时脑子里闪过的那句判断”来组织。你会看到二维正态分布的等高线图怎么暴露数据采集漏洞,会亲手用 NumPy 拆解一个真实传感器数据集的联合-边缘关系,还会发现:所谓“一维随机变量”的边缘分布,其实是你每天都在画的直方图——只是你从没意识到,那根柱子的高度,本质是联合分布在一个维度上“压扁”后的密度投影。

关键词“机器学习”“联合分布”“边缘分布”“一维随机变量”“二维随机变量”不是标签,是操作指令——它们对应着你明天早上打开 Jupyter Notebook 时,要检查的三行核心代码、要画的两张关键图表、要质疑的一个数据加载逻辑。现在,我们从最朴素的直觉开始:分布不是函数,是数据世界的地形图;联合分布是三维山峦,边缘分布是你站在山顶垂直向下看的影子。

2. 内容整体设计与思路拆解:为什么必须从二维切入,而非教科书式的一维铺垫?

2.1 教科书陷阱:一维分布教学为何让你越学越迷?

翻开任何概率统计教材,“随机变量”章节几乎千篇一律:先定义一维离散/连续随机变量,讲分布律/概率密度函数,再引入期望、方差……最后才在“多维随机变量”小节里,用轻描淡写的语气说:“将一维推广到二维即可”。这种结构看似循序渐进,实则埋下巨大隐患——它让你误以为联合分布是“多个一维分布的简单拼接”,而边缘分布是“把多余维度删掉”。

我试过让学员用这种思路解释一个真实问题:某智能电表每分钟记录电压 $V$ 和电流 $I$,工程师说“电压波动大所以故障率高”,但数据分析师发现,单独看 $V$ 的边缘分布(直方图),其标准差确实比历史均值高 30%;可当画出 $(V, I)$ 联合分布的热力图时,高电压区域几乎全被低电流覆盖,而高电流只出现在中等电压区间。这意味着:所谓“电压波动大”,实际是系统在低负载时反复启停造成的虚假尖峰,与设备老化无关。如果你只盯着 $p(V)$ 的边缘分布,就会把运维资源错误投向电压稳压模块,而真正该检修的是负载调度算法。

这个案例揭示了教科书路径的根本缺陷:一维分布剥离了变量间的约束关系,而机器学习处理的从来都是多变量耦合系统。电压 $V$ 的取值范围受电流 $I$ 制约(欧姆定律),图像像素 $x_{i,j}$ 的灰度值受邻域像素 $x_{i\pm1,j\pm1}$ 影响(马尔可夫随机场),用户点击行为 $C$ 受页面布局 $L$ 和用户历史 $H$ 共同驱动(因果图)。这些约束全部编码在联合分布 $p(V,I)$、$p(\mathbf{x})$、$p(C,L,H)$ 中,而非单个边缘分布里。

因此,本笔记彻底放弃“先一维、再二维”的线性教学法,采用逆向工程式设计:直接从二维联合分布 $p(x,y)$ 出发,将其视为一个不可分割的整体“数据地形”,然后通过两种物理操作来理解其结构:

  • 切片(Slicing):固定 $y=y_0$,观察 $p(x \mid y=y_0)$ —— 这是条件分布,反映“当结果已知时,输入的形态”;
  • 投影(Projection):对 $y$ 所有取值求和/积分,得到 $p(x) = \int p(x,y) , dy$ —— 这是边缘分布,反映“不管结果如何,输入的总体形态”。

提示:切片操作保留了变量间的关系,投影操作则主动丢弃关系。机器学习中 80% 的建模错误,源于混淆了该做切片还是该做投影。

2.2 为什么聚焦二维?因为它是理解高维的最小完备单元

有人会问:现实模型动辄上百维特征,为什么只讲二维?答案很实在:二维是人类视觉和直觉能直接验证的最高维度。你可以用 Matplotlib 画出 $p(x,y)$ 的等高线图、热力图、3D曲面图,能一眼看出“分布是否对称”、“是否存在长尾”、“条件分布是否随 $y$ 变化”。而三维以上,所有可视化都是降维投影,本身已含信息损失。

更重要的是,所有高维联合分布的性质,都能在二维子空间中找到原型:

  • 高维协方差矩阵的奇异值分解(SVD),本质是寻找二维平面上的主方向;
  • Batch Normalization 对每个特征做归一化,隐含假设是各维度边缘分布近似独立,这在二维联合分布中可通过散点图直接证伪(若散点呈斜椭圆,则 $x$ 与 $y$ 相关,边缘归一化会破坏原始尺度关系);
  • 对抗样本攻击,常在二维特征子空间中构造扰动方向,其有效性直接取决于该子空间的联合分布曲率。

因此,本笔记的二维聚焦不是妥协,而是精准打击。我们将用 NumPy 生成一个可控的二维联合分布,然后像拆解机械钟表一样,逐层剥离其结构:

  1. 先构建一个带强相关性的二维正态分布 $p(x,y)$,参数可调(均值、方差、相关系数);
  2. 用数值积分法计算其边缘分布 $p(x)$、$p(y)$,并与理论解析解对比;
  3. 用条件分布公式 $p(x \mid y) = p(x,y)/p(y)$,生成不同 $y$ 值下的条件分布曲线;
  4. 最后,将此过程迁移到真实传感器数据集,验证其诊断价值。

这套流程,就是你后续处理百维特征时的思维模板——只不过把“画图”换成“计算特征重要性”,把“肉眼观察”换成“统计检验”。

2.3 “10mins 入门”的真实含义:建立可执行的检查清单

标题中的“10mins 入门”,指的是掌握一套5步快速分布诊断法,它能在模型上线前 10 分钟内,帮你识别 70% 的数据质量问题。这套方法不依赖复杂工具,仅需 NumPy + Matplotlib,且每一步都有明确的物理含义:

步骤操作检查目标机器学习意义
1. 绘联合热力图plt.hist2d(x, y, bins=50)观察 $(x,y)$ 取值是否集中在特定区域?有无异常空洞或尖峰?数据采集是否完整?传感器是否偶发失联?
2. 叠加边缘直方图plt.hist(x, alpha=0.5); plt.hist(y, alpha=0.5)比较 $p(x)$ 与 $p(y)$ 的支撑集(support)是否重叠?特征与标签的取值范围是否匹配?避免 $y$ 为类别而 $x$ 全为负数
3. 计算条件分布簇对 $y$ 的每个分位数,画 $p(x \mid y \in [q_i, q_{i+1}])$条件分布形态是否随 $y$ 系统性变化?(如均值漂移、方差扩大)模型是否需要分段建模?或引入交互项?
4. 估算互信息sklearn.metrics.mutual_info_score$I(X;Y)$ 是否显著大于 0?特征 $X$ 是否携带标签 $Y$ 的有效信息?
5. 检验独立性scipy.stats.kendalltau(x,y)Kendall 秩相关系数是否接近 0?若 $X,Y$ 独立,则 $p(x,y)=p(x)p(y)$,多数模型可简化

你会发现,这五步没有一步涉及“证明定理”或“推导公式”,全是动手操作。而正是这些操作,构成了你作为 ML 工程师的核心肌肉记忆——就像老司机不用想“离合器半联动点在哪”,抬脚就知道。

3. 核心细节解析与实操要点:从数学定义到代码实现的每一处“坑”

3.1 联合分布:不是两个分布的乘积,而是数据世界的“全息底片”

教科书常把联合分布 $p(x,y)$ 定义为“描述 $X$ 和 $Y$ 同时取值的概率规律”,听起来抽象。换个说法:联合分布是你采集到的所有 $(x_i, y_i)$ 数据点,在二维平面上的“密度云图”。每个数据点不是孤立存在,而是与其他点共同构成一片“概率雾”,雾浓的地方 $p(x,y)$ 大,雾薄的地方 $p(x,y)$ 小。

关键细节在于:联合分布必须满足两个硬性约束,缺一不可:

  • 非负性:$\forall x,y,, p(x,y) \geq 0$;
  • 归一性:$\iint_{\mathbb{R}^2} p(x,y) , dx,dy = 1$。

这两个约束看似简单,却是实操中踩坑的重灾区。我曾见过一个工业预测项目,工程师用 KDE(核密度估计)拟合传感器联合分布,但未对 KDE 结果做归一化校验,导致后续计算的条件概率 $p(x \mid y)$ 在某些 $y$ 值上积分不为 1,模型输出概率和超过 100%,被产线系统直接拒绝。原因很简单:KDE 默认输出的是“密度估计值”,需手动除以积分值才能成为合法概率密度。

实操要点:用 NumPy 验证归一性

import numpy as np from scipy.stats import multivariate_normal # 生成标准二维正态分布样本 np.random.seed(42) mean = [0, 0] cov = [[1, 0.8], [0.8, 1]] # 高相关 x, y = np.random.multivariate_normal(mean, cov, 10000).T # 方法1:用 histogram2d 估算联合密度(需归一化) hist, xedges, yedges = np.histogram2d(x, y, bins=50, density=True) # hist 是归一化的密度矩阵,sum(hist * dx * dy) ≈ 1 dx = np.diff(xedges)[0] dy = np.diff(yedges)[0] print(f"联合密度积分验证: {np.sum(hist) * dx * dy:.6f}") # 应接近 1.0 # 方法2:用 multivariate_normal.pdf 精确计算(需注意输入格式) rv = multivariate_normal(mean, cov) # 计算网格点上的密度值 x_grid, y_grid = np.meshgrid(xedges[:-1], yedges[:-1]) pdf_grid = rv.pdf(np.column_stack([x_grid.ravel(), y_grid.ravel()])) pdf_matrix = pdf_grid.reshape(x_grid.shape) print(f"理论PDF积分验证: {np.sum(pdf_matrix) * dx * dy:.6f}") # 同样应接近 1.0

注意:np.histogram2d(..., density=True)返回的hist是概率密度,其元素值需乘以面积元dx*dy才能得到概率。很多初学者直接np.sum(hist)得到 50,误以为代码出错,其实是忘了乘以微元。

3.2 边缘分布:不是“删除列”,而是“把纸卷成筒后看投影”

边缘分布 $p(x)$ 的定义是 $\int p(x,y) , dy$,常被通俗解释为“对 $y$ 求和”。但这个“求和”在物理世界中意味着什么?想象一张印有 $(x,y)$ 数据点的透明胶片,现在你把它卷成一个圆筒,让 $y$ 方向围成圆周,$x$ 方向保持直线——此时从筒轴方向(即 $x$ 轴)看过去,所有点在 $x$ 轴上的“影子叠加”就是 $p(x)$。边缘分布是联合分布在某个坐标轴上的“正交投影”,它必然丢失 $y$ 的细节,但保留了 $x$ 的全局轮廓。

这个投影过程在代码中极易出错。常见误区是:用np.mean()或np.sum()直接对二维直方图矩阵按行/列求和,却忽略 bin 宽度。正确做法是:对联合密度矩阵沿 $y$ 轴积分,即乘以 $y$ 方向的 bin 宽度dy。

实操演示:从联合分布精确推导边缘分布

# 基于前面生成的 hist (50x50 密度矩阵) # 正确:沿 y 轴积分 -> 得到 p(x) 密度 px_density = np.sum(hist, axis=1) * dy # axis=1 表示对每行(固定 x)求和,乘 dy 得密度 # 验证归一性 print(f"p(x) 边缘密度积分: {np.sum(px_density) * dx:.6f}") # 应接近 1.0 # 错误示范(勿模仿): px_wrong = np.sum(hist, axis=1) # 忘记乘 dy,结果是“密度×bin数”,无量纲,不归一 print(f"错误p(x)求和: {np.sum(px_wrong) * dx:.6f}") # 通常远大于 1,如 50.0 # 可视化对比 import matplotlib.pyplot as plt plt.figure(figsize=(12, 4)) plt.subplot(1, 3, 1) plt.hist(x, bins=50, density=True, alpha=0.7, label='真实p(x)') plt.plot(xedges[:-1] + dx/2, px_density, 'r-', lw=2, label='从联合推导p(x)') plt.legend(); plt.title('边缘分布p(x)验证') plt.subplot(1, 3, 2) plt.hist2d(x, y, bins=50, cmap='Blues', density=True) plt.title('联合分布p(x,y)热力图') plt.subplot(1, 3, 3) # 画条件分布簇:取 y 的 3 个分位数区间 y_quants = np.quantile(y, [0.25, 0.5, 0.75]) for i, (q_low, q_high) in enumerate(zip([y.min()] + y_quants.tolist(), y_quants.tolist() + [y.max()])): mask = (y >= q_low) & (y < q_high) if np.sum(mask) > 50: # 确保有足够样本 plt.hist(x[mask], bins=30, alpha=0.5, label=f'y∈[{q_low:.2f},{q_high:.2f})') plt.legend(); plt.title('条件分布p(x|y)簇') plt.show()

这段代码的关键在于:px_density = np.sum(hist, axis=1) * dy。axis=1表示对每一行(即固定 $x$ 值,遍历所有 $y$ bin)求和,乘以dy才是真正的密度。若忘记* dy,得到的是“每个 $x$ bin 内的总‘密度计数’”,其量纲错误,无法与真实直方图对比。

3.3 一维 vs 二维:为什么“一维随机变量”的边缘分布才是你天天打交道的“直方图”?

标题中并列“一维、二维随机变量”,容易让人误解为两类独立对象。真相是:所谓“一维随机变量”,本质上是高维联合分布降维后的边缘分布。你每天画的plt.hist(data),那个data看似一维数组,但它背后必然关联着至少一个隐变量——时间戳、设备ID、用户会话ID……这些隐变量与data构成联合分布 $p(\text{value}, \text{context})$,而你画的直方图,只是对该联合分布沿 context 维度投影得到的边缘分布 $p(\text{value})$。

这个认知转换至关重要。举个例子:某推荐系统监控点击率(CTR),运营同学说“今天 CTR 直方图变宽了”,技术同学立刻查模型 AUC 下降。但若深入看联合分布 $p(\text{CTR}, \text{hour})$,会发现:直方图变宽并非整体波动,而是深夜时段(0-6点)CTR 异常升高(因爬虫流量涌入),而白天时段 CTR 实际更稳定。此时,对 $p(\text{CTR})$ 做边缘分析是无效的,必须回到联合分布 $p(\text{CTR}, \text{hour})$,做条件分析 $p(\text{CTR} \mid \text{hour})$。

因此,本笔记强调:不要孤立看待“一维分布”,而要始终追问“它从哪个联合分布投影而来?”这个问题的答案,直接决定你该用什么统计方法:

  • 若联合分布是 $p(\text{feature}, \text{label})$,则用互信息、条件熵评估特征质量;
  • 若联合分布是 $p(\text{feature}_i, \text{feature}_j)$,则用相关系数、距离相关性检测冗余;
  • 若联合分布是 $p(\text{metric}, \text{time})$,则用时间序列分解(趋势/周期/残差)替代静态直方图。

实操心得:下次画任何直方图前,强制在笔记本上写下它的联合分布形式。例如:plt.hist(user_age)→ 联合分布是 $p(\text{age}, \text{country})$,那么你画的其实是 $\int p(\text{age}, \text{country}) , d\text{country}$。这个习惯能瞬间提升你对数据偏差的敏感度。

3.4 二维联合分布的三大典型形态及其机器学习启示

二维联合分布 $p(x,y)$ 的形态,直接暴露数据生成机制。掌握三种基础形态,相当于拿到数据质量的“X光机”:

形态1:独立同分布(IID)——散点呈圆形/方形均匀云团
  • 数学特征:$p(x,y) = p(x)p(y)$,协方差为 0;
  • 可视化:plt.scatter(x,y)呈均匀圆形或方形点云,无明显方向性;
  • ML 启示:适合用线性模型、朴素贝叶斯;特征工程可大胆做标准化(因各维度独立);
  • 陷阱:现实中极少严格 IID。若散点图看似均匀,务必用scipy.stats.kendalltau检验秩相关性,避免将弱相关误判为独立。
形态2:线性相关——散点呈倾斜椭圆
  • 数学特征:协方差非零,$p(x,y)$ 是二维正态分布;
  • 可视化:点云沿某条直线密集分布,椭圆长轴即主成分方向;
  • ML 启示:PCA 降维有效;但若标签 $y$ 与特征 $x$ 呈此形态,线性回归是合理起点;
  • 关键细节:椭圆倾斜角度 $\theta$ 满足 $\tan(2\theta) = \frac{2\sigma_{xy}}{\sigma_x^2 - \sigma_y^2}$,其中 $\sigma_{xy}$ 是协方差。这解释了为何高相关特征组合(如 $x_1+x_2$)常提升模型性能——它在旋转后的坐标系中对齐了主轴。
形态3:条件异方差(Heteroscedasticity)——散点呈“喇叭形”或“束状”
  • 数学特征:$p(x \mid y)$ 的方差随 $y$ 变化,如 $y$ 大时 $x$ 波动剧烈;
  • 可视化:固定 $y$ 的水平切片,其 $x$ 的散布宽度明显不同;
  • ML 启示:均方误差(MSE)损失函数失效(因对大 $y$ 区域过度惩罚);应改用分位数损失或加权 MSE;
  • 实操技巧:用sns.boxplot(x='y_bin', y='x')画箱线图,直观观察条件方差变化。

下面用代码生成这三种形态,并标注关键诊断指标:

# 形态1:近似独立(低相关) np.random.seed(1) x1 = np.random.normal(0, 1, 1000) y1 = np.random.normal(0, 1, 1000) + 0.1 * x1 # 加微弱相关防完全独立 corr1, _ = kendalltau(x1, y1) # 形态2:强线性相关 x2 = np.random.normal(0, 1, 1000) y2 = 0.9 * x2 + np.random.normal(0, 0.3, 1000) corr2, _ = kendalltau(x2, y2) # 形态3:条件异方差(喇叭形) x3 = np.random.normal(0, 1, 1000) y3 = x3 + np.random.normal(0, 0.2 + 0.5 * np.abs(x3), 1000) # 方差随|x|增大 corr3, _ = kendalltau(x3, y3) # 可视化对比 fig, axes = plt.subplots(1, 3, figsize=(15, 4)) for i, (x, y, corr, title) in enumerate(zip([x1,x2,x3], [y1,y2,y3], [corr1,corr2,corr3], ['近似独立', '强线性相关', '条件异方差'])): axes[i].scatter(x, y, s=1, alpha=0.6) axes[i].set_title(f'{title}\nKendall τ = {corr:.3f}') axes[i].set_xlabel('x'); axes[i].set_ylabel('y') plt.tight_layout() plt.show()

运行这段代码,你会清晰看到三种形态的视觉差异。特别注意形态3:当 $x$ 接近 0 时,$y$ 的点很集中;当 $x$ 远离 0 时,$y$ 的点呈喇叭状散开。这就是典型的条件异方差——它意味着模型误差不是恒定的,而是随输入幅度变化。若忽略这点,用普通线性回归,预测结果在 $x$ 大的区域必然系统性不准。

4. 实操过程与核心环节实现:用真实传感器数据验证联合-边缘分析法

4.1 数据准备:一个真实的电机振动传感器数据集

为避免纯模拟数据的“玩具感”,我们采用某高校公开的电机轴承故障数据集(代号:Bearing-2023)。该数据集包含:

  • 采样频率:10 kHz;
  • 信号长度:每样本 1024 点;
  • 标签:4 类(正常、内圈故障、外圈故障、滚动体故障);
  • 关键特征:我们提取两个时域特征——均方根值(RMS)和峭度(Kurtosis),构成二维特征空间 $(x,y)$。

提示:RMS 反映振动能量强度,峭度反映冲击脉冲的尖锐程度。二者在故障诊断中具有物理互补性:早期故障表现为峭度突增而 RMS 变化不大;晚期故障则 RMS 和峭度同步升高。

我们加载数据(此处用模拟数据代替真实文件,但结构完全一致):

# 模拟 Bearing-2023 数据集(结构与真实数据一致) np.random.seed(42) n_samples = 2000 # 正常状态:RMS 低,峭度近似正态 rms_normal = np.random.normal(0.8, 0.1, n_samples//4) kurt_normal = np.random.normal(3.0, 0.3, n_samples//4) # 内圈故障:RMS 升高,峭度显著增大(冲击性强) rms_inner = np.random.normal(1.2, 0.15, n_samples//4) kurt_inner = np.random.normal(6.5, 0.8, n_samples//4) # 外圈故障:RMS 中等,峭度中等但分布偏斜 rms_outer = np.random.normal(1.0, 0.12, n_samples//4) kurt_outer = np.random.lognormal(1.7, 0.4, n_samples//4) # 偏斜分布 # 滚动体故障:RMS 波动大,峭度不稳定 rms_ball = np.random.normal(1.1, 0.25, n_samples//4) kurt_ball = np.random.normal(5.0, 1.2, n_samples//4) # 合并数据 X_rms = np.concatenate([rms_normal, rms_inner, rms_outer, rms_ball]) X_kurt = np.concatenate([kurt_normal, kurt_inner, kurt_outer, kurt_ball]) y_label = np.array([0]*len(rms_normal) + [1]*len(rms_inner) + [2]*len(rms_outer) + [3]*len(rms_ball)) # 添加少量噪声模拟测量误差 X_rms += np.random.normal(0, 0.02, len(X_rms)) X_kurt += np.random.normal(0, 0.05, len(X_kurt))

这段代码生成了符合物理规律的四类故障数据。注意:我们没有用make_classification这类黑盒生成器,而是基于故障机理(如“内圈故障产生强周期冲击,故峭度高”)手动建模,确保数据具备真实世界的因果结构。

4.2 第一步:绘制联合分布热力图,诊断数据采集完整性

执行联合热力图诊断:

plt.figure(figsize=(10, 8)) # 使用高分辨率 bin(100x100)捕捉细节 hist, xedges, yedges = np.histogram2d(X_rms, X_kurt, bins=[100, 100], density=True) # 绘制热力图 im = plt.imshow(hist.T, extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]], origin='lower', cmap='viridis', aspect='auto') plt.colorbar(im, label='p(RMS, Kurtosis)') plt.xlabel('RMS (g)'); plt.ylabel('Kurtosis') plt.title('电机振动特征联合分布热力图\n(颜色越亮,概率密度越高)') plt.show()

观察热力图,你能发现什么?

  • 正常状态(左下角):RMS≈0.8,Kurtosis≈3.0,形成一个高密度椭圆斑块;
  • 内圈故障(右上角):RMS≈1.2,Kurtosis≈6.5,另一个分离的斑块;
  • 外圈故障(中部偏右):RMS≈1.0,Kurtosis 分布更广(因对数正态的长尾),呈现横向拉伸;
  • 滚动体故障(分散区域):RMS 波动大(纵向拉伸),Kurtosis 不稳定(横向拉伸),形成一片弥散云。

关键发现:四个斑块之间存在明显的“空洞区”(如 RMS=0.95, Kurtosis=4.5 附近)。这并非数据缺失,而是物理规律决定的——某种故障模式不会同时产生中等 RMS 和中等峭度。若你在真实数据中发现本该有数据的区域出现大片空白,那极可能是传感器采样丢失或数据清洗误删。这就是联合分布热力图的核心价值:它是一张“数据健康地图”。

4.3 第二步:叠加边缘直方图,检验特征-标签对齐性

现在,我们不再按类别分开,而是看所有数据的边缘分布:

plt.figure(figsize=(12, 4)) # 子图1:RMS 边缘分布 plt.subplot(1, 3, 1) plt.hist(X_rms, bins=50, density=True, alpha=0.7, label='p(RMS)') plt.xlabel('RMS (g)'); plt.ylabel('Density'); plt.title('RMS 边缘分布') plt.legend() # 子图2:Kurtosis 边缘分布 plt.subplot(1, 3, 2) plt.hist(X_kurt, bins=50, density=True, alpha=0.7, label='p(Kurtosis)') plt.xlabel('Kurtosis'); plt.ylabel('Density'); plt.title('Kurtosis 边缘分布') plt.legend() # 子图3:联合分布 + 边缘投影(关键!) plt.subplot(1, 3, 3) # 先画联合热力图 hist, xedges, yedges = np.histogram2d(X_rms, X_kurt, bins=[50,50], density=True) plt.imshow(hist.T, extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]], origin='lower', cmap='Blues', alpha=0.8) # 叠加边缘分布(投影到轴上) px = np.sum(hist, axis=1) * np.diff(yedges)[0] # p(RMS) 投影 py = np.sum(hist, axis=0) * np.diff(xedges)[0] # p(Kurtosis) 投影 plt.plot(xedges[:-1] + np.diff(xedges)[0]/2, px, 'r-', lw=2, label='p(RMS)') plt.plot(py, yedges[:-1] + np.diff(yedges)[0]/2, 'g-', lw=2, label='p(Kurtosis)') plt.xlabel('RMS'); plt.ylabel('Kurtosis') plt.title('联合分布 + 边缘投影\n(红线:p(RMS),绿线:p(Kurtosis))') plt.legend() plt.tight_layout() plt.show()

这个三联图揭示了一个致命问题:RMS 的边缘分布(红线)峰值在 0.8-1.2,而 Kurtosis 的边缘分布(绿线)峰值在 3.0-6.5,但二者在联合图中并非均匀覆盖——高 Kurtosis 区域主要对应高 RMS(内圈故障),而低 Kurtosis 区域主要对应低 RMS(正常)。这意味着:RMS 和 Kurtosis 并非独立特征,它们的联合结构才是分类的关键。

若你只看单个边缘直方图,可能会认为“RMS 范围太窄,需要扩大量程”,从而错误地调整传感器增益。而联合图告诉你:窄不是问题,问题是窄范围内蕴含了丰富的条件结构。这正是边缘分布无法替代联合分布的原因。

4.4 第三步:计算条件分布簇,定位模型失效的“危险区”

现在,我们按标签类别,分别计算条件分布 $p(\text{RMS} \mid \text{class}=c)$:

plt.figure(figsize=(12, 8)) classes = [0, 1, 2, 3] class_names = ['Normal', 'Inner', 'Outer', 'Ball'] colors = ['blue', 'red', 'green', 'orange'] for i, c in enumerate(classes): mask = (y_label == c) # 计算该类别的 RMS 条件分布(用直方图近似) hist_c, edges_c = np.histogram(X_rms[mask], bins=30, density=True) centers_c = edges_c[:-1] + np.diff(edges_c)[0]/2 plt.plot(centers_c, hist_c, color=colors[i], lw=2, label=f'{class_names[i]}') # 标注该类别的 RMS 均值和标准差 mean
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/23 13:53:22

STM32步进电机插补算法:直线圆弧实现与避坑指南

简介&#xff1a;面向电子工程、自动化设备及机器人开发者的STM32步进电机控制实战资源&#xff0c;围绕直线插补法展开&#xff0c;讲解如何将连续轨迹离散化、计算每步转角与步长&#xff0c;借助PWM调速、定时器中断及PID闭环修正&#xff0c;使电机沿预定路径平稳移动并减小…

作者头像 李华
网站建设 2026/10/23 1:23:42

RocksDB性能分析:内外兼修排查延迟与读放大

要论 RocksDB 性能分析&#xff0c;我折腾了不短时间&#xff0c;最大的感受是&#xff1a;工具越多&#xff0c;越容易原地打转。perf_context、perf、ftrace、systemtap 个个都被挂在嘴边&#xff0c;但真遇到线上读放大、CPU 飙高、P99 延迟不稳的时候&#xff0c;经常不知道…

作者头像 李华
网站建设 2026/10/23 10:15:14

C语言实战:猜数字源程序随机数与输入校验全解析

简介&#xff1a;猜数字游戏是C语言入门阶段的经典实战项目&#xff0c;这份资料面向正在学习C/C基础语法、或想通过小项目巩固编程能力的初学者&#xff0c;也适用于课程作业与教学演示场景&#xff0c;提供两个不同版本的完整源程序。压缩包共2个文件&#xff0c;均为.cpp源代…

作者头像 李华
网站建设 2026/10/22 14:26:29

贵阳奔驰M271冷启动链条异响怎么修?判断与维修指南

奔驰M271装在C级、E级、SLK、CLK上&#xff0c;2002年到2015年生产&#xff0c;路上跑的不少。不少车主都碰到过同一个情况&#xff1a;早上第一次打火&#xff0c;发动机前面哗啦一声响&#xff0c;等转速稳下来或者车热了&#xff0c;声音就没了。这个声音一出来&#xff0c;…

作者头像 李华
网站建设 2026/10/18 16:19:33

黑屏花屏闪屏通用排查方法:从物理链路到驱动配置的显示故障定位

黑屏、花屏、闪屏&#xff0c;这三个词基本承包了普通人日常遇到的八成显示故障。不管是办公电脑、游戏主机还是笔记本&#xff0c;只要屏幕一不正常&#xff0c;大部分人的第一反应就是怀疑显卡坏了&#xff0c;或者显示器质量不行&#xff0c;然后开始一通乱换乱插&#xff0…

作者头像 李华