AI诊断天车故障,凭什么这么判——Grad-CAM/SHAP让深度学习决策过程透明化
📌 天车AI故障诊断的”黑箱”问题正在被两种可解释性技术破解:Grad-CAM生成热力图告诉操作员模型”看”了哪个传感器区域,SHAP定量回答每个输入特征对诊断结论的贡献值。克鲁德重工在某钢厂连铸跨5台QD32/5t天车上部署双方法集成系统后,操作员对AI诊断的采纳率从初始62%提升至94%,非计划停机降低61%。技术核心在于:Grad-CAM提供空间定位(”卷筒轴承座振动频带1.2~2.4kHz被我关注”),SHAP提供归因排序(”V1_RMS贡献+0.32,V2_峭度贡献+0.21″),二者互补构成完整的诊断证据链。
深度学习模型(CNN/GNN)在天车故障诊断中已达F1>0.97的精度,但绝大多数工业用户无法接受”模型说故障就故障”的黑箱决策。合规角度:GB/T 41867-2022《人工智能 可解释性 术语和分类》明确要求高风险AI系统提供决策解释。实操角度:操作员需要知道AI为什么判轴承故障——是振动频率对了还是电流波形变了——才能信任并执行维护指令。
本文基于克鲁德重工在12台天车上部署的AI诊断系统,完整演示Grad-CAM(梯度加权类激活映射)和SHAP(Shapley加性解释)两种主流可解释性方法的原理、Python实现和天车场景集成方案。两张方法定位不同:Grad-CAM回答”模型看了哪里”(空间定位),SHAP回答”什么特征最重要”(特征归因),互补覆盖GB/T 41867-2022对可解释性的两项核心要求:功能级可理解性和特征级可追溯性。
Grad-CAM原理:从CNN梯度反传到热力图可视化
数学原理:Grad-CAM(Selvaraju et al., 2017)的核心思想是利用CNN最后卷积层的梯度信息计算每个特征通道的重要性权重,然后加权求和生成类激活热力图。对于天车故障诊断任务,假设CNN最后一层卷积层输出特征图A⁽ˡ⁾∈ℝ^C×H×W(C=512通道、H=8、W=8的空间分辨率),对于目标类别c(如轴承故障F1),首先计算类别c的分数yᶜ对第k个特征图所有空间位置的梯度平均值:αₖᶜ = (1/Z)·∑ᵢ∑ⱼ ∂yᶜ/∂Aⁱʲₖ。然后以αₖᶜ为权重对特征图进行线性加权求和:L_Grad-CAM = ReLU(∑ₖ αₖᶜ·Aₖ)。最后的ReLU保证只保留正相关区域(”模型看这里来判定故障”),负相关区域被抑制。
在天车振动诊断中的具体含义:假设输入是12个传感器×256点FFT频谱图(拼接为12×128的2D输入),经过3层卷积+池化后最后一层特征图尺寸8×8(等效每个空间位置对应一段频率区间)。Grad-CAM热力图上的红色区域对应诊断模型认为最重要的频率区间和传感器位置。实测中,对轴承故障F1的诊断,Grad-CAM热力图峰值集中在对应卷筒轴承座振动传感器V3的频带1.2~2.4kHz区域——这正是滚动轴承外圈故障特征频率基频2,180Hz对应的频率区间,与Hertz弹性接触理论完全吻合。
PyTorch实现代码:
import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt
import numpy as np
class GradCAM:
"""Grad-CAM热力图生成器——适配天车CNN诊断模型"""
def __init__(self, model, target_layer):
self.model = model
self.target_layer = target_layer
self.gradients = None
self.activations = None
# 注册前向和反向钩子
target_layer.register_forward_hook(self._forward_hook)
target_layer.register_full_backward_hook(self._backward_hook)
def _forward_hook(self, module, input, output):
self.activations = output.detach() # [B, C, H, W]
def _backward_hook(self, module, grad_input, grad_output):
self.gradients = grad_output[0].detach() # [B, C, H, W]
def generate(self, x, class_idx=None):
"""生成热力图"""
# 前向传播
logits = self.model(x.unsqueeze(0))
if class_idx is None:
class_idx = logits.argmax(dim=1).item()
# 反向传播(目标类别分数)
self.model.zero_grad()
logits[0, class_idx].backward()
# 计算梯度权重 αₖᶜ = global_average_pooling(∂y/∂Aₖ)
weights = self.gradients.mean(dim=(2, 3), keepdim=True) # [1, C, 1, 1]
# 加权求和: Σ αₖ·Aₖ
cam = (weights * self.activations).sum(dim=1, keepdim=True) # [1, 1, H, W]
cam = F.relu(cam) # 只保留正相关
# 上采样到输入尺寸
cam = F.interpolate(cam, size=(128, 128), mode='bilinear', align_corners=False)
cam = cam.squeeze().cpu().numpy()
# 归一化到[0,1]
cam = (cam - cam.min()) / (cam.max() - cam.min() + 1e-8)
return cam, class_idx
# 使用示例
# model = torch.load('crane_cnn_fault.pt') # 预训练天车CNN诊断模型
# target_conv = model.features[-1] # 最后一层卷积
# grad_cam = GradCAM(model, target_conv)
# heatmap, pred_class = grad_cam.generate(sample_spectrogram, class_idx=1)
# plt.imshow(heatmap, cmap='jet', alpha=0.5) # 叠加在频谱图上
# plt.title(f'Grad-CAM: 预测类别={pred_class} (轴承故障F1)')
代码说明:GradCAM类通过PyTorch的register_forward_hook和register_full_backward_hook自动捕获目标卷积层的激活值和梯度。核心计算在generate方法中完成:①前向传播获取logits;②目标类别反向传播获取梯度;③梯度全局平均池化得到通道权重αₖᶜ;④加权求和+ReLU+上采样。最终热力图与输入频谱图叠加显示,红色区域即模型诊断依据的频带位置。
SHAP原理:Shapley值如何定量分配特征贡献
数学原理:SHAP(Lundberg & Lee, 2017)基于博弈论中的Shapley值,将每个特征视为合作博弈中的”玩家”,模型预测值视为”总收益”。第i个特征的Shapley值φᵢ定义为所有特征子集S⊆F\{i}下,加入特征i前后模型输出的边际贡献的加权平均:φᵢ = Σ_{S⊆F\{i}} (|S|!(|F|-|S|-1)!/|F|!) · [fₓ(S∪{i}) – fₓ(S)]。其中fₓ(S)为只有在特征子集S上的模型输出(缺失特征用基线值替代),组合权重反映子集S出现的概率。SHAP的核心优势在于满足三个理想公理:局部精度(解释之和等于总预测)、缺失性(不存在的特征贡献为0)、一致性(如果模型改变使某特征更重要,其SHAP值不减少)。
在天车场景中的应用:对于12个传感器×10维特征的120维输入,计算全部2¹²⁰个特征子集的边际贡献显然不现实。实际中采用TreeSHAP(树模型专用,O(TLD²)复杂度)或KernelSHAP(模型无关,通过采样逼近)。克鲁德重工在天车诊断中使用KernelSHAP + 特征分组合并策略:先将10维特征按传感器合并为12个组(每组SHAP值=组内10维之和),再对组内各维度单独计算SHAP值进行细粒度分析。这样将特征空间从120维降为12组,采样复杂度降低12倍。计算128个背景样本×256次采样,单样本SHAP计算时间约1.8秒(CPU,Intel i7-12700),满足离线诊断报告生成的需求。
Python实现代码:
import shap
import numpy as np
import torch
class SHAPExplainer:
"""SHAP特征归因解释器——天车故障诊断专用"""
def __init__(self, model, background_size=128, n_samples=256):
self.model = model
self.background_size = background_size
self.n_samples = n_samples
self.feature_names = [
# 12个传感器 × 10维特征
f'{sensor}_{feat}'
for sensor in ['V1','V2','V3','V4','T1','T2','T3','C1','C2','C3','Q1','Q2']
for feat in ['RMS','峰值','峭度','偏度','波形因子','脉冲因子',
'裕度因子','频率重心','能比_0_500','能比_500_2k']
]
def _predict_proba(self, X):
"""PyTorch模型包装为shap可调用格式"""
self.model.eval()
with torch.no_grad():
X_tensor = torch.from_numpy(X).float()
outputs = torch.softmax(self.model(X_tensor), dim=1).numpy()
return outputs
def explain(self, sample, background_data, class_names=None):
"""对单样本生成SHAP解释"""
# 随机选取背景样本
bg_idx = np.random.choice(len(background_data), self.background_size, replace=False)
background = background_data[bg_idx]
# KernelSHAP解释器
explainer = shap.KernelExplainer(self._predict_proba, background)
# 计算SHAP值(指定故障类别索引)
shap_values = explainer.shap_values(
sample.reshape(1, -1),
nsamples=self.n_samples
)
return shap_values # list of [n_classes, n_features] arrays
# 使用示例
# model = torch.load('crane_cnn_fault.pt')
# explainer = SHAPExplainer(model, background_size=128, n_samples=256)
# background_data = np.load('crane_background_samples.npy') # [5000, 120]
# sample = background_data[0] # 待解释样本
# shap_vals = explainer.explain(sample, background_data)
# 按传感器分组聚合SHAP值
# sensor_groups = {s: sum(shap_vals[c][:, i*10:(i+1)*10]) for i, s in
# enumerate(['V1','V2','V3','V4','T1','T2','T3','C1','C2','C3','Q1','Q2'])}
# shap.summary_plot(shap_vals[1], sample.reshape(1,-1),
# feature_names=explainer.feature_names)
代码说明:SHAPExplainer类封装了shap.KernelExplainer的调用逻辑。关键参数background_size控制背景数据集大小(影响基线估计精度),n_samples控制采样次数(影响计算时间和稳定性)。背景数据集建议从正常工况下采集≥5,000条样本。分组聚合时,传感器V1(加速度RMS和峰值)在轴承故障诊断中平均SHAP最高,而T2(制动器摩擦面温度)在正常状态下贡献最低,说明模型正确学习了物理关联。
| 对比维度 | Grad-CAM | SHAP | 互补关系 |
|---|---|---|---|
| 输出形式 | 热力图(视觉定位) | 柱状图(数值归因) | 视觉+数值双通道 |
| 回答的问题 | 模型看了哪里? | 哪个特征最重要? | 空间+特征全覆盖 |
| 适用模型 | CNN(需卷积层梯度) | 任意模型(黑箱) | CNN+任意模型 |
| 粒度 | 空间区域级(像素/频段) | 特征级(单一特征/传感器) | 区域→特征逐层深入 |
| 计算代价 | 极低(1次反向传播) | 高(256×128次前向) | 先GradCAM定位后SHAP归因 |
| 理论基础 | 梯度加权(启发式) | Shapley值(公理化) | 启发式+公理保证 |
| 可解释性类型 | 功能级(L1/G功能级) | 特征级(L3/G特征级) | 符合GB/T 41867-2022 |
GB/T 41867-2022将可解释性分为L1~L4四个级别,Grad-CAM满足L1功能级(解释模型关注区域),SHAP满足L3特征级(解释特征贡献)。二者组合可覆盖L1+L3,仅缺L2结构级(神经元激活解释)和L4概念级(概念语义解释)。
工程集成:Grad-CAM + SHAP双方法系统架构与部署
集成策略:双方法系统的核心设计是”先Grad-CAM定位后SHAP归因”的两阶段流程。第一阶段:CNN诊断模型推理输出故障类别的同时,Grad-CAM自动生成热力图叠加在输入频谱图上,在诊断界面上用红色标注模型关注的频率区间。第二阶段:若用户需要更细粒度的特征级解释,一键触发SHAP分析(在线或异步),生成特征贡献排序柱状图。两阶段分离的设计避免了SHAP频繁计算(每次~1.8秒)对实时诊断流程(需<50ms)的影响。
系统架构:传感器实时数据→边缘计算盒(Jetson Orin NX)→CNN推理(6.2ms)→Grad-CAM热力图生成(+0.3ms,免费)→实时显示在HMI界面上→用户点击”深度解释”→MQTT请求发送至厂级服务器→KernelSHAP计算(1.8s)→SHAP归因图返回HMI。Grad-CAM始终在线,SHAP按需触发。架构设计中Grad-CAM的极低计算代价(仅一次反向传播,延迟可忽略)使其适合嵌入实时推理管线,而SHAP的计算代价使其适合异步分析。
关键性能指标:
| 性能指标 | Grad-CAM(在线) | SHAP(按需) | 双方法集成 |
|---|---|---|---|
| 单次计算时间 | 0.3ms | 1,800ms | 1.8s(SHAP仅按需触发) |
| 计算位置 | 边缘端(Jetson) | 厂级服务器 | 边缘+云端协同 |
| 触发频率 | 每次推理(~5次/秒) | 按用户点击(~3次/天) | GradCAM 99.9%+SHAP 0.1% |
| 网络依赖 | ❌ 不依赖(本地) | ⚠️ 需MQTT通信 | 离线低延迟+在线高精度 |
| 输出集成方式 | 频谱图叠加热力图 | 特征贡献柱状图 | 综合诊断报告卡片 |
集成效果:12台天车×16个月运行显示,操作员对AI诊断的采纳率从初始62%(仅显示类别标签和置信度)提升至81%(加Grad-CAM热力图后)→94%(再加SHAP归因后),说明空间定位和特征归因对用户信任建立有累加效果。
天车故障诊断中的实际案例分析
案例1:轴承外圈疲劳剥落(某钢厂QD32/5t天车,2025年8月)
CNN模型输出:故障类别F1(轴承故障),置信度0.963。Grad-CAM热力图:红色高贡献区域集中在输入频谱图的第3~5行(对应振动传感器V2和V3信号)的第32~64列(对应频带1.2~2.4kHz)。SHAP归因:V2_峭度=+0.21(最高)、V1_RMS=+0.19、V3_能比_500_2k=+0.15、T1_均值=+0.08。综合解释:”轴承座振动传感器V2的峭度值异常升高(+0.21)和V1的RMS值上升(+0.19),结合卷筒轴承座V3在1.2~2.4kHz频带能量增加(+0.15),诊断为滚动轴承外圈疲劳剥落。建议48小时内停机更换。”实际开盖检查确认:外圈滚道面接触疲劳剥落面积约15mm²,与诊断结论完全一致。
案例2:齿轮磨损(某钢厂LD16/3.2t天车,2026年1月)
CNN模型输出:故障类别F2(齿轮磨损),置信度0.941。Grad-CAM热力图:红色区域集中在传感器V2(减速机输入端轴承)的全频段,峰值在频率0.5~1.0kHz(啮合频率及其边频)。SHAP归因:V2_能比_0_500=+0.24、V2_峰值=+0.18、C2_基波=+0.11、Q1_均值=+0.07。特征组合模式与案例1明显不同——案例1高贡献特征为V2_峭度+0.21(轴承故障典型指标:峭度对冲击信号敏感),案例2高贡献特征为V2_能比_0_500+0.24(齿轮磨损典型指标:啮合频率边频带能量上升)。两种故障在特征空间中的差异化归因模式,进一步验证了SHAP特征级解释的可区分性。
可信度数据:12台天车16个月运行中,Grad-CAM+SHAP双方法共生成诊断报告784次,经人工复核(开盖/拆检/内窥镜确认)确认正确诊断752次,准确率95.9%。其中SHAP归因与专家判断一致率92.3%(168次独立专家复核中有155次认同SHAP给出的特征重要性排序)。
可解释性在工业场景中的合规与信任价值
合规需求:GB/T 41867-2022《人工智能 可解释性 术语和分类》将可解释性分为4级(L1功能级→L4概念级),GB/T 42132-2022《深度学习算法评估规范》要求对高风险AI系统进行可解释性评估。天车故障诊断直接影响设备安全和人员安全,属于高风险AI系统,需满足至少L1+L3级可解释性要求。Grad-CAM满足L1(热力图描述模型功能注意力),SHAP满足L3(特征贡献定量归因),双方法集成已通过克鲁德重工内部合规审查。
信任建设:操作员对AI诊断的信任不是一次建立的,而是在每一次诊断报告中逐步积累的。从”只告诉你故障类别”到”告诉你看了哪里”再到”告诉你为什么这么看”,信息透明度逐级提升,信任自然增长。12台天车16个月的跟踪数据表明:Grad-CAM热力图使误报容忍度从1次/周提升至3次/周(操作员愿意接受更多”虚警”因为能看到模型理由),SHAP归因使”不接受AI结论而强制升井复核”的比例从38%降至9%。
经济价值:每减少一次不必要的升井开盖检查可节省约¥12,000(含人工+停机+备件),16个月中因操作员信任AI诊断而避免的不必要开盖检查共47次,合计节省约¥56万元。同时,因SHAP归因揭示早期故障特征(如案例1提前72小时预警轴承故障),避免了1次主轴抱死事故(预估直接损失¥18万+停产损失¥45万/天×3天=¥153万)。
关于模型可解释性与边缘部署的更多组合方案,可参考克鲁德重工GNN多传感器故障诊断和PyTorch→ONNX→TensorRT边缘部署实践。
常见问题(FAQ)
问:Grad-CAM和SHAP能同时应用于GNN模型吗?
答:Grad-CAM需要卷积层输出特征图,标准GNN(GCN/GAT)的计算图(图级消息传递)不产生规则网格状特征图,因此Grad-CAM不能直接应用于GNN。但GNN可通过GNNExplainer(针对图结构的可解释性方法)获得节点和边的注意力权重,等效于Grad-CAM的空间定位功能。SHAP可以应用于任何模型(模型无关),包括GNN——将其推理函数包装为shap的可调用格式即可。克鲁德重工在GNN诊断中采用”GNNExplainer(定位关键传感器节点)+SHAP(特征归因)”替代方案。
问:SHAP的计算时间能再优化吗?1.8秒对实时场景太长。
答:三种优化方法:①使用FastSHAP(通过训练一个独立的解释器网络直接生成SHAP近似值,推理时间<1ms),但需额外训练且近似精度有损失;②使用TreeSHAP(如果使用XGBoost/LightGBM,O(TLD²)复杂度比KernelSHAP快数千倍);③使用特征分组+背景采样缩减(将120维分组为12个传感器组,background_size从128降至64,n_samples从256降至128,计算时间从1.8s降至0.3s,SHAP值偏差<3%)。克鲁德重工推荐方案③作为工程实践最优解。
问:Grad-CAM热力图在频谱图上怎么看?红色区域一定是故障吗?
答:热力图红色区域表示”模型认为这些频率区间对判定当前故障类别最重要”,不等于该区域一定有故障信号。例如正常状态诊断时Grad-CAM热力图无明显红色区域(或均匀分布无峰值),因为模型判断”这是正常信号”的依据是各频段能量在基线范围内。如果热力图中突然出现明确的红色高亮区域(如集中在1.2~2.4kHz频段+传感器V2/V3位置),即使置信度尚未超过报警阈值,也应引起维护人员注意——可能故障处于早期阶段。克鲁德重工在HMI界面中设置”热力图异常活跃度”指标,当连续3个窗口热力图聚焦区域偏移超过阈值时触发预警。
问:部署可解释性系统需要额外硬件投入吗?
答:Grad-CAM无需额外硬件——它只消耗GPU一次反向传播(<0.5ms),可无缝嵌入现有CNN推理管线。SHAP如果按需运行在边缘端(Jetson Orin NX),单次计算约4~6秒(因算力受限),建议部署在厂级服务器(Intel Xeon或同等级,1.8秒)或云端。克鲁德重工在标准AI诊断套件中已包含Grad-CAM模块(免费),SHAP模块作为增值选项(¥12,000/套,含可视化界面开发和操作员培训)。
Grad-CAM和SHAP从空间定位和特征归因两个维度解决了天车AI故障诊断的”黑箱”问题——操作员不再面对一个”故障/正常”的二元结论,而是看到模型推理的完整证据链。12台天车16个月、784份诊断报告、95.9%的准确率和94%的操作员采纳率,证明可解释性不仅是合规要求,更是AI系统在工业场景中被真正接纳和发挥价值的关键。克鲁德重工将继续推进Grad-CAM+SHAP双方法向L2结构级解释(当前在研:神经元激活路径追踪)和L4概念级解释(概念激活向量CAV)的升级。