当前位置:   article > 正文

基于短时傅里叶变换和卷积神经网络的轴承故障诊断研究_轴承时频图卷积

轴承时频图卷积

目录

摘要

数据集

数据预处理

短时傅里叶变换原理

公式表示

基于python的stft实现

数据划分

故障诊断


摘要

        基于凯斯西储大学的轴承数据,首先利用短时傅里叶变换,将一维的训练样本转换为二维图像。然后,将处理好的样本进行样本分割为训练集、测试集,输入到卷积神经网络训练。

数据集

       CWRU(Case Western Reserve University)轴承故障数据集是一个用于振动信号分析和故障诊断的公开数据集。这个数据集主要用于机械设备(轴承)的故障检测和诊断研究。

        该数据集由Case Western Reserve University的机械与航空工程系提供。它是通过在不同工作条件下采集轴承的振动信号得到的。 

        数据集包含四个不同工作条件下的振动信号,每个工作条件都包含正常运行和不同类型故障(例如内圈故障、外圈故障、滚珠故障等)的振动信号。因此,总共有多个类别的振动信号,适用于故障检测和分类任务。

        振动信号是使用加速度计(accelerometers)测量得到的。这些振动信号通常包含有关轴承状态的信息,因此对于机械系统的健康状态监测和故障预测非常有用。

        CWRU轴承故障数据集通常被用于测试和评估振动信号处理、特征提取、机器学习和深度学习等技术在机械故障检测领域的性能。研究人员和工程师可以使用这个数据集来开发和验证他们的故障诊断算法。

数据预处理

傅里叶变换的基本思想:

  • 将信号分解成一系列不同频率的连续正弦波的叠加;
  • 将信号从时间域转换到频率域。

由于傅里叶变换是对整个信号进行变换,将整个信号从时域转换到频域,得到一个整体的频谱;丢掉了时间信息,无法根据傅立叶变换的结果判断一个特定信号在什么时候发生;所以傅里叶变换缺乏时频分析能力、多分辨率分析能力,难以分析非平稳信号。

短时傅里叶变换(Short-Time Fourier Transform,STFT)是一种将信号分解为时域和频域信息的时频分析方法。它通过将信号分成短时段,并在每个短时段上应用傅里叶变换来捕捉信号的瞬时频率。即采用中心位于时间α的时间窗g(t-α)在时域信号上滑动,在时间窗g(t-α)限定的范围内进行傅里叶变换,这样就使短时傅里叶变换具有了时间和频率的局部化能力,兼顾了时间和频率的分析。

  • 使用窄窗,时间分辨率提高而频率分辨率降低;
  • 使用宽窗,频率分辨率提高而时间分辨率降低。

短时傅里叶变换原理

1.时间分割

        在短时傅里叶变换(STFT)中,首先将信号分割成短时段。这个过程通常通过使用窗口函数来实现,窗口函数是一个在有限时间内非零,而在其他时间上为零的函数。常见的窗口函数有矩形窗、汉明窗、汉宁窗等。通过将窗口函数应用于信号,可以将信号分成许多短时段。

2.傅里叶变换

        对于每个短时段,都会进行傅里叶变换。傅里叶变换是一种将信号从时域(时间域)转换为频域(频率域)的方法。在这个上下文中,它用于分析每个短时段内信号的频率成分。傅里叶变换将信号表示为不同频率的正弦和余弦函数的组合。

3.时频图:

        将每个短时段的傅里叶变换结果排列成一个矩阵,构成了时频图。时频图的横轴表示时间,纵轴表示频率,而每个点的强度表示对应频率在对应时刻的幅度。时频图提供了一种直观的方式来观察信号在时间和频率上的变化。

公式表示

