Bootstrap

故障诊断之FFT

FFT

顺手记录一下工作。

快速傅里叶变换 (Fast Fourier Transform)

preprocess

from scipy.io import loadmat
import numpy as np
import os
from sklearn import preprocessing  # 0-1编码
from sklearn.model_selection import StratifiedShuffleSplit  # 随机划分,保证每一类比例相同

def prepro(d_path, length=0, number=0, normal=True, rate=[0, 0, 0], enc=False, enc_step=28):

    # 获得该文件夹下所有.mat文件名
    filenames = os.listdir(d_path)

    def capture(original_path):
        files = {}
        for i in filenames:
            # 文件路径
            file_path = os.path.join(d_path, i)
            file = loadmat(file_path)
            file_keys = file.keys()
            for key in file_keys:
                if 'DE' in key:
                    files[i] = file[key].ravel()
        return files

    def slice_enc(data, slice_rate=rate[1] + rate[2]):
        keys = data.keys()
        Train_Samples = {}
        Test_Samples = {}
        for i in keys:
            slice_data = data[i]

            all_lenght = len(slice_data)
            # end_index = int(all_lenght * (1 - slice_rate))
            samp_train = int(number * (1 - slice_rate))  # 1000(1-0.3)
            Train_sample = []
            Test_Sample = []

            for j in range(samp_train):
                sample = slice_data[j*150: j*150 + length]
                Train_sample.append(sample)

            # 抓取测试数据
            for h in range(number - samp_train):
                sample = slice_data[samp_train*150 + length + h*150: samp_train*150 + length + h*150 + length]
                Test_Sample.append(sample)
            Train_Samples[i] = Train_sample
            Test_Samples[i] = Test_Sample
        return Train_Samples, Test_Samples

    # 仅抽样完成,打标签
    def add_labels(train_test):
        X = []
        Y = []
        label = 0
        for i in filenames:
            x = train_test[i]
            X += x
            lenx = len(x)
            Y += [label] * lenx
            label += 1
        return X, Y

    def scalar_stand(Train_X, Test_X):
        # 用训练集标准差标准化训练集以及测试集
        data_all = np.vstack((Train_X, Test_X))
        scalar = preprocessing.StandardScaler().fit(data_all)
        Train_X = scalar.transform(Train_X)
        Test_X = scalar.transform(Test_X)
        return Train_X, Test_X

    def valid_test_slice(Test_X, Test_Y):

        test_size = rate[2] / (rate[1] + rate[2])
        ss = StratifiedShuffleSplit(n_splits=1, test_size=test_size)
        Test_Y = np.asarray(Test_Y, dtype=np.int32)

        for train_index, test_index in ss.split(Test_X, Test_Y):
            X_valid, X_test = Test_X[train_index], Test_X[test_index]
            Y_valid, Y_test = Test_Y[train_index], Test_Y[test_index]

            return X_valid, Y_valid, X_test, Y_test

    # 从所有.mat文件中读取出数据的字典
    data = capture(original_path=d_path)
    # 将数据切分为训练集、测试集
    train, test = slice_enc(data)
    # 为训练集制作标签,返回X,Y
    Train_X, Train_Y = add_labels(train)
    # 为测试集制作标签,返回X,Y
    Test_X, Test_Y = add_labels(test)

    # 训练数据/测试数据 是否标准化.
    if normal:
        Train_X, Test_X = scalar_stand(Train_X, Test_X)
    Train_X = np.asarray(Train_X)
    Test_X = np.asarray(Test_X)
    # 将测试集切分为验证集和测试集.
    Valid_X, Valid_Y, Test_X, Test_Y = valid_test_slice(Test_X, Test_Y)
    return Train_X, Train_Y, Valid_X, Valid_Y, Test_X, Test_Y

一维数据快速傅里叶变换(1d-FFT)

缺少哪个包就直接去pip

from tensorflow import keras
from sklearn.metrics import confusion_matrix
import tensorflow.keras as keras
import tensorflow.keras.layers as layers
from datetime import datetime
from tensorflow_core.python.keras import layers
import tensorflow as tf


import random
import matplotlib.pyplot as plt
from scipy.fftpack import fft
import numpy as np
from preprocess import prepro

