Research on Bearing Fault Diagnosis Based on Continuous Wavelet Transform and Convolutional Neural Network

Summary

       Based on the bearing data of Case Western Kitchen University, firstly, the data augmentation method is used to oversample the original data to increase the number of samples. Then, using continuous wavelet transform, the one-dimensional training samples are converted into two-dimensional RGB images. Second, the processed samples are divided into training sets and test sets, and input to the convolutional neural network training. Finally, the T-SNE dimensionality reduction algorithm is used to dynamically visualize the network layer specified by the model.

data set

        A bearing failure benchmark dataset obtained by the Case Western Reserve University (CWRU) data center in the United States is introduced. An experimental test bench (as shown in Figure 1) is used to detect the bearing defect detection signal. The platform consists of a 1.5W electric motor (left), torque sensor decoder (middle), and a power test meter (right). The bearing is damaged by the use of EDM, and the damage positions are the outer ring, the inner ring and the rolling elements. There are two types of bearings, one is the bearing placed on the drive end, the model is SKF6205, and the sampling frequency is 12Khz and 48Khz. The other is the bearing placed at the fan end, the model is SKF6203, and the sampling frequency is 12Khz. The acquisition of the vibration signal is done by the accelerometer. The data used in this study are all from the drive end bearing with a sampling frequency of 12Khz. Meanwhile, the bearing failure diameters used in the experiments were 0.007 inches, 0.014 inches, and 0.021 inches.

Figure 1 Bearing data of Case Western Reserve University

Western Reserve University download address: http://csegroups.case.edu/bearingdatacenter/pages/download-data-file

         The above is the official data, download it by yourself, and organize and classify it according to your own needs. Below is the data folder that I have organized myself. 07, 14, 21 are three bearing sizes; 0, 1, 2, 3 are 4 different loads; 1797, 1772, 1750, 1797 are speeds for 4 different loads. as shown in picture 2.

 Figure 2 Data type data organization

 data preprocessing

        In the data preprocessing part, use matlab for data enhancement and continuous wavelet change.

1. Data Augmentation

        Although deep learning has a good learning ability, it usually has a disadvantage: it needs a relatively large amount of data to obtain a better effect. Considering that the number of vibration signals in each bearing fault type is only more than 120,000, according to 1024 vibration signal points as a sample, there are only 120 samples at most. Therefore, in order to enhance the generalization and robustness of the model, data augmentation methods are used to expand the dataset. Simple and rough understanding, it is like cutting a watermelon. Originally a large piece of watermelon, you cut a lot of knives according to a certain distance and direction, and turned into several uniform pieces of watermelon.

Principle reference: https://blog.csdn.net/zhangjiali12011/article/details/98039748

2. Continuous Wavelet Transform

        Compared with the short-time Fourier transform, the wavelet transform has the characteristics of window adaptation, that is, the high-frequency signal has high resolution (but poor frequency resolution), and the low-frequency signal has high frequency resolution (but poor time resolution). In engineering, we often care about the frequency of low frequencies and the time when high frequencies appear, so they have been widely used in recent years. Simple and rude understanding, transform the original one-dimensional data into a two-dimensional image.

Principle reference: https://blog.csdn.net/weixin_42943114/article/details/896032

3. Effect display

Due to the limited configuration of my computer, the calculation speed is still a bit insufficient in all aspects, and only 6 types of fault diagnosis have been made. As shown in Figure 3.

 105inner data

 

 118ball data

 130outer data

 

 119ball data

  119inner data

 131outer data

Figure 3 Six wavelet transform effects

 model training

         The structure of the VGG16 convolutional neural network is shown in Figure 4. Through the repeated stacking of convolution layers and pooling layers , there are 13 convolution layers and 3 fully connected layers . The pooling layer does not count the weights, so it is not included in the total number of layers. The convolutional layer and the pooling layer are actually an extraction process for the input image. The multi-layer convolutional pooling layers are stacked on each other, which makes the network have a larger receptive field while reducing the network parameters. The single linear change of , becomes diversified, and the learning ability is also enhanced [10] . The samples can be classified through the fully connected layer and the output layer, and the probability distribution of the current samples belonging to different categories can be obtained through the softmax activation function.            

   

Figure 4 VGG16 model

db_train = tf.data.Dataset.from_tensor_slices((x_train,y_train))
db_train = db_train.shuffle(1000).batch(4)

db_test = tf.data.Dataset.from_tensor_slices((x_test,y_test))

sample = next(iter(db_train))
print("sample: ",sample[0].shape,sample[1].shape)

