博主简介:擅长数据搜集与处理、建模仿真、程序设计、仿真代码、论文写作与指导,毕业论文、期刊论文经验交流。
✅ 如需沟通交流,扫描文章底部二维码。


(1)高维数据降维与建模困难问题的可逆神经网络方案

高速列车牵引系统作为典型的多层级机电耦合架构,其运行过程中产生的监测数据具有维度高、变量多、关联复杂等特征,直接对原始高维数据进行故障检测建模会面临维度诅咒、计算开销过大以及特征冗余等多重挑战,而传统的线性降维方法又难以有效保留高维数据中的非线性故障信息。本研究提出了一种基于可逆神经网络的高维数据建模方案,通过精心设计的双射变换将高维输入数据映射到一个维度可控的隐空间,在隐空间中进行后续的故障检测分析,既保持了原始数据的关键信息又有效降低了建模复杂度。所设计的可逆网络由可逆耦合块、批归一化层以及通道置换层三种组件交替堆叠组成,其中可逆耦合块负责数据的非线性变换,批归一化层稳定每一层输出的分布特性,通道置换层确保每一个特征通道在网络的不同位置都能够被充分变换。整个网络在训练过程中以最大化数据对数似然为目标进行端到端优化,训练好的网络能够将原本复杂分布的牵引系统监测数据映射为接近标准多元高斯的隐变量,显著简化了后续故障检测算法的设计难度。

(2)综合密度估计与重构残差的双重检测策略

变流器、牵引电机以及传动装置等核心功能单元在长期承受电热应力与机械振动耦合作用下产生的故障表现各异,单一的检测指标往往难以覆盖所有故障类型,本研究基于可逆神经网络的特性设计了一套综合密度估计与重构残差的双重故障检测策略。在密度估计层面,我们利用训练好的可逆网络对每一个待检测样本计算其在原始数据空间中的对数概率密度值,这一计算通过隐变量的高斯密度对数与变换雅可比行列式的对数相加即可精确得到。正常运行的样本因属于训练分布而具有较高的概率密度,故障样本则因偏离训练分布而呈现出较低的概率密度,以负对数似然作为检测指标即可识别出概率密度异常的样本。在重构残差层面,我们利用可逆网络的双向映射特性对样本进行重构检验,具体做法是先将样本正向映射到隐空间,然后将隐空间表示进行截断处理(只保留主要成分将其余成分置零),再通过反向映射回原空间得到去噪后的重构样本,实测样本与重构样本的欧氏距离即为重构残差,故障样本因偏离主要成分子空间而具有较大的重构残差。两类指标的协同检测能够同时捕捉概率密度的整体异常以及主成分子空间的局部偏离,显著提升了故障检测的灵敏度与覆盖度。

(3)面向多类型故障的可解释性分析与定位方法

高速列车牵引系统一旦检测到故障,工程人员需要进一步了解故障发生在哪个具体子系统以及故障的可能机理,以便采取针对性的处置措施,本研究在可逆神经网络故障检测的基础上构建了一个可解释性分析与故障定位方法。该方法的核心思想是利用可逆网络梯度反向传播的清晰物理含义来追溯故障特征在原空间中的源头位置。具体来说,当某个测试样本被检测为故障状态后,算法对其负对数似然指标关于输入变量的梯度进行计算,梯度向量的各分量绝对值反映了对应输入变量对最终异常分数的贡献程度,绝对值越大说明该变量在引起异常分数升高方面发挥的作用越显著,从而可作为故障定位的重要依据。在此基础上,我们进一步将各输入变量按照其所属的物理子系统进行归类聚合,得到各子系统的累计贡献度,贡献度最大的子系统即被识别为最可能的故障源头。除此之外,方法还结合了局部线性近似技术,在故障样本的小邻域内对可逆网络的非线性映射进行线性化近似,得到一个易于解释的线性模型,工程人员可以通过分析这个局部线性模型的权重直观理解当前故障是如何在各变量上具体表现出来的,提升了故障检测系统在实际工业应用中的可信度。

