Pesquisa em Diagnóstico de Falhas em Rolamentos Baseado em Transformada Wavelet Contínua e Rede Neural Convolucional

Resumo

       Com base nos dados de rolamento da Case Western Kitchen University, em primeiro lugar, o método de aumento de dados é usado para superamostrar os dados originais para aumentar o número de amostras. Em seguida, usando a transformada wavelet contínua, as amostras de treinamento unidimensionais são convertidas em imagens RGB bidimensionais. Em segundo lugar, as amostras processadas são divididas em conjuntos de treinamento e conjuntos de teste e entrada para o treinamento da rede neural convolucional. Por fim, o algoritmo de redução de dimensionalidade T-SNE é usado para visualizar dinamicamente a camada de rede especificada pelo modelo.

conjunto de dados

        Um conjunto de dados de referência de falha de rolamento obtido pelo data center da Case Western Reserve University (CWRU) nos Estados Unidos é apresentado. Uma bancada de teste experimental (como mostrado na Figura 1) é usada para detectar o sinal de detecção de defeito do rolamento. A plataforma consiste em um motor elétrico de 1,5 W (esquerda), decodificador do sensor de torque (meio) e um medidor de teste de potência (direita). O rolamento é danificado pelo uso de EDM, e as posições de dano são o anel externo, o anel interno e os corpos rolantes. Existem dois tipos de rolamentos, um é o rolamento colocado na extremidade da unidade, o modelo é SKF6205 e a frequência de amostragem é de 12Khz e 48Khz. O outro é o rolamento colocado na extremidade do ventilador, o modelo é SKF6203 e a frequência de amostragem é de 12Khz. A aquisição do sinal de vibração é feita pelo acelerômetro. Os dados usados ​​neste estudo são todos do rolamento da extremidade do acionamento com uma frequência de amostragem de 12Khz. Enquanto isso, os diâmetros de falha do rolamento usados ​​nos experimentos foram de 0,007 polegadas, 0,014 polegadas e 0,021 polegadas.

Figura 1 Dados de rolamento da Case Western Reserve University

Endereço de download da Western Reserve University: http://csegroups.case.edu/bearingdatacenter/pages/download-data-file

         Os dados acima são os oficiais, baixe-os você mesmo e organize-os e classifique-os de acordo com suas próprias necessidades. Abaixo está a pasta de dados que eu mesmo organizei. 07, 14, 21 são três tamanhos de rolamento; 0, 1, 2, 3 são 4 cargas diferentes; 1797, 1772, 1750, 1797 são velocidades para 4 cargas diferentes. como mostrado na imagem 2.

 Figura 2 Organização de dados do tipo de dados

 pré-processamento de dados

        Na parte de pré-processamento de dados, use o matlab para aprimoramento de dados e mudança contínua de wavelet.

1. Aumento de dados

        Embora o aprendizado profundo tenha uma boa capacidade de aprendizado, geralmente tem uma desvantagem: precisa de uma quantidade relativamente grande de dados para obter um efeito melhor. Considerando que o número de sinais de vibração em cada tipo de falha de rolamento é apenas superior a 120.000, de acordo com 1024 pontos de sinal de vibração como amostra, existem apenas 120 amostras no máximo. Portanto, a fim de aumentar a generalização e robustez do modelo, métodos de aumento de dados são usados ​​para expandir o conjunto de dados. Entendimento simples e grosseiro, é como cortar uma melancia. Originalmente um grande pedaço de melancia, você corta muitas facas de acordo com uma certa distância e direção, e se transforma em vários pedaços uniformes de melancia.

Referência do princípio: https://blog.csdn.net/zhangjiali12011/article/details/98039748

2. Transformada Wavelet Contínua

        Comparada com a transformada de Fourier de curta duração, a transformada wavelet tem as características de adaptação de janela, ou seja, o sinal de alta frequência tem alta resolução (mas baixa resolução de frequência), e o sinal de baixa frequência tem resolução de alta frequência (mas pobre Na engenharia, muitas vezes nos preocupamos com a frequência das baixas frequências e o momento em que as altas frequências aparecem, por isso elas têm sido amplamente utilizadas nos últimos anos. Compreensão simples e grosseira, transforma os dados originais unidimensionais em uma imagem bidimensional.

Referência do princípio: https://blog.csdn.net/weixin_42943114/article/details/896032

3. Exibição do efeito

Devido à configuração limitada do meu computador, a velocidade de cálculo ainda é um pouco insuficiente em todos os aspectos, e apenas 6 tipos de diagnóstico de falhas foram feitos. Como mostrado na Figura 3.

 105dados internos

 

 dados da bola 118

 130 dados externos

 

 dados da bola 119

  119dados internos

 131 dados externos

Figura 3 Seis efeitos de transformada wavelet

 treinamento de modelo

         A estrutura da rede neural convolucional VGG16 é mostrada na Figura 4. Através do empilhamento repetido de camadas de convolução e camadas de agrupamento , existem 13 camadas de convolução e 3 camadas totalmente conectadas . A camada de agrupamento não conta os pesos, portanto não é incluída no número total de camadas. A camada convolucional e a camada de pooling são na verdade um processo de extração para a imagem de entrada. As camadas de pooling convolucional multicamadas são empilhadas umas sobre as outras, o que faz com que a rede tenha um campo enquanto reduz os parâmetros da rede.receptivo [10] . As amostras podem ser classificadas através da camada totalmente conectada e da camada de saída, e a distribuição de probabilidade das amostras atuais pertencentes a diferentes categorias pode ser obtida através da função de ativação softmax.            

   

Figura 4 modelo VGG16

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')

 Teste de modelo

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)

  Exibição Dinâmica Modelo T-SNE

1. Gere uma imagem

        SNE é a incorporação estocástica de vizinhos A ideia básica é que pontos de dados semelhantes em espaço de alta dimensão sejam mapeados para espaço de baixa dimensão com distâncias semelhantes. SNE converte esta relação de distância em uma probabilidade condicional para representar similaridade. 

        Neste artigo, focamos na visualização dinâmica da última camada de saída da camada totalmente conectada. O primeiro passo é gerar uma figura para cada época e salvá-la na pasta especificada. Por fim, use a ferramenta gif para criar imagens de exibição dinâmicas. Há muitas maneiras de fazê-lo, e é bom poder alcançar o efeito.

Referência do princípio: 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. Gerar 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. Demonstração do efeito

        O poder de computação do computador não é suficiente, e 20 épocas são executadas a noite toda. Por fim, a perda é estável em torno de 0,005, o que é visualizado pelo tsne, que basicamente realiza a separação de diferentes tipos.        

PS: Esta é a primeira vez que escrevo um blog, há muitas falhas, por favor me perdoe. O tempo é relativamente curto, e o código será aprimorado depois de um tempo, e todo o código e dados serão anexados ao segundo artigo.

Acho que você gosta

Origin blog.csdn.net/qq_36865346/article/details/120053869
Recomendado
Clasificación