def fft_data():
    length = 784
    number = 300  # 每类样本的数量
    normal = True  # 是否标准化
    rate = [0.6, 0.2, 0.2]  # 测试集验证集划分比例

    path = r'C:/Users/LIU/Desktop/xianligong/CaseWesternReserveUniversityData-master/1HP'
    x_train, y_train, x_valid, y_valid, x_test, y_test = prepro(
                                                                      d_path=path,
                                                                      length=length,
                                                                      number=number,
                                                                      normal=normal,
                                                                      rate=rate,
                                                                      enc=False, enc_step=28)
    y_valid, y_test = y_valid[:, np.newaxis], y_test[:, np.newaxis]

    x_test = np.vstack((x_valid, x_test))
    y_test = np.vstack((y_valid, y_test))

    x_train = np.array(x_train)
    y_train = np.array(y_train)
    x_test = np.array(x_test)
    y_test = np.array(y_test)
    y_test = np.squeeze(y_test)
    return x_train, y_train, x_valid, y_valid, x_test, y_test


def fft_transform():
    x_train0, y_train0, x_valid0, y_valid0, x_test0, y_test0 = fft_data()

    x_train1 = []
    x_valid1 = []
    x_test1 = []
    N = 784
    for i in range(len(x_train0)):
        y1 = x_train0[i]
        yf1 = abs(fft(y1)) / N # 归一化处理
        yf2 = yf1[range(int(len(yf1) / 2))]  # 由于对称性,只取一半区间
        #yf2 = yf1[range(N)]
        x_train1.append(yf2)

    for i in range(len(x_valid0)):
        y2 = x_valid0[i]
        yf3 = abs(fft(y2)) / N  # 归一化处理
        yf4 = yf3[range(int(len(yf1) / 2))]  # 由于对称性,只取一半区间
        #yf4 = yf3[range(N)]
        x_valid1.append(yf4)

    for i in range(len(x_test0)):
        y2 = x_test0[i]
        yf3 = abs(fft(y2)) / N  # 归一化处理
        yf4 = yf3[range(int(len(yf1) / 2))]  # 由于对称性,只取一半区间
        #yf4 = yf3[range(N)]
        x_test1.append(yf4)

    x_train3 = np.array(x_train1)
    x_valid3 = np.array(x_valid1)
    x_test3 = np.array(x_test1)
    return x_train3, y_train0, x_valid3, y_valid0, x_test3, y_test0

x_train, y_train, x_valid, y_valid, x_test, y_test = fft_transform()

#绘制FFT结果
plt.plot(x_train[0])
plt.title('FFT of Mixed wave)', fontsize=10, color='#F08080')
plt.show()

print(x_train.shape)
print(x_valid.shape)
print(x_test.shape)
print(y_train.shape)
print(y_valid.shape)
print(y_test.shape)


y_train = [int(i) for i in y_train]
y_valid = [int(i) for i in y_valid]
y_test = [int(i) for i in y_test]

# 打乱顺序
index = [i for i in range(len(x_train))]
random.seed(1)
random.shuffle(index)
x_train = np.array(x_train)[index]
y_train = np.array(y_train)[index]

index1 = [i for i in range(len(x_valid))]
random.shuffle(index1)
x_valid = np.array(x_valid)[index1]
y_valid = np.array(y_valid)[index1]

index2 = [i for i in range(len(x_test))]
random.shuffle(index2)
x_test = np.array(x_test)[index2]
y_test = np.array(y_test)[index2]

print(x_train.shape)
print(x_valid.shape)
print(x_test.shape)
print(y_train)
print(y_valid)
print(y_test)
print("x_train的最大值和最小值:", x_train.max(), x_train.min())
print("x_test的最大值和最小值:", x_test.max(), x_test.min())

x_train = tf.reshape(x_train, (len(x_train), 392, 1))
x_valid = tf.reshape(x_valid, (len(x_valid), 392, 1))
x_test = tf.reshape(x_test, (len(x_test), 392, 1))


# 保存最佳模型
class CustomModelCheckpoint(keras.callbacks.Callback):
    def __init__(self, model, path):
        self.model = model
        self.path = path
        self.best_loss = np.inf

    def on_epoch_end(self, epoch, logs=None):
        val_loss = logs['val_loss']
        if val_loss < self.best_loss:
            print("\nValidation loss decreased from {} to {}, saving model".format(self.best_loss, val_loss))
            self.model.save_weights(self.path, overwrite=True)
            self.best_loss = val_loss