基于python的stft实现

  1. import pandas as pd
  2. import numpy as np
  3. from scipy.signal import stft
  4. import matplotlib.pyplot as plt
  5. import os
  6. # 读取csv文件
  7. data1 = pd.read_csv('E:/pycharm_file/fuel_system/data/cwru_data/normal.csv')
  8. data2 = pd.read_csv('E:/pycharm_file/fuel_system/data/cwru_data/b.csv')
  9. data3 = pd.read_csv('E:/pycharm_file/fuel_system/data/cwru_data/ir.csv')
  10. data4 = pd.read_csv('E:/pycharm_file/fuel_system/data/cwru_data/or.csv')
  11. print(f'data1.shape:{data1.shape}')
  12. # 注意,读取出来的data是字典格式,可以通过函数type(data)查看。
  13. # 划窗取值(大多数窗口大小为1024)
  14. data_list1 = data1[0:1024].values.reshape(-1)
  15. data_list2 = data2[0:1024].values.reshape(-1)
  16. data_list3 = data3[0:1024].values.reshape(-1)
  17. data_list4 = data4[0:1024].values.reshape(-1)
  18. # 数据可视化
  19. plt.figure(figsize=(20,10))
  20. plt.subplot(2,2,1)
  21. plt.plot(data_list1)
  22. plt.title('normal')
  23. plt.subplot(2,2,2)
  24. plt.plot(data_list2)
  25. plt.title('b')
  26. plt.subplot(2,2,3)
  27. plt.plot(data_list3)
  28. plt.title('ir')
  29. plt.subplot(2,2,4)
  30. plt.plot(data_list4)
  31. plt.title('or')
  32. plt.show()
  33. # STFT参数需要人工选择,通过下面的对比,选择window_size = 8
  34. # 设置STFT参数
  35. window_size = 4 # 窗口大小
  36. overlap = 0.5 # 重叠比例
  37. # 计算重叠的样本数
  38. overlap_samples = int(window_size * overlap)
  39. frequencies1, times1, magnitude1 = stft(data_list2, nperseg=window_size, noverlap=overlap_samples)
  40. # 设置STFT参数
  41. window_size = 8 # 窗口大小
  42. overlap = 0.5 # 重叠比例
  43. # 计算重叠的样本数
  44. overlap_samples = int(window_size * overlap)
  45. frequencies2, times2, magnitude2 = stft(data_list2, nperseg=window_size, noverlap=overlap_samples)
  46. # 设置STFT参数
  47. window_size = 16 # 窗口大小
  48. overlap = 0.5 # 重叠比例
  49. # 计算重叠的样本数
  50. overlap_samples = int(window_size * overlap)
  51. frequencies3, times3, magnitude3 = stft(data_list2, nperseg=window_size, noverlap=overlap_samples)
  52. # 设置STFT参数
  53. window_size = 32 # 窗口大小
  54. overlap = 0.5 # 重叠比例
  55. # 计算重叠的样本数
  56. overlap_samples = int(window_size * overlap)
  57. frequencies4, times4, magnitude4 = stft(data_list2, nperseg=window_size, noverlap=overlap_samples)
  58. plt.figure(figsize=(20,10), dpi=100)
  59. plt.subplot(2,2,1)
  60. plt.pcolormesh(times1, frequencies1, np.abs(magnitude1), shading='gouraud')
  61. plt.title('window_size = 4')
  62. plt.subplot(2,2,2)
  63. plt.pcolormesh(times2, frequencies2, np.abs(magnitude2), shading='gouraud')
  64. plt.title('window_size = 8')
  65. plt.subplot(2,2,3)
  66. plt.pcolormesh(times3, frequencies3, np.abs(magnitude3), shading='gouraud')
  67. plt.title('window_size = 16')
  68. plt.subplot(2,2,4)
  69. plt.pcolormesh(times4, frequencies4, np.abs(magnitude4), shading='gouraud')
  70. plt.title('window_size = 32')
  71. plt.show()
        下图为取前1024数据图像:

        stft需要人工对窗口宽度进行选择,根据下图选择window_size=8

        下图是选择window_size=8,四种情况的stft图像:

        从图中可以看出,四种情况的stft图像存在较大差异,适合图像分类。

数据划分

        将图像划分为训练集:测试集=9:1。

故障诊断

        采用VGG卷积神经网络进行故障诊断。

  1. from torch import nn
  2. import torch
  3. class VGG(nn.Module):
  4. def __init__(self, features, num_classes=1000, init_weights=False):
  5. super(VGG, self).__init__()
  6. self.featurs = features
  7. self.classifier = nn.Sequential(
  8. nn.Linear(512 * 7 * 7, 4096),
  9. nn.ReLU(inplace=True),
  10. nn.Dropout(p=0.5),
  11. nn.Linear(4096, 4096),
  12. nn.ReLU(inplace=True),
  13. nn.Dropout(p=0.5),
  14. nn.Linear(4096, num_classes)
  15. )
  16. # 初始化参数
  17. if init_weights:
  18. self._initialize_weights()
  19. def forward(self, x):
  20. # N x 3 X 224 x224
  21. x = self.featurs(x)
  22. # N x 512 x 7 x 7
  23. x = torch.flatten(x, start_dim=1)
  24. # N x 512*7*7
  25. x = self.classifier(x)
  26. return x
  27. def _initialize_weights(self):
  28. for m in self.modules(): # 变量网络所有层
  29. if isinstance(m, nn.Conv2d): # 是否为卷积层
  30. # 使用Kaiming初始化方法来初始化该层的权重
  31. nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
  32. if m.bias is not None: # 否具有偏差项
  33. nn.init.constant_(m.bias, 0)
  34. elif isinstance(m, nn.Linear): # 是否为Linear
  35. # 正太分布初始化全连接层
  36. nn.init.normal_(m.weight, 0, 0.01)
  37. # 将偏项设置为0
  38. nn.init.constant_(m.bias, 0)
  39. def make_features(cfg: list):
  40. # 创建一个空列表用于存储神经网络的不同层
  41. layers = []
  42. # 初始输入通道数
  43. in_channels = 3
  44. # 遍历传入的配置列表
  45. for v in cfg:
  46. if v == "M": # 池化层3
  47. layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
  48. else: # 卷积层
  49. conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1)
  50. layers += [conv2d, nn.ReLU(inplace=True)]
  51. # 更新输入通道数,以便下一层的卷积层使用
  52. in_channels = v
  53. # 返回一个包含所有层的顺序容器,通常是一个特征提取器部分
  54. return nn.Sequential(*layers)
  55. # 定义了不同VGG模型的卷积配置信息,其中 'M' 表示池化层,数字表示卷积层的输出通道数
  56. cfgs = {
  57. 'vgg11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
  58. 'vgg13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
  59. 'vgg16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
  60. 'vgg19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
  61. }
  62. # 定义一个函数 vgg,用于构建不同类型的VGG神经网络模型
  63. def vgg(model_name="vgg16", **kwargs):
  64. # 检查传入的模型名是否在配置字典中
  65. assert model_name in cfgs, "Warning: model number {} not in cfgs dict!".format(model_name)
  66. # 根据模型名获取对应的卷积配置信息
  67. cfg = cfgs[model_name]
  68. # 使用 make_features 函数创建特征提取器,然后将其传递给 VGG 模型
  69. model = VGG(make_features(cfg), **kwargs)
  70. return model

训练结果

        从训练结果可以看出,经过十轮训练,准确率可以达到97.5%。结果还是挺满意的。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/694462
推荐阅读
相关标签
  

闽ICP备14008679号