资讯动态

改进ACGAN轴承故障诊断:SE与残差结构实现小样本数据增强

发布时间:2026/10/20 1:19:44 来源:尧图企业网站定制
简介这份文档资料围绕改进数据增强方法在轴承故障诊断中的应用展开面向电机故障诊断、旋转机械状态监测方向的研究生与工程技术人员帮助解决故障样本分布不均衡导致分类准确率偏低的问题。资源为单个docx文档压缩包约1.21MB内容涵盖生成式对抗网络、辅助分类生成式对抗网络ACGAN的原理推导以及融合压缩激励机制SE的改进ACGAN方法通过为重要通道赋予更大权重提升样本生成质量。文中对比了改进ACGAN与原始ACGAN的算例结果验证了模型在提高故障诊断准确率方面的有效性与优越性并给出目标函数、结构图与实验分析可作为数据增强与故障诊断研究的参考材料。目前已有131人学习下载适合需要了解GAN类数据增强思路、撰写相关论文或开展轴承故障诊断实验的读者参考借鉴。1. 从一份轴承故障诊断文档说起为什么改进 ACGAN 值得你花时间拆一遍工业现场跑旋转设备的都知道轴承故障占电机故障的三成左右这个比例不是吓唬人。问题是正常运转的机器多坏了的样本少采集到的故障数据天然就是长尾分布——外圈故障可能攒了几百条滚珠 0.18mm 这种细微缺陷可能就几十条甚至更少。拿这种数据去训分类器少数类要么被忽略要么直接过拟合到几个噪声点上。这份文档给出的思路是在 ACGAN 的判别器里嵌入压缩激励机制SE加残差结构让生成器在少样本条件下也能产出分布接近真实的故障样本最终把 1000 张原始样本下的诊断准确率推到 99.82%。如果你手头正好有振动信号数据集、正在做小样本故障诊断、或者想搞清楚 GAN 做数据增强到底怎么落地这份文档值得跟着走一遍。2. ACGAN 做数据增强的底层逻辑从 GAN 到辅助分类器2.1 GAN 的博弈框架与目标函数GAN 的核心就两个角色生成器 G 和判别器 D。G 接收随机噪声 z输出假样本 G(z)D 接收真样本 x 和假样本 G(z)判断哪个是真的。训练过程就是两人打架——G 想骗过 DD 想识破 G。形式化地写目标函数是min_G max_D V(D,G) E_{x~p_data(x)}[log D(x)] E_{z~p_z(z)}[log(1 - D(G(z)))]这个式子里p_data(x) 是真实样本分布p_z(z) 是噪声分布一般用标准正态。D(x) 越接近 1 说明 D 认为 x 是真的D(G(z)) 越接近 0 说明 D 认为生成样本是假的。训练时交替优化固定 G 训 D 几轮再固定 D 训 G 几轮。实际操作中这个平衡很难拿捏——D 太强G 梯度消失D 太弱G 生成的东西没意义。这是 GAN 训练不稳定的根源也是后面改进要解决的核心问题。2.2 ACGAN 怎么把类别标签塞进生成过程普通 GAN 只能生成“像”的样本但不知道生成的是哪一类故障。ACGAN 的做法是把类别标签 c 也作为生成器的输入G 接收 (c, z) 输出 X_fake G(c, z)。判别器这边改成一个多任务结构既要判断真假输出 P(S|X)又要判断类别输出 P(C|X)。对应的损失函数拆成两部分L_S E[log P(Sreal|X_real)] E[log P(Sfake|X_fake)] L_C E[log P(Cc|X_real)] E[log P(Cc|X_fake)]训练时 D 要最大化 L_S L_CG 要最大化 L_C - L_S。翻译成人话D 既要分真假又要分对类别G 既要让 D 分不出真假又要让 D 能分对类别。这个设计的好处是标签信息直接参与了生成过程生成样本不再是“随机像”而是“像某一类”。对于轴承故障诊断这种多分类任务ACGAN 比原始 GAN 更对路。2.3 为什么要在判别器里加 SE 和残差ACGAN 虽然比 GAN 强但仍有问题训练收敛慢、生成样本质量不稳定、偶尔模式坍塌。文档的改进思路是在判别器里嵌入 SE 模块和残差连接。SE 模块做的事叫“通道注意力”——先对特征图做全局平均池化把每个通道压缩成一个标量然后通过两层全连接层学出一组权重最后用这组权重去重新标定每个通道的特征响应。用公式表示z_c (1/(H×W)) × Σ_i Σ_j u_c(i,j) # Squeeze全局平均池化 s_c σ(W_2 · δ(W_1 · z_c)) # Excitation两层全连接 Sigmoid x_c s_c · u_c # Scale通道加权其中 W_1 的维度是 (C/r) × CW_2 是 C × (C/r)r 是降维比率通常取 16。δ 是 ReLUσ 是 Sigmoid。这个操作的直觉是判别器提取的特征里有些通道对区分故障类型更关键SE 就是自动给这些通道加权重让判别器“把注意力放在该放的地方”。残差连接的加入则是为了解决梯度问题。在 SE 模块外面套一个残差结构卷积核数量与输入通道数保持一致配合 Padding 保证输入输出形状相同梯度可以通过 shortcut 直接回传避免深层网络里的梯度消失或爆炸。这两者组合起来判别器的特征提取能力上去了训练也更稳。3. 复现改进 ACGAN数据准备、模型搭建与训练参数3.1 轴承数据的预处理与样本划分文档用的是 CWRU 电机轴承数据集10 类1 类正常 3 种故障位置外圈、内圈、滚珠× 3 种故障尺寸0.18mm、0.36mm、0.54mm。常见做法是把原始振动信号切成固定长度的片段比如每段 1024 个采样点然后做归一化。如果你用的是自己的数据流程类似import numpy as np from sklearn.preprocessing import LabelEncoder def segment_signal(signal, window_size1024, overlap0.5): 把长振动信号切成等长片段 step int(window_size * (1 - overlap)) segments [] for start in range(0, len(signal) - window_size 1, step): seg signal[start:start window_size] segments.append(seg) return np.array(segments) def normalize(segments): 按片段做 Z-score 归一化 mean segments.mean(axis1, keepdimsTrue) std segments.std(axis1, keepdimsTrue) 1e-8 return (segments - mean) / std # 假设 raw_signals 是 dict: {label: [signal_array, ...]} all_segments, all_labels [], [] for label, signals in raw_signals.items(): for sig in signals: segs segment_signal(sig) segs normalize(segs) all_segments.append(segs) all_labels.extend([label] * len(segs)) X np.concatenate(all_segments, axis0) y LabelEncoder().fit_transform(all_labels) print(f样本总数: {X.shape[0]}, 类别数: {len(set(y))})这里 window_size 取 1024 是振动信号分析里比较通用的选择overlap 取 0.5 可以在不引入太多冗余的前提下增加样本量。归一化按片段做而不是全局做是为了避免不同工况下的幅值差异干扰模型。如果你的数据采样率不同窗口长度可以按 2 的幂次调整但建议不低于 512否则频率分辨率不够。3.2 生成器与判别器的网络结构设计生成器的输入是噪声向量 z维度一般取 100和类别标签的 embedding。输出是一个和真实样本同形状的向量。判别器接收样本输出两个东西真假概率和类别概率。下面是 PyTorch 的核心结构import torch import torch.nn as nn class Generator(nn.Module): def __init__(self, noise_dim100, num_classes10, output_dim1024): super().__init__() self.label_emb nn.Embedding(num_classes, noise_dim) self.net nn.Sequential( nn.Linear(noise_dim * 2, 256), nn.BatchNorm1d(256), nn.LeakyReLU(0.2), nn.Linear(256, 512), nn.BatchNorm1d(512), nn.LeakyReLU(0.2), nn.Linear(512, output_dim), nn.Tanh() # 输出归一化到 [-1, 1] ) def forward(self, z, labels): label_input self.label_emb(labels) x torch.cat([z, label_input], dim1) return self.net(x) class SEBlock(nn.Module): 压缩激励机制模块 def __init__(self, channels, reduction16): super().__init__() self.squeeze nn.AdaptiveAvgPool1d(1) self.excitation nn.Sequential( nn.Linear(channels, channels // reduction), nn.ReLU(), nn.Linear(channels // reduction, channels), nn.Sigmoid() ) def forward(self, x): # x: (batch, channels, length) b, c, _ x.size() s self.squeeze(x).view(b, c) s self.excitation(s).view(b, c, 1) return x * s class Discriminator(nn.Module): def __init__(self, input_dim1024, num_classes10): super().__init__() self.feature nn.Sequential( nn.Conv1d(1, 64, kernel_size5, stride2, padding2), nn.LeakyReLU(0.2), SEBlock(64), nn.Conv1d(64, 128, kernel_size5, stride2, padding2), nn.LeakyReLU(0.2), SEBlock(128), ) self.fc nn.Linear(128 * (input_dim // 4), 128) self.adv_head nn.Linear(128, 1) # 真假判别 self.cls_head nn.Linear(128, num_classes) # 类别判别 def forward(self, x): x x.unsqueeze(1) # (batch, 1, length) feat self.feature(x) feat feat.view(feat.size(0), -1) feat self.fc(feat) return self.adv_head(feat), self.cls_head(feat)生成器用全连接堆叠是因为输入是 1D 振动信号不需要卷积上采样。判别器用 Conv1d SEBlock 的组合SEBlock 放在每个卷积层之后对通道特征做重标定。注意 SEBlock 里用的是 AdaptiveAvgPool1d 而不是 2D 池化因为信号是一维的。判别器输出两个头adv_head 输出一个标量表示真假cls_head 输出 num_classes 维向量表示类别。3.3 训练循环与损失函数配置训练时用 RMSprop 优化器学习率一般设 0.0002beta 取 0.5。损失函数方面真假判别用 BCEWithLogitsLoss类别判别用 CrossEntropyLoss。关键代码import torch.optim as optim device torch.device(cuda if torch.cuda.is_available() else cpu) G Generator().to(device) D Discriminator().to(device) opt_G optim.RMSprop(G.parameters(), lr0.0002) opt_D optim.RMSprop(D.parameters(), lr0.0002) bce nn.BCEWithLogitsLoss() ce nn.CrossEntropyLoss() for epoch in range(200): for real_x, real_y in dataloader: batch_size real_x.size(0) real_x, real_y real_x.to(device), real_y.to(device) # --- 训练判别器 --- z torch.randn(batch_size, 100).to(device) fake_y torch.randint(0, 10, (batch_size,)).to(device) fake_x G(z, fake_y).detach() real_adv, real_cls D(real_x) fake_adv, fake_cls D(fake_x) loss_D_real bce(real_adv, torch.ones_like(real_adv)) loss_D_fake bce(fake_adv, torch.zeros_like(fake_adv)) loss_D_cls ce(real_cls, real_y) ce(fake_cls, fake_y) loss_D loss_D_real loss_D_fake loss_D_cls opt_D.zero_grad() loss_D.backward() opt_D.step() # --- 训练生成器 --- z torch.randn(batch_size, 100).to(device) gen_y torch.randint(0, 10, (batch_size,)).to(device) gen_x G(z, gen_y) gen_adv, gen_cls D(gen_x) loss_G_adv bce(gen_adv, torch.ones_like(gen_adv)) loss_G_cls ce(gen_cls, gen_y) loss_G loss_G_cls - loss_G_adv # 对应 L_C - L_S opt_G.zero_grad() loss_G.backward() opt_G.step()判别器的损失由三部分组成真样本判真、假样本判假、两类样本的类别分类。生成器的损失是类别损失减去真假损失对应前面公式里的 L_C - L_S。注意生成器更新时要把判别器的梯度冻结用 detach 或者只更新 G 的参数。训练轮数文档里提到 10000 次迭代左右收敛实际复现时建议每 500 步记录一次生成器和判别器的 loss画出来看趋势。3.4 生成样本质量评估IS 与 FID 怎么算ISInception Score衡量的是生成样本的清晰度和多样性。直觉上好的生成样本应该被分类器以高置信度分到某一类清晰同时所有类别的样本都有多样。公式是IS exp(E_{x~p_g}[D_KL(P(y|x) || P(y))])P(y|x) 是生成样本 x 属于各类别的概率P(y) 是边缘概率。IS 越大越好。FIDFréchet Inception Distance则是比较真实样本和生成样本在特征空间里的分布距离FID ||μ_x - μ_g||² Tr(Σ_x Σ_g - 2(Σ_x · Σ_g)^{1/2})μ 是均值Σ 是协方差矩阵。FID 越小说明两个分布越接近。文档里的结果1000 张训练样本时ACGAN 的 FID 是 78.92、IS 是 24.65改进 ACGAN 的 FID 是 40.87、IS 是 31.51。差距很明显。实际计算时IS 和 FID 都需要一个预训练的分类器来提取特征常见做法是用在 ImageNet 上训好的 Inception 网络但振动信号是一维的需要先转成二维图像或者用一维特征提取器替代。这一步是复现时最容易卡住的地方后面避坑章节会展开。4. 避坑与排查复现改进 ACGAN 时最容易翻车的五个点4.1 生成器 loss 震荡不收敛现象训练了几千步生成器 loss 一直在大幅震荡生成的样本看起来像噪声。原因最常见的是判别器太强生成器梯度消失。另外学习率设太大也会导致震荡。解决先把判别器的学习率降到生成器的 1/2 到 1/5或者每训练判别器 1 次就训练生成器 2 次。如果还不行检查判别器里有没有加 BatchNorm——判别器用 BatchNorm 容易导致训练不稳定建议换成 LayerNorm 或者 InstanceNorm。文档里用的是 RMSprop如果你用 Adambeta1 建议设 0.5 而不是默认的 0.9。4.2 SE 模块加了之后反而变差现象加了 SEBlock 之后判别器的分类准确率不升反降。原因SE 模块的降维比率 r 设得太小比如 r2导致全连接层参数量过大过拟合了。或者 SEBlock 放的位置不对放在了激活函数之前。解决r 一般取 16 或 8不要低于 4。SEBlock 的标准顺序是卷积 → SE 重标定 → 激活函数。如果你把 SE 放在激活之后通道权重会被 ReLU 截断效果打折。另外SE 模块的输入通道数要和卷积输出通道数对齐否则广播会出错。4.3 FID 算出来是负数或者 NaN现象计算 FID 时结果出现负数或 NaN。原因协方差矩阵开平方时出现了复数。文档里也提到了这一点——“当结果出现复数时只保留实数部分”。另一个原因是样本量太少协方差矩阵不满秩。解决用 scipy.linalg.sqrtm 计算矩阵平方根时加一个小的正则项比如 1e-6 × I到协方差矩阵对角线上。如果样本量少于特征维度先做 PCA 降维再算 FID。另外确保真实样本和生成样本的数量一致否则均值估计偏差会很大。4.4 生成样本扩充后诊断准确率不升反降现象用生成样本扩充训练集后分类器的测试准确率比不用增强还低。原因生成样本质量不够引入了噪声。或者生成样本和真实样本的标签对不上——比如生成器把内圈故障生成了外圈故障的波形。解决先单独评估生成样本的 IS 和 FID确认质量达标再拿去增强。增强时不要把所有生成样本一股脑加进去按文档表 2 的结论生成样本到 4000 张左右就饱和了再加反而可能引入噪声。建议按 1:1 到 1:3 的比例混合真实样本和生成样本然后做消融实验确认。4.5 训练时间过长显存不够现象训练一轮要几个小时或者直接 OOM。原因判别器里的全连接层参数量太大或者 batch_size 设得太大。解决把判别器最后的全连接层维度从 128 降到 64或者用全局平均池化替代 flatten。batch_size 从 64 降到 32 甚至 16。如果显存还是不够把信号长度从 1024 降到 512。另外SE 模块里的全连接层可以用 1×1 卷积替代参数量更少。5. 从生成样本到诊断结果一个可复用的验证流程把生成样本拿去训练分类器这一步很多人做得太随意。我一般会固定一个验证流程先用真实样本训一个基线分类器比如 1D-CNN 或 ResNet记录准确率然后用“真实 生成”的混合数据训同一个分类器对比准确率变化。分类器不要选太复杂的否则生成样本的贡献被模型容量掩盖了。文档里用的是简单的分类器改进 ACGAN 在 1000 张原始样本 2000 张生成样本时达到 99.73%加到 3000 张时到 99.82%再加就饱和了。具体操作上我习惯按下面的流程走一遍步骤操作检查点1固定随机种子划分训练/测试集测试集不参与任何训练2训练基线分类器记录准确率作为对照3用改进 ACGAN 生成样本检查 IS/FID 是否达标4按比例混合真实生成样本生成样本不超过真实的 3 倍5训练同一分类器对比基线准确率6做消融去掉 SE、去掉残差确认每个模块都有贡献最后一步的消融实验最容易被跳过但恰恰是最能说明问题的。如果去掉 SE 之后准确率没变化那说明你的数据上 SE 没起作用可能是通道数太少或者降维比率不合适。如果去掉残差之后训练直接崩了那说明残差确实是稳定训练的关键。还有一个细节生成样本的标签质量。ACGAN 的辅助分类器会输出类别概率如果某个生成样本的类别概率最大值低于 0.6我一般会把它丢掉。这个阈值不是固定的取决于你的类别数和数据难度但加一道过滤总比不加好。从那以后我每次做 GAN 数据增强都会先把生成样本的 IS 和 FID 跑一遍再拿去做分类验证两步都过了才敢往论文或报告里写。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