# 模型定义
def mymodel():
    inputs = keras.Input(shape=(x_train.shape[1], x_train.shape[2]))
    h1 = layers.Conv1D(filters=8, kernel_size=3, strides=1, padding='same', activation='relu')(inputs)
    h1 = layers.MaxPool1D(pool_size=2, strides=2, padding='same')(h1)

    h1 = layers.Conv1D(filters=16, kernel_size=3, strides=1, padding='same', activation='relu')(h1)
    h1 = layers.MaxPool1D(pool_size=2, strides=2, padding='same')(h1)

    h1 = layers.Flatten()(h1)
    h1 = layers.Dropout(0.6)(h1)
    h1 = layers.Dense(32, activation='relu')(h1)
    h1 = layers.Dense(10, activation='softmax')(h1)

    deep_model = keras.Model(inputs, h1, name="cnn")
    return deep_model

model = mymodel()

model.summary()
startdate = datetime.utcnow()  # 获取当前时间

# 编译模型
model.compile(
    optimizer=keras.optimizers.Adam(),
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy'])

history = model.fit(x_train, y_train,
                    batch_size=256, epochs=50, verbose=1,
                    validation_data=(x_valid, y_valid),
                    callbacks=[CustomModelCheckpoint(
  model, r'best_fft_1dcnn.h5')])

#加载模型
model.load_weights(filepath='best_fft_1dcnn.h5')
# 编译模型
model.compile(loss='sparse_categorical_crossentropy', optimizer=keras.optimizers.Adam(), metrics=['accuracy'])
# 评估模型
scores = model.evaluate(x_test, y_test, verbose=1)
print('%s: %.2f%%' % (model.metrics_names[1], scores[1] * 100))

y_predict = model.predict(x_test)
y_pred_int = np.argmax(y_predict, axis=1)
print(y_pred_int[0:5])
from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred_int, digits=4))

def acc_line():
    # 绘制acc和loss曲线
    acc = history.history['accuracy']
    val_acc = history.history['val_accuracy']
    loss = history.history['loss']
    val_loss = history.history['val_loss']

    epochs = range(len(acc))  # Get number of epochs

    # 画accuracy曲线
    plt.plot(epochs, acc, 'r', linestyle='-.')
    plt.plot(epochs, val_acc, 'b', linestyle='dashdot')
    plt.title('Training and validation accuracy')
    plt.xlabel("Epochs")
    plt.ylabel("Accuracy")
    plt.legend(["Accuracy", "Validation Accuracy"])

    plt.figure()

    # 画loss曲线
    plt.plot(epochs, loss, 'r', linestyle='-.')
    plt.plot(epochs, val_loss, 'b', linestyle='dashdot')
    plt.title('Training and validation loss')
    plt.xlabel("Epochs")
    plt.ylabel("Loss")
    plt.legend(["Loss", "Validation Loss"])
    # plt.figure()
    plt.show()


acc_line()


# 绘制混淆矩阵
def confusion():
    y_pred_gailv = model.predict(x_test, verbose=1)
    y_pred_int = np.argmax(y_pred_gailv, axis=1)
    print(len(y_pred_int))
    con_mat = confusion_matrix(y_test.astype(str), y_pred_int.astype(str))
    print(con_mat)
    classes = list(set(y_train))
    classes.sort()
    plt.imshow(con_mat, cmap=plt.cm.Blues)
    indices = range(len(con_mat))
    plt.xticks(indices, classes)
    plt.yticks(indices, classes)
    plt.colorbar()
    plt.xlabel('guess')
    plt.ylabel('true')
    for first_index in range(len(con_mat)):
        for second_index in range(len(con_mat[first_index])):
            plt.text(first_index, second_index, con_mat[second_index][first_index], va='center', ha='center')
    plt.show()
confusion()

二维时频图快速傅里叶变换(2d-FFT)

前面都大差不差,如果在可视化部分需要增加或修改X,Y轴,两种方法:1.通过代码直接修改,比如字体大小或者XY轴名称(过完周末再写);2.通过PowerPoint或WPS直接去添加文本框,然后合并图层。


from tensorflow import keras
from sklearn.metrics import confusion_matrix
import tensorflow.keras as keras
import tensorflow.keras.layers as layers
from datetime import datetime
from tensorflow_core.python.keras import layers
import tensorflow as tf