#--------------------------------卷积神经网络-----------------------------------------
conv_layers = [
    layers.Conv2D(64, kernel_size=[3, 3], padding="same", activation=tf.nn.relu),
    layers.Conv2D(64, kernel_size=[3, 3], padding="same", activation=tf.nn.relu),
    layers.MaxPool2D(pool_size=[4, 4], strides=4, padding='same'),

    # unit 2
    layers.Conv2D(128, kernel_size=[3, 3], padding="same", activation=tf.nn.relu),
    layers.Conv2D(128, kernel_size=[3, 3], padding="same", activation=tf.nn.relu),
    layers.MaxPool2D(pool_size=[4, 4], strides=4, padding='same'),

    # unit 3
    layers.Conv2D(256, kernel_size=[3, 3], padding="same", activation=tf.nn.relu),
    layers.Conv2D(256, kernel_size=[3, 3], padding="same", activation=tf.nn.relu),
    layers.MaxPool2D(pool_size=[4, 4], strides=4, padding='same'),

    # unit 4
    layers.Conv2D(512, kernel_size=[3, 3], padding="same", activation=tf.nn.relu),
    layers.Conv2D(512, kernel_size=[3, 3], padding="same", activation=tf.nn.relu),
    layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same'),

    # unit 5
    layers.Conv2D(512, kernel_size=[3, 3], padding="same", activation=tf.nn.relu),
    layers.Conv2D(512, kernel_size=[3, 3], padding="same", activation=tf.nn.relu),
    layers.MaxPool2D(pool_size=[2, 2], strides=2, padding='same')
]

def main():
    conv_net = Sequential(conv_layers)
    # 测试输出的图片尺寸
    conv_net.build(input_shape=[None, 128, 128, 3])
    x = tf.random.normal([4, 128, 128, 3])
    out = conv_net(x)
    print(out.shape)

    # 设置全连接层
    fc_net = Sequential([
        layers.Dense(256, activation=tf.nn.relu),
        layers.Dense(128, activation=tf.nn.relu),
        layers.Dense(6, activation=None)
    ])

    conv_net.build(input_shape=[None, 128, 128, 3])
    fc_net.build(input_shape=[None, 512])
    optimizer = optimizers.Adam(lr=0.00001)

    variables = conv_net.trainable_variables + fc_net.trainable_variables

    for epoch in range(50):
        for step,(x,y) in enumerate(db_train):
            with tf.GradientTape() as tape:
             
                out = conv_net(x)
             
                out = tf.reshape(out,[-1,512])
                
                logits = fc_net(out)

                y_hot = tf.one_hot(y,depth=3)
                # 计算loss数值
                loss = tf.losses.categorical_crossentropy(y_hot,logits,from_logits=True)
                loss = tf.reduce_mean(loss)

            grads = tape.gradient(loss,variables)
            optimizer.apply_gradients(zip(grads,variables))

            if step % 20 ==0:
                print(epoch, step, "loss ", float(loss))

        total_num = 0
        totsl_correct = 0
        for x,y in db_test:
            x = tf.expand_dims(x,axis=0)
            # print(x.shape)
            out = conv_net(x)
            out = tf.reshape(out,[-1,512])
            logits = fc_net(out)
            prob = tf.nn.softmax(logits,axis=1)

            pred = tf.argmax(prob,axis=1)
            pred = tf.cast(pred,dtype=tf.int32)

            correct = tf.cast(tf.equal(pred,y),dtype=tf.int32)
            correct = tf.reduce_sum(correct)

            total_num += x.shape[0]
            totsl_correct += int(correct)
        acc = totsl_correct/total_num
        print(epoch, acc)
        conv_net.save('weights/conv.h5')
        fc_net.save('weights/fc.h5')

 Model testing

import tensorflow as tf
from tensorflow.keras import layers,optimizers,datasets,Sequential
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

os.environ['CUDA_VISIBLE_DEVICES'] = '/gpu:0'
tf.random.set_seed(2345)

from PIL import Image
import numpy as np

#-------------------------------读取待预测图片------------------------------------
ima1 = os.listdir('E:/prediction/')
def read_image1(filename):
    img = Image.open('E:/prediction/'+filename).convert('RGB')
    return np.array(img)

x_train = []
for i in ima1:
    x_train.append(read_image1(i))
x_train = np.array(x_train)

#-------------------------------加载神经网络模型-----------------------------------
conv_net = tf.keras.models.load_model('weights/conv.h5')
fc_net = tf.keras.models.load_model('weights/fc.h5')

#-----------------------------------图片识别--------------------------------------
out = conv_net(x_train)
out = tf.reshape(out,[-1,512])
logits = fc_net(out)

