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

本文介绍了如何使用CWRU轴承故障数据集,通过短时傅里叶变换将振动信号转换为二维图像,然后利用CNN进行故障诊断。实验中展示了不同窗口大小的STFT结果,并利用VGG模型实现了高精度的故障识别,训练结果显示97.5%的准确率。
摘要由CSDN通过智能技术生成

目录

摘要

数据集

数据预处理

短时傅里叶变换原理

公式表示

基于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实现

import pandas as pd
import numpy as np
from scipy.signal import stft
import matplotlib.pyplot as plt
import os
# 读取csv文件
data1 = pd.read_csv('E:/pycharm_file/fuel_system/data/cwru_data/normal.csv')
data2 = pd.read_csv('E:/pycharm_file/fuel_system/data/cwru_data/b.csv')
data3 = pd.read_csv('E:/pycharm_file/fuel_system/data/cwru_data/ir.csv')
data4 = pd.read_csv('E:/pycharm_file/fuel_system/data/cwru_data/or.csv')
print(f'data1.shape:{data1.shape}')
# 注意,读取出来的data是字典格式,可以通过函数type(data)查看。
# 划窗取值(大多数窗口大小为1024)
data_list1 = data1[0:1024].values.reshape(-1)
data_list2 = data2[0:1024].values.reshape(-1)
data_list3 = data3[0:1024].values.reshape(-1)
data_list4 = data4[0:1024].values.reshape(-1)

# 数据可视化
plt.figure(figsize=(20,10))
plt.subplot(2,2,1)
plt.plot(data_list1)
plt.title('normal')
plt.subplot(2,2,2)
plt.plot(data_list2)
plt.title('b')
plt.subplot(2,2,3)
plt.plot(data_list3)
plt.title('ir')
plt.subplot(2,2,4)
plt.plot(data_list4)
plt.title('or')
plt.show()

# STFT参数需要人工选择,通过下面的对比,选择window_size = 8
# 设置STFT参数
window_size = 4  # 窗口大小
overlap = 0.5  # 重叠比例
# 计算重叠的样本数
overlap_samples = int(window_size * overlap)
frequencies1, times1, magnitude1 = stft(data_list2, nperseg=window_size, noverlap=overlap_samples)

# 设置STFT参数
window_size = 8  # 窗口大小
overlap = 0.5  # 重叠比例
# 计算重叠的样本数
overlap_samples = int(window_size * overlap)
frequencies2, times2, magnitude2 = stft(data_list2, nperseg=window_size, noverlap=overlap_samples)

# 设置STFT参数
window_size = 16  # 窗口大小
overlap = 0.5  # 重叠比例
# 计算重叠的样本数
overlap_samples = int(window_size * overlap)
frequencies3, times3, magnitude3 = stft(data_list2, nperseg=window_size, noverlap=overlap_samples)

# 设置STFT参数
window_size = 32  # 窗口大小
overlap = 0.5  # 重叠比例
# 计算重叠的样本数
overlap_samples = int(window_size * overlap)
frequencies4, times4, magnitude4 = stft(data_list2, nperseg=window_size, noverlap=overlap_samples)

plt.figure(figsize=(20,10), dpi=100)
plt.subplot(2,2,1)
plt.pcolormesh(times1, frequencies1, np.abs(magnitude1), shading='gouraud')
plt.title('window_size = 4')
plt.subplot(2,2,2)
plt.pcolormesh(times2, frequencies2, np.abs(magnitude2), shading='gouraud')
plt.title('window_size = 8')
plt.subplot(2,2,3)
plt.pcolormesh(times3, frequencies3, np.abs(magnitude3), shading='gouraud')
plt.title('window_size = 16')
plt.subplot(2,2,4)
plt.pcolormesh(times4, frequencies4, np.abs(magnitude4), shading='gouraud')
plt.title('window_size = 32')
plt.show()
        下图为取前1024数据图像:

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

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

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

数据划分

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

故障诊断

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

from torch import nn
import torch

class VGG(nn.Module):
    def __init__(self, features, num_classes=1000, init_weights=False):
        super(VGG, self).__init__()
        self.featurs = features
        self.classifier = nn.Sequential(
            nn.Linear(512 * 7 * 7, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(p=0.5),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(p=0.5),
            nn.Linear(4096, num_classes)
        )

        # 初始化参数
        if init_weights:
            self._initialize_weights()

    def forward(self, x):
        # N x 3 X 224 x224
        x = self.featurs(x)
        # N x 512 x 7 x 7
        x = torch.flatten(x, start_dim=1)
        # N x 512*7*7
        x = self.classifier(x)
        return x

    def _initialize_weights(self):
        for m in self.modules():  # 变量网络所有层
            if isinstance(m, nn.Conv2d):  # 是否为卷积层
                # 使用Kaiming初始化方法来初始化该层的权重
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
                if m.bias is not None:  # 否具有偏差项
                    nn.init.constant_(m.bias, 0)
            elif isinstance(m, nn.Linear):  # 是否为Linear
                # 正太分布初始化全连接层
                nn.init.normal_(m.weight, 0, 0.01)
                # 将偏项设置为0
                nn.init.constant_(m.bias, 0)


def make_features(cfg: list):
    # 创建一个空列表用于存储神经网络的不同层
    layers = []
    # 初始输入通道数
    in_channels = 3
    # 遍历传入的配置列表
    for v in cfg:
        if v == "M":  # 池化层3
            layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
        else:  # 卷积层
            conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1)
            layers += [conv2d, nn.ReLU(inplace=True)]
            # 更新输入通道数,以便下一层的卷积层使用
            in_channels = v
    # 返回一个包含所有层的顺序容器,通常是一个特征提取器部分
    return nn.Sequential(*layers)


# 定义了不同VGG模型的卷积配置信息,其中 'M' 表示池化层,数字表示卷积层的输出通道数
cfgs = {
    'vgg11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
    'vgg13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
    'vgg16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
    'vgg19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
}


# 定义一个函数 vgg,用于构建不同类型的VGG神经网络模型
def vgg(model_name="vgg16", **kwargs):
    # 检查传入的模型名是否在配置字典中
    assert model_name in cfgs, "Warning: model number {} not in cfgs dict!".format(model_name)
    # 根据模型名获取对应的卷积配置信息
    cfg = cfgs[model_name]

    # 使用 make_features 函数创建特征提取器,然后将其传递给 VGG 模型
    model = VGG(make_features(cfg), **kwargs)
    return model

训练结果

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

  • 17
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值