import matplotlib.pyplot as plt
from scipy.fftpack import fft
import numpy as np
from fft.preprocess import prepro

def fft_data():
    length = 784
    number = 300  # 每类样本的数量
    normal = True  # 是否标准化
    rate = [0.6, 0.2, 0.2]  # 测试集验证集划分比例

    path = r'C:/Users/LIU/Desktop/xianligong/CaseWesternReserveUniversityData-master/1HP'
    x_train, y_train, x_valid, y_valid, x_test, y_test = prepro(
                                                                      d_path=path,
                                                                      length=length,
                                                                      number=number,
                                                                      normal=normal,
                                                                      rate=rate,
                                                                      enc=False, enc_step=28)
    y_valid, y_test = y_valid[:, np.newaxis], y_test[:, np.newaxis]

    x_test = np.vstack((x_valid, x_test))
    y_test = np.vstack((y_valid, y_test))

    x_train = np.array(x_train)
    y_train = np.array(y_train)
    x_test = np.array(x_test)
    y_test = np.array(y_test)
    y_test = np.squeeze(y_test)
    return x_train, y_train, x_valid, y_valid, x_test, y_test


def fft_transform():
    x_train0, y_train0, x_valid0, y_valid0, x_test0, y_test0 = fft_data()

    x_train1 = []
    x_valid1 = []
    x_test1 = []
    N = 784
    for i in range(len(x_train0)):
        y1 = x_train0[i]
        yf1 = abs(fft(y1)) / N # 归一化处理
        # yf2 = yf1[range(int(len(yf1) / 2))]  # 由于对称性,只取一半区间
        yf2 = yf1[range(N)]
        x_train1.append(yf2)

    for i in range(len(x_valid0)):
        y2 = x_valid0[i]
        yf3 = abs(fft(y2)) / N  # 归一化处理
        # yf4 = yf3[range(int(len(yf1) / 2))]  # 由于对称性,只取一半区间
        yf4 = yf3[range(N)]
        x_valid1.append(yf4)

    for i in range(len(x_test0)):
        y2 = x_test0[i]
        yf3 = abs(fft(y2)) / N  # 归一化处理
        # yf4 = yf3[range(int(len(yf1) / 2))]  # 由于对称性,只取一半区间
        yf4 = yf3[range(N)]
        x_test1.append(yf4)

    x_train3 = np.array(x_train1)
    x_valid3 = np.array(x_valid1)
    x_test3 = np.array(x_test1)
    return x_train3, y_train0, x_valid3, y_valid0, x_test3, y_test0

x_train, y_train, x_valid, y_valid, x_test, y_test = fft_transform()

# 绘制FFT结果
plt.plot(x_train[0])
plt.title('FFT of Mixed wave)', fontsize=10, color='#F08080')
plt.show()

print(x_train.shape)
print(x_valid.shape)
print(x_test.shape)
print(y_train.shape)
print(y_valid.shape)
print(y_test.shape)


y_train = [int(i) for i in y_train]
y_valid = [int(i) for i in y_valid]
y_test = [int(i) for i in y_test]

# 打乱顺序
index = [i for i in range(len(x_train))]
random.seed(1)
random.shuffle(index)
x_train = np.array(x_train)[index]
y_train = np.array(y_train)[index]

index1 = [i for i in range(len(x_valid))]
random.shuffle(index1)
x_valid = np.array(x_valid)[index1]
y_valid = np.array(y_valid)[index1]

index2 = [i for i in range(len(x_test))]
random.shuffle(index2)
x_test = np.array(x_test)[index2]
y_test = np.array(y_test)[index2]

print(x_train.shape)
print(x_valid.shape)
print(x_test.shape)
print(y_train)
print(y_valid)
print(y_test)
print("x_train的最大值和最小值:", x_train.max(), x_train.min())
print("x_test的最大值和最小值:", x_test.max(), x_test.min())

x_train = tf.reshape(x_train, (len(x_train), 28, 28, 1))
x_valid = tf.reshape(x_valid, (len(x_valid), 28, 28, 1))
x_test = tf.reshape(x_test, (len(x_test), 28, 28, 1))