import torch
import torch.nn as nn

# 1. 可逆耦合块(带批归一化稳定训练)
class ReversibleBlock(nn.Module):
    def __init__(self, dim, hidden=128):
        super().__init__()
        self.dim = dim
        self.bn = nn.BatchNorm1d(dim)
        self.scale_shift = nn.Sequential(
            nn.Linear(dim // 2, hidden), nn.ReLU(),
            nn.Linear(hidden, hidden), nn.ReLU(),
            nn.Linear(hidden, dim))                    # 输出 [s; t]

    def forward(self, x, reverse=False):
        if not reverse:
            x = self.bn(x)
        x1, x2 = x.chunk(2, dim=1)
        s, t = self.scale_shift(x1).chunk(2, dim=1)
        s = torch.tanh(s) * 0.5                        # 软约束稳定性
        if not reverse:
            y2 = x2 * torch.exp(s) + t
        else:
            y2 = (x2 - t) * torch.exp(-s)
        log_det = s.sum(dim=1)
        return torch.cat([x1, y2], dim=1), log_det

# 2. 完整可逆网络
class InvertibleFaultNet(nn.Module):
    def __init__(self, dim, n_block=8):
        super().__init__()
        self.blocks = nn.ModuleList([ReversibleBlock(dim) for _ in range(n_block)])
        self.perms = nn.ParameterList([
            nn.Parameter(torch.randperm(dim).float(), requires_grad=False)
            for _ in range(n_block)])

    def forward(self, x):
        log_det = 0
        for blk, perm in zip(self.blocks, self.perms):
            idx = perm.long()
            x = x[:, idx]
            x, ld = blk(x)
            log_det = log_det + ld
        return x, log_det

# 3. 双重检测统计量
def dual_detection_stats(model, x, k_main=10):
    z, log_det = model(x)
    # 指标1: 负对数似然(密度估计)
    log_pz = -0.5 * (z**2).sum(dim=1)
    nll = -(log_pz + log_det)
    # 指标2: 主成分子空间重构残差
    z_truncated = z.clone()
    z_truncated[:, k_main:] = 0                        # 只保留前k个主成分
    # 反向重构
    x_rec = z_truncated                                # 简化:实际需逆向通过整个网络
    rec_err = ((x - x_rec)**2).sum(dim=1).sqrt()
    return nll, rec_err

# 4. 基于梯度的故障变量定位(可解释性)
def gradient_based_localization(model, x_fault, var_groups):
    x_fault.requires_grad_(True)
    z, log_det = model(x_fault)
    nll = -((-0.5*(z**2).sum(dim=1)) + log_det).mean()
    nll.backward()
    grad = x_fault.grad.abs().mean(dim=0)              # 各变量梯度幅值
    # 按物理子系统聚合贡献度
    group_contribution = {}
    for group_name, indices in var_groups.items():
        group_contribution[group_name] = grad[indices].sum().item()
    # 排序找出主导故障源
    sorted_groups = sorted(group_contribution.items(), key=lambda x: -x[1])
    return sorted_groups

# 5. 局部线性近似:在故障邻域生成可解释模型
def local_linear_approx(model, x_anchor, n_perturb=100, sigma=0.05):
    perturbations = x_anchor + torch.randn(n_perturb, *x_anchor.shape) * sigma
    z_anchor, ld_a = model(x_anchor.unsqueeze(0))
    z_pert, ld_p = model(perturbations)
    nll_anchor = -((-0.5*(z_anchor**2).sum(1)) + ld_a)
    nll_pert = -((-0.5*(z_pert**2).sum(1)) + ld_p)
    # 线性回归: nll ≈ w·dx + b
    dx = perturbations - x_anchor
    dy = nll_pert - nll_anchor
    w = torch.linalg.lstsq(dx, dy.unsqueeze(1)).solution
    return w.squeeze().detach()                        # 局部权重


如有问题,可以直接沟通

👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇 

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