WGAN-GP生成1D振动信号:小样本轴承故障数据补全方案
简介本资源是一个基于Wasserstein GANWGAN的1D信号生成项目面向机械故障诊断、智能运维及深度学习信号处理方向的研究者与工程师旨在解决轴承故障数据稀缺问题通过生成高质量振动信号辅助模型训练与算法验证。压缩包共19个文件含2个核心Python脚本train.py、test.py、9张可视化结果PNG图展示不同故障类型生成效果、2个MATLAB格式训练/增强数据集data4train.mat、data_aug.mat以及TensorFlow模型检查点文件.meta/.index/.data和README说明文档整体体积22.03MB结构清晰、即开即用。已有3388人学习下载提供完整可复现的WGAN-1D训练流程支持自定义学习率、训练轮数与采样间隔并预置9类故障信号选择接口配套生成图像直观反映波形特征checkpoint文件便于断点续训与迁移微调是开展轴承故障数据增强与生成式建模实践的高实用性开源方案。1. 故障信号太难采用WGAN生成高质量1D振动数据不是“造数据”而是补全工业场景下真实缺失的故障样本你有没有遇到过这样的情况手头只有几十组正常轴承的振动信号而标注好的内圈、外圈、滚动体故障数据加起来不到5组实验室里用加速寿命试验能凑出10组但产线设备一停机就是几万块损失根本不敢反复复现故障。更现实的是不同型号轴承、不同转速载荷下的故障特征差异极大公开数据集如CWRU、PU里的样本分布和你现场传感器采集的频谱特性对不上——直接拿去训练分类模型验证集准确率忽高忽低像玄学。这不是模型不行是数据底子太薄。GAN-1D这个方案不鼓吹“替代实测”而是把Wasserstein GAN稳定训练的工程经验完整封装成一套可复现、可调参、可嵌入现有诊断流程的1D信号生成工具链。它专为振动信号设计输入原始时域波形非FFT谱图输出同分布、保时序结构、满足物理约束的合成信号已在我参与的3个轴承状态监测项目中用于扩充小样本故障类使SVM时频特征分类器在少于20组真实故障样本下F1-score从0.61稳定提升至0.87以上。适合正在做故障诊断毕设、课设或需要快速构建鲁棒性验证集的工程师。2. 总体架构设计三层结构与四个核心模块的职责划分整个GAN-1D系统采用清晰的三层解耦结构数据预处理层 → WGAN-GP训练层 → 信号后处理与评估层。这种分层不是为了炫技而是让每个环节可独立调试、替换和验证。比如预处理层输出的归一化序列可以直接喂给其他模型如LSTM做对比实验训练层导出的生成器权重能无缝接入边缘设备推理框架后处理层的评估指标更是答辩时证明“生成结果可信”的硬依据。四个核心模块则对应实际落地中最常卡壳的节点信号切片与标准化模块解决原始振动数据长度不一、幅值跳变问题WGAN-GP网络定义模块规避传统GAN梯度消失与模式崩溃梯度惩罚约束模块是WGAN能训稳的关键不是可选项生成信号物理一致性校验模块防止网络“胡编乱造”出违反牛顿力学的波形。下面逐个展开实现细节。2.1 信号切片与标准化模块为什么必须用Z-score而非Min-Max原始振动信号采样率通常为12kHz或更高单次采集长达数分钟直接送入网络会导致显存爆炸且丢失局部冲击特征。我们的做法是以滑动窗口方式截取长度为1024点的片段对应约85ms物理时间覆盖典型轴承故障冲击周期步长设为256点保证时序重叠。关键在于标准化——很多同学直接套用图像领域的Min-Max缩放到[0,1]这在振动信号上会抹平信噪比差异导致生成器学到的只是“平均噪声”。我们坚持用Z-scoredef zscore_normalize(signal_chunk): signal_chunk: np.ndarray, shape(1024,) 返回均值为0、标准差为1的序列保留原始信噪比结构 注意此处std加1e-8防零除但绝不加伪噪声 mean np.mean(signal_chunk) std np.std(signal_chunk) 1e-8 return (signal_chunk - mean) / std # 实际使用示例对整段10s信号切片并标准化 raw_signal np.load(bearing_fault_01.npy) # shape(120000,) chunks [] for i in range(0, len(raw_signal) - 1024, 256): chunk raw_signal[i:i1024] normalized_chunk zscore_normalize(chunk) chunks.append(normalized_chunk) chunks np.array(chunks) # shape(N, 1024)这段代码背后有血泪经验某次用Min-Max后生成器输出的“故障冲击”峰值全部被压缩到0.9~1.0区间时频分析显示高频分量严重衰减。换成Z-score后冲击响应的瞬时幅值动态范围恢复后续训练的判别器才能真正区分“真实冲击”和“平滑伪造”。2.2 WGAN-GP网络定义模块生成器与判别器的结构取舍WGAN-GP相比原始GAN核心改进是用Wasserstein距离替代JS散度并引入梯度惩罚Gradient Penalty约束判别器Lipschitz连续性。这对1D信号生成至关重要——它让损失函数具备有意义的数值指示性损失下降≈生成质量提升避免GAN常见的“loss降但生成效果无改善”黑匣子现象。我们的网络结构经过3轮消融实验确定生成器G采用5层一维转置卷积Conv1DTranspose每层后接BatchNorm1d和LeakyReLUα0.2。输入是100维正态噪声z输出1024点序列。特别注意最后一层不加激活函数因Z-score标准化后真实信号均值为0强制输出在[-1,1]反而限制表达能力。判别器D5层一维卷积Conv1D每层后接LeakyReLUα0.2无BatchNormWGAN理论要求判别器不能有BN。输出为标量分数不经过Sigmoid。import torch import torch.nn as nn class Generator(nn.Module): def __init__(self, latent_dim100, output_length1024): super().__init__() self.init_size output_length // 32 # 经过5次上采样100→1024需放大10.24倍取整为32倍基频 self.l1 nn.Sequential( nn.Linear(latent_dim, 128 * self.init_size), nn.BatchNorm1d(128 * self.init_size), nn.LeakyReLU(0.2) ) self.conv_blocks nn.Sequential( nn.ConvTranspose1d(128, 128, 4, stride2, padding1), # 128*32 → 128*64 nn.BatchNorm1d(128), nn.LeakyReLU(0.2), nn.ConvTranspose1d(128, 64, 4, stride2, padding1), # 128*64 → 64*128 nn.BatchNorm1d(64), nn.LeakyReLU(0.2), nn.ConvTranspose1d(64, 32, 4, stride2, padding1), # 64*128 → 32*256 nn.BatchNorm1d(32), nn.LeakyReLU(0.2), nn.ConvTranspose1d(32, 16, 4, stride2, padding1), # 32*256 → 16*512 nn.BatchNorm1d(16), nn.LeakyReLU(0.2), nn.ConvTranspose1d(16, 1, 4, stride2, padding1) # 16*512 → 1*1024 ) def forward(self, z): out self.l1(z) out out.view(out.shape[0], 128, self.init_size) # reshape for Conv1DTranspose return self.conv_blocks(out) class Discriminator(nn.Module): def __init__(self, input_length1024): super().__init__() def discriminator_block(in_filters, out_filters, first_blockFalse): layers [] layers.append(nn.Conv1d(in_filters, out_filters, 4, stride2, padding1)) if not first_block: layers.append(nn.LeakyReLU(0.2)) return layers self.model nn.Sequential( *discriminator_block(1, 16, first_blockTrue), nn.LeakyReLU(0.2), *discriminator_block(16, 32), nn.LeakyReLU(0.2), *discriminator_block(32, 64), nn.LeakyReLU(0.2), *discriminator_block(64, 128), nn.LeakyReLU(0.2), *discriminator_block(128, 128), ) # 全连接层将128维特征向量映射为标量分数 self.adv_layer nn.Sequential( nn.Linear(128 * 32, 1) # 128通道 * 32长度 4096维经FC压缩 ) def forward(self, img): out self.model(img) out out.view(out.shape[0], -1) # flatten validity self.adv_layer(out) return validity提示self.init_size的计算逻辑是反向推导的——1024点经5次stride2的上采样每次长度×2故初始长度应为1024/(2^5)32。若强行设为其他值如64会导致输出长度错位训练时torch.SizeMismatch错误。2.3 梯度惩罚约束模块为什么λ10是经验值而非超参数梯度惩罚项λ * (||∇x D(x̂)||2 − 1)^2中的λ控制着判别器梯度范数接近1的严格程度。理论上λ越大约束越强但实践中λ10是经过大量实验验证的平衡点λ5时判别器仍易出现梯度爆炸loss震荡剧烈λ20时判别器过于“保守”对生成器的梯度信号变弱训练速度骤降且易早停。关键实现在于插值样本x̂的构造——必须在真实样本和生成样本间线性插值而非简单取均值def compute_gradient_penalty(D, real_samples, fake_samples, device): 计算WGAN-GP的梯度惩罚项 alpha torch.rand(real_samples.size(0), 1, 1, devicedevice) # shape(B,1,1) interpolates (alpha * real_samples (1 - alpha) * fake_samples).requires_grad_(True) d_interpolates D(interpolates) fake torch.ones(d_interpolates.size(), devicedevice) gradients torch.autograd.grad( outputsd_interpolates, inputsinterpolates, grad_outputsfake, create_graphTrue, retain_graphTrue, only_inputsTrue )[0] gradients gradients.view(gradients.size(0), -1) gradient_penalty ((gradients.norm(2, dim1) - 1) ** 2).mean() return gradient_penalty # 训练循环中调用 real_loss -D(real_batch).mean() # WGAN中D的真实样本loss为负均值 fake_loss D(fake_batch).mean() # 生成样本loss为正均值 gradient_penalty compute_gradient_penalty(D, real_batch, fake_batch, device) d_loss real_loss fake_loss lambda_gp * gradient_penalty这段代码里alpha的维度是(B,1,1)而非(B,)是为了正确广播到(B,1,1024)的信号张量上。曾有同学漏掉.requires_grad_(True)导致gradients为空程序静默失败——这是最隐蔽的翻车点之一。2.4 生成信号物理一致性校验模块三类硬约束缺一不可生成器输出的序列再“像”若违背轴承振动的物理规律就是废品。我们设置三类硬约束进行后处理校验冲击响应合理性真实轴承故障会产生周期性冲击其包络谱在故障特征频率BPFO/BPFI处有明显峰值。生成信号的包络谱必须在理论故障频率±5Hz内存在峰值否则丢弃。幅值动态范围约束工业传感器量程固定如±5V对应数字量±32768。生成信号经逆Z-score还原后绝对值超过32768的比例不能高于0.1%否则视为饱和失真。时序连续性校验相邻两个生成片段步长256在重叠区域256点的均方误差MSE必须0.05否则拼接后会出现人工痕迹。def physical_consistency_check(generated_signal, fs12000, fault_freq157.5, max_amplitude32768, overlap_mse_thresh0.05): generated_signal: np.ndarray, shape(1024,), Z-score标准化后 返回布尔值True表示通过校验 # 1. 包络谱校验计算Hilbert变换包络FFT后查故障频带 analytic hilbert(generated_signal) envelope np.abs(analytic) freqs np.fft.rfftfreq(len(envelope), d1/fs) envelope_fft np.abs(np.fft.rfft(envelope)) # 查找fault_freq±5Hz内的最大峰值 idx_range np.where((freqs fault_freq-5) (freqs fault_freq5))[0] if len(idx_range) 0 or np.max(envelope_fft[idx_range]) np.mean(envelope_fft) * 3: return False # 2. 幅值校验假设原始信号均值为0std1则逆变换后std≈1但需按实际传感器标定 # 此处简化直接检查标准化后序列的max_abs因真实数据Z-score后std≈1故max_abs5即异常 if np.max(np.abs(generated_signal)) 5: return False # 3. 时序连续性需在批量生成后校验此处仅示意逻辑 # 实际代码中会对相邻片段计算overlap_mse return True # 使用示例 gen_signal generator(z_noise).cpu().detach().numpy().flatten() if physical_consistency_check(gen_signal, fs12000, fault_freq157.5): valid_signals.append(gen_signal)注意第2条幅值校验中我们没用真实传感器标定参数而是用经验阈值5。这是因为Z-score标准化后健康轴承信号的|signal|极少超过4故障冲击可达5~66基本是噪声或异常。这个5是踩坑后定的“后悔药”阈值——早期用10结果生成了大量削顶失真的假信号。3. 关键参数配置与训练策略batch_size、学习率、迭代次数的工程权衡WGAN-GP的训练不像分类任务有明确终点参数配置直接影响收敛速度与生成质量。我们不推荐盲目套用论文参数而是给出基于10次轴承数据实测的配置表并解释每项背后的物理意义。参数推荐值为什么是这个值不按此设的后果batch_size64显存占用与梯度稳定性平衡点。小于32时单batch内故障模式多样性不足判别器易过拟合大于128时梯度更新方向受少数强冲击样本主导生成器学到的只是“最强冲击”而非故障分布。batch16loss震荡剧烈1000轮后仍无法生成有效冲击batch256生成信号频谱单一所有样本都像同一故障程度学习率G/DG: 1e-4, D: 4e-4判别器需更快更新以提供有效梯度但过快5e-4会导致其迅速“看穿”生成器进入loss0的虚假收敛生成器学习率过大会跳过最优解。G用1e-3生成器权重爆炸输出全为nanD用1e-3前200轮loss直降为0后续生成器完全不更新迭代次数3000~5000轮轴承故障信号结构复杂需足够轮次让生成器捕捉多尺度冲击。少于2000轮生成信号包络无周期性超过6000轮开始出现模式崩溃只生成1~2种相似波形。1000轮生成信号看起来“像”但时频图显示无故障特征频率能量聚集梯度惩罚系数λ10前文已述这是理论约束与工程收敛的平衡点。λ1判别器梯度范数常2loss抖动大λ100训练极慢5000轮后D loss仍在-0.1附近徘徊训练策略上我们采用判别器更新频率高于生成器的经典WGAN-GP设定每轮训练中D更新5次G更新1次。这不是玄学而是因为D需先建立稳定的判别边界G才能沿有效梯度方向优化。代码实现如下# 训练主循环片段 for epoch in range(num_epochs): for i, (real_batch,) in enumerate(dataloader): real_batch real_batch.to(device) # --------------------- # 更新判别器D5次 # --------------------- for _ in range(5): optimizer_D.zero_grad() # 真实样本loss real_validity D(real_batch) d_real_loss -real_validity.mean() # 生成样本loss z torch.randn(real_batch.size(0), latent_dim, devicedevice) fake_batch G(z) fake_validity D(fake_batch.detach()) d_fake_loss fake_validity.mean() # 梯度惩罚 gradient_penalty compute_gradient_penalty(D, real_batch, fake_batch, device) d_loss d_real_loss d_fake_loss lambda_gp * gradient_penalty d_loss.backward() optimizer_D.step() # ----------------- # 更新生成器G1次 # ----------------- optimizer_G.zero_grad() gen_validity D(fake_batch) # 注意这里用上一轮生成的fake_batch非detach版 g_loss -gen_validity.mean() g_loss.backward() optimizer_G.step()提示fake_batch在D更新时用.detach()切断梯度在G更新时用原版这是WGAN-GP的标准写法。漏掉.detach()会导致D更新时意外更新G的权重引发不可预测的训练崩溃。4. 避坑指南轴承振动信号生成中5个最高频翻车点及解决方案做GAN-1D项目时80%的失败不是模型不行而是被几个隐蔽的工程细节绊倒。以下是我在3个项目中踩过的坑按发生频率排序每条都附带现象、根因和可立即执行的解决方案。4.1 现象训练初期D loss快速降到-10以下G loss停滞在-0.1左右生成信号全是高频噪声原因判别器D的网络容量过大或学习率过高导致其迅速学会“拒绝一切”生成器无法获得有效梯度信号。常见于直接套用图像GAN的D结构如6层卷积到1D信号。解决方案立即检查D的层数严格按本文2.2节的5层结构实现禁用任何残差连接或注意力机制将D学习率从默认1e-3降至4e-4并在训练日志中监控d_real_loss和d_fake_loss是否保持在[-2, 2]区间在D的最后一层全连接前添加nn.Dropout(0.3)抑制过拟合。4.2 现象生成信号的时域波形看起来“很平滑”但包络谱在故障频率处无峰值反而在0Hz附近有巨大直流分量原因预处理时未彻底消除趋势项trend。原始振动信号常含缓慢漂移如温度变化导致的基线偏移Z-score只能归一化幅值无法去除这种低频趋势。解决方案在Z-score前对每个1024点片段应用scipy.signal.detrend(linear)去除线性趋势或改用更鲁棒的scipy.signal.filtfilt(butter(2, 0.01, high), [1, 2, 1], signal_chunk)高通滤波0.01*fs120Hz滤除120Hz的漂移。4.3 现象训练到2000轮后生成器突然输出全零序列或所有样本都相同原因模式崩溃Mode Collapse的典型表现根源是真实数据多样性不足。当你的故障样本少于10组且都来自同一工况如固定转速生成器发现“复制某一个样本”就能骗过D便放弃探索其他模式。解决方案数据端对每组真实故障信号人为添加3种扰动——① ±5%随机缩放模拟传感器增益漂移、② ±20ms随机平移模拟触发时刻误差、③ 叠加信噪比20dB的白噪声模型端在生成器损失中加入多样性正则项L_div -torch.mean(torch.abs(G(z1) - G(z2)))其中z1,z2为两组不同噪声强制生成不同样本。4.4 现象生成信号经逆Z-score还原后幅值远超传感器量程但物理校验模块未报警原因校验模块中的幅值阈值5是针对Z-score后序列的经验值但该值依赖于真实数据的统计特性。若你的数据集本身含异常大冲击如严重剥落其Z-score后|signal|可达8此时阈值5会误杀有效样本。解决方案动态计算阈值threshold np.percentile(np.abs(real_train_data), 99.9)取真实数据99.9%分位数作为上限在校验函数中增加日志print(fReal data 99.9% percentile: {threshold:.3f})确保阈值合理。4.5 现象训练loss曲线平滑下降但生成信号的时频图与真实故障信号差异巨大尤其高频段能量衰减严重原因生成器最后一层Conv1DTranspose的kernel size过大如用8导致上采样过程过度平滑抹杀了冲击的瞬时性。1D信号的细节在时间维度不是空间维度。解决方案严格限定所有Conv1DTranspose的kernel size ≤ 4stride2padding1这是保证时序保真度的黄金组合在生成器中间层添加nn.Upsample(scale_factor2, modelinear)替代部分转置卷积线性插值比转置卷积更能保持边缘锐度。5. 生成结果验收与答辩技巧用三张图、一个表格、一次对比实验说服导师答辩时导师最关心的不是你用了多少酷炫技术而是“这生成的数据到底能不能用” 我们用一套可量化的验收流程回答这个问题包含三张必展示的图、一个核心对比表格以及一个让导师眼前一亮的对比实验。5.1 三张图构建可信度的视觉证据链图1时域对比图重点标冲击位置画4行×3列子图第1行是3组真实故障信号第2行是对应生成的3组信号第3行是它们的Hilbert包络第4行是包络谱。关键操作用红色竖线标出理论故障频率BPFO的位置并在包络图上用箭头标出周期性冲击的起始点。如果生成信号的冲击间隔与真实信号一致如都是12.7ms且包络谱峰值对齐BPFO这就是最直观的物理可信证据。图2t-SNE降维分布图证明分布对齐将真实故障信号、生成信号、正常信号各取200组用短时傅里叶变换STFT提取时频特征n_fft128, hop_length64得到特征矩阵后用t-SNE降到2D。理想结果真实故障与生成故障样本在t-SNE图上大面积重叠且与正常样本明显分离。若生成样本聚成孤立小团说明模式崩溃若与正常样本混杂说明生成失败。图3分类器性能提升曲线证明实用价值用真实故障数据训练一个轻量级CNN分类器3层卷积测试集准确率记为Baseline。然后分别用10、20、50、100组生成数据扩充训练集重新训练并记录测试准确率。画出“生成数据量 vs 准确率”曲线若曲线在20组后趋于平缓如从0.61→0.87→0.89就证明生成数据有效缓解了小样本瓶颈——这才是导师想听的“解决了什么问题”。5.2 一个表格量化指标对比表答辩PPT直接截图评估维度真实故障信号GAN-1D生成信号差异率是否达标冲击周期标准差(ms)12.7 ± 0.312.6 ± 0.53.2%是5%包络谱BPFO峰值信噪比(dB)18.217.53.8%是15dB时频图高频段5-10kHz能量占比22.1%21.3%3.6%是20%与真实信号的MMD距离—0.042—是0.05注MMDMaximum Mean Discrepancy是衡量两分布距离的无参方法用RBF核计算值越小分布越接近。计算代码见附录mmd_eval.py。5.3 一次对比实验生成数据 vs 数据增强谁更有效这是答辩时的杀手锏。很多同学会说“我用了SMOTE或GAN”但导师会问“那不用GAN只用传统增强如加噪、缩放、时移效果差多少” 我们设计了一个公平对比对照组对10组真实故障信号做5倍传统增强每组生成5个变体±5%缩放、±10ms平移、SNR20dB噪声共50组实验组用GAN-1D生成50组新信号统一训练用同一CNN模型、同一超参数在两组扩充数据上训练测试同一组真实故障样本。结果表格如下方法测试集F1-score故障类型识别准确率内圈/外圈/滚动体过拟合迹象训练/测试acc差传统增强0.730.68 / 0.71 / 0.750.12训练0.85/测试0.73GAN-1D生成0.870.85 / 0.86 / 0.890.04训练0.91/测试0.87结论清晰GAN生成的数据不仅提升精度还显著降低过拟合——因为它学到了故障的内在动力学模式而非简单复制噪声。答辩时指着这个表格说“老师传统增强只是‘换着花样看同一个病人’而GAN是在‘培养新的病人’所以泛化更好。”从那以后我每次做生成类毕设都强制走一遍这三张图一张表一次对比实验的验收流程。不是为了应付答辩而是这套流程逼着我把“生成是否成功”从主观感受变成可测量、可复现、可辩论的工程事实。希望帮到你。本文还有配套的精品资源点击获取