# 保存最佳模型
class CustomModelCheckpoint(keras.callbacks.Callback):
    def __init__(self, model, path):
        self.model = model
        self.path = path
        self.best_loss = np.inf

    def on_epoch_end(self, epoch, logs=None):
        val_loss = logs['val_loss']
        if val_loss < self.best_loss:
            print("\nValidation loss decreased from {} to {}, saving model".format(self.best_loss, val_loss))
            self.model.save_weights(self.path, overwrite=True)
            self.best_loss = val_loss
def mymodel():
    inputs = keras.Input(shape=(x_train.shape[1], x_train.shape[2], x_train.shape[3]))
    h1 = layers.Conv2D(filters=8, kernel_size=(3, 3), strides=(1,1), padding='same', activation='relu')(inputs)
    h1 = layers.MaxPool2D(pool_size=(2,2), strides=(2, 2), padding='same')(h1)
    h1 = layers.Conv2D(filters=16, kernel_size=(3,3), strides=(1,1), padding='same', activation='relu')(h1)
    h1 = layers.MaxPool2D(pool_size=(2,2), strides=(2,2), padding='same')(h1)

    h1 = layers.Flatten()(h1)
    h1 = layers.Dense(32, activation='relu')(h1)
    h1 = layers.Dense(10, activation='softmax')(h1)

    deep_model = keras.Model(inputs, h1, name="cnn")
    return deep_model

model = mymodel()
model.summary()
startdate = datetime.utcnow()  # 获取当前时间

# 编译模型
model.compile(
    optimizer=keras.optimizers.Adam(),
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy'])

history = model.fit(x_train, y_train,
                    batch_size=256, epochs=50, verbose=1,
                    validation_data=(x_valid, y_valid),
                    callbacks=[CustomModelCheckpoint(
  model, r'best_fft_2dcnn.h5')])

#加载模型
model.load_weights(filepath='best_fft_2dcnn.h5')
# 编译模型
model.compile(loss='sparse_categorical_crossentropy', optimizer=keras.optimizers.Adam(), metrics=['accuracy'])
# 评估模型
scores = model.evaluate(x_test, y_test, verbose=1)
print('%s: %.2f%%' % (model.metrics_names[1], scores[1] * 100))

y_predict = model.predict(x_test)
y_pred_int = np.argmax(y_predict, axis=1)
# print(y_pred_int[0:5])
from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred_int, digits=4))

def acc_line():
    # 绘制acc和loss曲线
    acc = history.history['accuracy']
    val_acc = history.history['val_accuracy']
    loss = history.history['loss']
    val_loss = history.history['val_loss']

    epochs = range(len(acc))  # Get number of epochs

    # 画accuracy曲线
    plt.plot(epochs, acc, 'r', linestyle='-.')
    plt.plot(epochs, val_acc, 'b', linestyle='dashdot')
    plt.title('Training and validation accuracy')
    plt.xlabel("Epochs")
    plt.ylabel("Accuracy")
    plt.legend(["Accuracy", "Validation Accuracy"])

    plt.figure()

    # 画loss曲线
    plt.plot(epochs, loss, 'r', linestyle='-.')
    plt.plot(epochs, val_loss, 'b', linestyle='dashdot')
    plt.title('Training and validation loss')
    plt.xlabel("Epochs")
    plt.ylabel("Loss")
    plt.legend(["Loss", "Validation Loss"])
    plt.show()
acc_line()


# 绘制混淆矩阵
def confusion():
    y_pred_gailv = model.predict(x_test, verbose=1)
    y_pred_int = np.argmax(y_pred_gailv, axis=1)
    print(len(y_pred_int))
    con_mat = confusion_matrix(y_test.astype(str), y_pred_int.astype(str))
    print(con_mat)
    classes = list(set(y_train))
    classes.sort()
    plt.imshow(con_mat, cmap=plt.cm.Blues)
    indices = range(len(con_mat))
    plt.xticks(indices, classes)
    plt.yticks(indices, classes)
    plt.colorbar()
    plt.xlabel('guess')
    plt.ylabel('true')
    for first_index in range(len(con_mat)):
        for second_index in range(len(con_mat[first_index])):
            plt.text(first_index, second_index, con_mat[second_index][first_index], va='center', ha='center')
    plt.show()
confusion()

写在最后

中间定义的那个模型

def mymodel

用了很简单的一个模型,如果需要特定的模型需求,只需要在最前面from引一下。

然后在model=这个地方也修改一下。

有不会的可以私信问我,看到会回,一起进步,一起学习。

;