prob = tf.nn.softmax(logits,axis=1)
prob = np.array(prob)

pred = tf.argmax(prob,axis=1)
pred = np.array(pred)
print(pred)

  Model T-SNE Dynamic Display

1. Generate a picture

        SNE is stochastic neighbor embedding. The basic idea is that similar data points in high-dimensional space are mapped to low-dimensional space with similar distances. SNE converts this distance relationship into a conditional probability to represent similarity. 

        In this paper, we focus on dynamic visualization of the last output layer of the fully connected layer. The first step is to generate a figure for each epoch and save it to the specified folder. Finally, use the gif tool to make dynamic display pictures. There are many ways to do it, and it is good to be able to achieve the effect.

Principle reference: https://blog.csdn.net/SweetSeven_/article/details/108010565

    #轴承数据训练
    for epoch in range(20):
        # 定义列表,data_xx存放训练数据,data_y存放训练数据标签
        data_xx = []
        data_y = []

        for step,(x,y) in enumerate(db_train):
            with tf.GradientTape() as tape:
                #计算一个batchsize的卷积神经网络输出
                out = conv_net(x)
                #卷积神经网络输出数据进行reshape[-1,512]
                out = tf.reshape(out,[-1,512])
                #reshape的数据输入到全连接层
                logits = fc_net(out)
                #最终输出数据进行one_hot转换
                y_hot = tf.one_hot(y,depth=6)
                # 计算loss数值
                loss = tf.losses.categorical_crossentropy(y_hot,logits,from_logits=True)
                loss = tf.reduce_mean(loss)

            grads = tape.gradient(loss,variables)
            optimizer.apply_gradients(zip(grads,variables))

            #每隔20个bachsize,输出一次loss数值
            if step % 20 ==0:
                print(epoch, step, "loss ", float(loss))

            if epoch >= 2:
                # 列出对应元素的标签值
                data_y.extend(y)
                # 获取所有训练后的样本数据
                for i in range(len(logits)):
                    # 得到训练的样本
                    data_xx.append(logits[i])
                #每次epoch将data_y和data_xx列表转换为numpy数据


        if epoch >= 2:
            data_y = np.array(data_y)
            data_xx = np.array(data_xx)
            # print("data_xx", data_xx.shape)
            # print("data_y", data_y.shape)
            # print("data_y", data_y)
            #进行tsne降维
            tsne = manifold.TSNE(n_components=2, init='pca')
            X_tsne = tsne.fit_transform(data_xx)

            #将降维数据进行可视化显示
            x_min, x_max = X_tsne.min(0), X_tsne.max(0)
            X_norm = (X_tsne - x_min) / (x_max - x_min)  # 归一化

            for i in range(len(X_norm)):
                # plt.text(X_norm[i, 0], X_norm[i, 1], str(y[i]), color=plt.cm.Set1(y[i]),
                if data_y[i] == 0:
                    color = 'r'
                if data_y[i] == 1:
                    color = 'g'
                if data_y[i] == 2:
                    color = 'b'
                if data_y[i] == 3:
                    color = 'c'
                if data_y[i] == 4:
                    color = 'm'
                if data_y[i] == 5:
                    color = 'k'
                #          fontdict={'weight': 'bold', 'size': 9})
                plt.scatter(X_norm[i][0], X_norm[i][1], c=color, cmap=plt.cm.Spectral)

            plt.xticks([])
            plt.yticks([])
            plt.savefig("E:/tsne_figure/" + str(epoch) + ".png")
            plt.close('all')

2. Generate gif

# 初始化图片地址文件夹途径

image_path = 'E:/tsne_figure/'

# 获取文件列表

files = os.listdir(image_path)

# 定义第一个文件的全局路径

file_first_path = os.path.join(image_path, files[0])

# 获取Image对象

img = Image.open(file_first_path)

# 初始化文件对象数组

images = []

for image in files[:]:
    # 获取当前图片全量路径

    img_path = os.path.join(image_path, image)

    # 将当前图片使用Image对象打开、然后加入到images数组

    images.append(Image.open(img_path))

# 保存并生成gif动图

img.save('beauty.gif', save_all=True, append_images=images, loop=0, duration=200)

3. Effect demonstration

        The computing power of the computer is not enough, and 20 epochs run all night. Finally, the loss is stable at around 0.005, which is visualized by tsne, which basically realizes the separation of different types.        

PS: This is the first time I write a blog, there are many shortcomings, please forgive me. The time is relatively short, and the code will be improved after a while, and all the code and data will be attached to the second article.

Guess you like

Origin blog.csdn.net/qq_36865346/article/details/120053869