diff --git a/TensorFlow_eaxmple/Model_train_test/RUL/test/LSTMContinueTest.py b/TensorFlow_eaxmple/Model_train_test/RUL/test/LSTMContinueTest.py index d1e1b2f..d125ef8 100644 --- a/TensorFlow_eaxmple/Model_train_test/RUL/test/LSTMContinueTest.py +++ b/TensorFlow_eaxmple/Model_train_test/RUL/test/LSTMContinueTest.py @@ -14,6 +14,8 @@ import matplotlib.pyplot as plt from keras.callbacks import EarlyStopping from model.LossFunction.FTMSE import FTMSE +from model.ChannelAttention.DCT_channelAttention import DCTChannelAttention +from model.ChannelAttention.Light_channelAttention import LightChannelAttention1 as LightChannelAttention import math from sklearn.metrics import mean_absolute_error, mean_squared_error from pylab import * @@ -27,10 +29,10 @@ batch_size = 32 EPOCH = 1000 unit = 512 # LSTM的维度 predict_num = 50 # 预测个数 -model_name = "FTLSTM" +model_name = "FC_FTLSTM" save_name = r"selfMulti_{0}_hidden{1}_unit{2}_feature{3}_predict{4}.h5".format(model_name, hidden_num, unit, - feature, - predict_num) + feature, + predict_num) def standardization(data): @@ -134,6 +136,8 @@ def splitValData(data, label, label_single, predict_num=50): def predict_model_multi(filter_num, dims): + tf.config.experimental_run_functions_eagerly(True) + input = tf.keras.Input(shape=[filter_num, dims]) input = tf.cast(input, tf.float32) @@ -143,9 +147,11 @@ def predict_model_multi(filter_num, dims): #### 自己 LSTM = LSTMLayer(units=512, return_sequences=True)(input) + # LSTM = LightChannelAttention()(LSTM) LSTM = LSTMLayer(units=256, return_sequences=True)(LSTM) + LSTM = LightChannelAttention()(LSTM) - ###flatten + ### flatten x = tf.keras.layers.Flatten()(LSTM) x = tf.keras.layers.Dense(128, activation="relu")(x) x = tf.keras.layers.Dense(64, activation="relu")(x) @@ -161,30 +167,7 @@ def predict_model_multi(filter_num, dims): return model -def split_data(train_data, train_label): - return train_data[:1150, :, :], train_label[:1150, :], train_data[-70:, :, :], train_label[-70:, :] - - # 仅使用预测出来的最新的一个点预测以后 -def predictOneByOne(newModel, train_data, predict_num=50): - # 取出训练数据的最后一条 - each_predict_data = np.expand_dims(train_data[-1, :, :], axis=0) - predicted_list = np.empty(shape=(predict_num, 1)) # (5,filter_num,30) - # all_data = total_data # (1201,) - for each_predict in range(predict_num): - # predicted_data.shape : (1,1) - predicted_data = newModel.predict(each_predict_data) # (batch_size,filer_num,1) - predicted_list[each_predict] = predicted_data - # (1,1) => (10,1) - temp1 = np.transpose(np.concatenate([each_predict_data[:, 1:, -1], predicted_data], axis=1), [1, 0]) - - each_predict_data = np.expand_dims( - np.concatenate([np.squeeze(each_predict_data[:, :, 1:], axis=0), temp1], axis=1), axis=0) - - return predicted_list - - -# 使用最后预测出来的一整行与之前的拼接 def predictContinueByOne(newModel, train_data, predict_num=50): # 取出训练数据的最后一条 each_predict_data = np.expand_dims(train_data[-1, :, :], axis=0) @@ -221,13 +204,13 @@ def predictByEveryData(trained_model: tf.keras.Model, predict_data): if __name__ == '__main__': # 数据读取 # 数据读入 --> 所有的原始数据;所有的训练数据;所有的训练标签(预测一个序列);所有的训练标签(预测一个点) - total_data, train_data, train_label, train_label_single = getData(hidden_num, feature, if_norm=False) + total_data, train_data, train_label, train_label_single = getData(hidden_num, feature) # 根据预测的点数划分训练集和测试集(验证集) train_data, val_data, train_label, val_label, train_label_single, val_label_single = splitValData(train_data, train_label, train_label_single, predict_num=predict_num) - # # #### TODO 训练 + # #### TODO 训练 model = predict_model_multi(hidden_num, feature) checkpoint = tf.keras.callbacks.ModelCheckpoint( filepath=save_name, @@ -237,7 +220,8 @@ if __name__ == '__main__': mode='min') lr_scheduler = tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=20, min_lr=0.001) - model.compile(optimizer=tf.optimizers.SGD(), loss=FTMSE()) + model.compile(optimizer=tf.optimizers.SGD(), loss=tf.losses.mse) + # model.compile(optimizer=tf.optimizers.SGD(learning_rate=0.001), loss=FTMSE()) model.summary() early_stop = EarlyStopping(monitor='val_loss', min_delta=0.0001, patience=100, mode='min', verbose=1) @@ -247,7 +231,11 @@ if __name__ == '__main__': #### TODO 测试 - trained_model = tf.keras.models.load_model(save_name, custom_objects={'LSTMLayer': LSTMLayer}) + # trained_model = tf.keras.models.load_model(save_name, custom_objects={'LSTMLayer': LSTMLayer, 'FTMSE': FTMSE}) + + # todo 解决自定义loss无法导入的问题 + trained_model = tf.keras.models.load_model(save_name, compile=False, custom_objects={'LSTMLayer': LSTMLayer,'DCTChannelAttention':DCTChannelAttention}) + trained_model.compile(optimizer=tf.optimizers.SGD(), loss=FTMSE()) # 使用已知的点进行预测 predicted_data = predictByEveryData(trained_model, train_data) diff --git a/TensorFlow_eaxmple/Model_train_test/RUL/test/LSTMTest.py b/TensorFlow_eaxmple/Model_train_test/RUL/test/LSTMTest.py index 2e5f861..a315dda 100644 --- a/TensorFlow_eaxmple/Model_train_test/RUL/test/LSTMTest.py +++ b/TensorFlow_eaxmple/Model_train_test/RUL/test/LSTMTest.py @@ -205,7 +205,7 @@ if __name__ == '__main__': #### TODO 测试 - trained_model = tf.keras.models.load_model(save_name, custom_objects={'LSTMLayer': LSTMLayer, 'FTMSE': FTMSE}) + trained_model = tf.keras.models.load_model(save_name, custom_objects={'LSTMLayer': LSTMLayer}) # 使用已知的点进行预测 predicted_data = predictByEveryData(trained_model, train_data) diff --git a/TensorFlow_eaxmple/Model_train_test/model/ChannelAttention/DCT_channelAttention.py b/TensorFlow_eaxmple/Model_train_test/model/ChannelAttention/DCT_channelAttention.py index 3c6b693..8752bc6 100644 --- a/TensorFlow_eaxmple/Model_train_test/model/ChannelAttention/DCT_channelAttention.py +++ b/TensorFlow_eaxmple/Model_train_test/model/ChannelAttention/DCT_channelAttention.py @@ -13,62 +13,139 @@ import tensorflow.keras.layers as layers import numpy as np import pandas as pd import matplotlib.pyplot as plt -from model.DepthwiseCon1D.DepthwiseConv1D import DepthwiseConv1D +from tensorflow.keras.layers import Dense, Dropout, ReLU, BatchNormalization +from scipy.fftpack import dct +# def dct(x, norm=None): +# """ +# Discrete Cosine Transform, Type II (a.k.a. the DCT) +# +# For the meaning of the parameter `norm`, see: +# https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.fftpack.dct.html +# +# :param x: the input signal +# :param norm: the normalization, None or 'ortho' +# :return: the DCT-II of the signal over the last dimension +# """ +# x_shape = x.shape +# N = x_shape[-1] +# x = x.contiguous().view(-1, N) +# +# +# v = tf.concat([x[:, ::2], x[:, 1::2].flip([1])], axis=1) +# +# # Vc = torch.fft.rfft(v, 1, onesided=False) +# Vc = tf.signal.fft(v, 1) +# +# +# k = - tf.range(N, dtype=x.dtype, device=x.device)[None, :] * np.pi / (2 * N) +# +# W_r = tf.cos(k) +# W_i = tf.sin(k) +# +# V = Vc[:, :, 0] * W_r - Vc[:, :, 1] * W_i +# +# if norm == 'ortho': +# V[:, 0] /= np.sqrt(N) * 2 +# V[:, 1:] /= np.sqrt(N / 2) * 2 +# +# V = 2 * V.view(*x_shape) +# +# return V + + + +import tensorflow as tf + + +def sdct_tf(signals, frame_length, frame_step, window_fn=tf.signal.hamming_window): + """Compute Short-Time Discrete Cosine Transform of `signals`. + + No padding is applied to the signals. + + Parameters + ---------- + signal : Time-domain input signal(s), a `[..., n_samples]` tensor. + + frame_length : Window length and DCT frame length in samples. + + frame_step : Number of samples between adjacent DCT columns. + + window_fn : See documentation for `tf.signal.stft`. + Default: hamming window. Window to use for DCT. + + Returns + ------- + dct : Real-valued T-F domain DCT matrix/matrixes, a `[..., n_frames, frame_length]` tensor. + """ + framed = tf.signal.frame(signals, frame_length, frame_step, pad_end=False) + if window_fn is not None: + window = window_fn(frame_length, dtype=framed.dtype) + framed = framed * window[tf.newaxis, :] + return tf.signal.dct(framed, norm="ortho", axis=-1) + + +def isdct_tf(dcts, *, frame_step, frame_length=None, window_fn=tf.signal.hamming_window): + """Compute Inverse Short-Time Discrete Cosine Transform of `dct`. + + Parameters other than `dcts` are keyword-only. + + Parameters + ---------- + dcts : DCT matrix/matrices from `sdct_tf` + + frame_step : Number of samples between adjacent DCT columns (should be the + same value that was passed to `sdct_tf`). + + frame_length : Ignored. Window length and DCT frame length in samples. + Can be None (default) or same value as passed to `sdct_tf`. + + window_fn : See documentation for `tf.signal.istft`. + Default: hamming window. Window to use for DCT. + + Returns + ------- + signals : Time-domain signal(s) reconstructed from `dcts`, a `[..., n_samples]` tensor. + Note that `n_samples` may be different from the original signals' lengths as passed to `sdct_torch`, + because no padding is applied. + """ + *_, n_frames, frame_length2 = dcts.shape + assert frame_length in {None, frame_length2} + signals = tf.signal.overlap_and_add( + tf.signal.idct(dcts, norm="ortho", axis=-1), frame_step + ) + if window_fn is not None: + window = window_fn(frame_length2, dtype=signals.dtype) + window_frames = tf.tile(window[tf.newaxis, :], (n_frames, 1)) + window_signal = tf.signal.overlap_and_add(window_frames, frame_step) + signals = signals / window_signal + return signals + class DCTChannelAttention(layers.Layer): - def __init__(self): - # 调用父类__init__()方法 - super(DCTChannelAttention, self).__init__() - self.DWC = DepthwiseConv1D(kernel_size=1, padding='SAME') def build(self, input_shape): - if len(input_shape) != 3: - raise ValueError('Inputs to `DynamicChannelAttention` should have rank 3. ' - 'Received input shape:', str(input_shape)) - - # print(input_shape) - # GAP - self.GAP = tf.keras.layers.GlobalAvgPool1D() - self.c1 = tf.keras.layers.Conv1D(filters=input_shape[2], kernel_size=1, padding='SAME') - # s1 = tf.nn.sigmoid(c1) - - # GMP - self.GMP = tf.keras.layers.GlobalMaxPool1D() - self.c2 = tf.keras.layers.Conv1D(filters=input_shape[2], kernel_size=1, padding='SAME') - # s2 = tf.nn.sigmoid(c2) - - # weight - self.weight_kernel = self.add_weight( - shape=(1, input_shape[2]), - initializer='glorot_uniform', - name='weight_kernel') + _, hidden, channel = input_shape + self.l1 = Dense(channel * 2, use_bias=False) + self.drop1 = Dropout(0.1) + self.relu = ReLU(0.1) + self.l2 = Dense(channel, use_bias=False) def call(self, inputs, **kwargs): - batch_size, length, channel = inputs.shape - # print(batch_size,length,channel) - DWC1 = self.DWC(inputs) + batch_size, hidden, channel = inputs.shape + list = [] + stack_dct = tf.signal.dct(inputs, norm="ortho",axis=-1) + # for i in range(channel): + # freq = tf.signal.dct(inputs[:, i, :], norm="ortho", axis=-1) + # # print("freq-shape:",freq.shape) + # list.append(freq) + # stack_dct = tf.stack(list, dim=1) - # GAP - GAP = self.GAP(DWC1) - GAP = tf.expand_dims(GAP, axis=1) - c1 = self.c1(GAP) - c1 = tf.keras.layers.BatchNormalization()(c1) - s1 = tf.nn.sigmoid(c1) + lr_weight = self.l1(stack_dct) + lr_weight = self.drop1(lr_weight) + lr_weight = self.relu(lr_weight) + lr_weight = self.l2(lr_weight) - # GMP - GMP = self.GMP(DWC1) - GMP = tf.expand_dims(GMP, axis=1) - c2 = self.c2(GMP) - c2 = tf.keras.layers.BatchNormalization()(c2) - s2 = tf.nn.sigmoid(c2) + lr_weight = BatchNormalization()(lr_weight) - # print(self.weight_kernel) - - weight_kernel = tf.broadcast_to(self.weight_kernel, shape=[length, channel]) - weight_kernel = tf.broadcast_to(weight_kernel, shape=[batch_size, length, channel]) - s1 = tf.broadcast_to(s1, shape=[batch_size, length, channel]) - s2 = tf.broadcast_to(s2, shape=[batch_size, length, channel]) - - output = tf.add(weight_kernel * s1 * inputs, (tf.ones_like(weight_kernel) - weight_kernel) * s2 * inputs) - return output + return inputs * lr_weight diff --git a/TensorFlow_eaxmple/Model_train_test/model/ChannelAttention/Light_channelAttention.py b/TensorFlow_eaxmple/Model_train_test/model/ChannelAttention/Light_channelAttention.py index 233ae1e..2951db5 100644 --- a/TensorFlow_eaxmple/Model_train_test/model/ChannelAttention/Light_channelAttention.py +++ b/TensorFlow_eaxmple/Model_train_test/model/ChannelAttention/Light_channelAttention.py @@ -64,15 +64,6 @@ class LightChannelAttention(layers.Layer): c1 = tf.keras.layers.BatchNormalization()(c1) s1 = tf.nn.sigmoid(c1) - # # GMP - # GMP = self.GMP(DWC1) - # GMP = tf.expand_dims(GMP, axis=1) - # c2 = self.c2(GMP) - # c2 = tf.keras.layers.BatchNormalization()(c2) - # s2 = tf.nn.sigmoid(c2) - - # print(self.weight_kernel) - # weight_kernel = tf.broadcast_to(self.weight_kernel, shape=[length, channel]) # weight_kernel = tf.broadcast_to(weight_kernel, shape=[batch_size, length, channel]) s1 = tf.broadcast_to(s1, shape=[batch_size, length, channel]) @@ -82,6 +73,42 @@ class LightChannelAttention(layers.Layer): return s1 +class LightChannelAttention1(layers.Layer): + + def __init__(self): + # 调用父类__init__()方法 + super(LightChannelAttention1, self).__init__() + self.DWC = DepthwiseConv1D(kernel_size=1, padding='SAME') + # self.DWC = DepthwiseConv1D(kernel_size=1, padding='causal',dilation_rate=4,data_format='channels_last') + + def build(self, input_shape): + if len(input_shape) != 3: + raise ValueError('Inputs to `DynamicChannelAttention` should have rank 3. ' + 'Received input shape:', str(input_shape)) + + print(input_shape) + # GAP + self.GAP = tf.keras.layers.GlobalAvgPool1D() + self.c1 = tf.keras.layers.Conv1D(filters=input_shape[2], kernel_size=1, padding='SAME') + + + def call(self, inputs, **kwargs): + batch_size, length, channel = inputs.shape + DWC1 = self.DWC(inputs) + + # GAP + GAP = self.GAP(DWC1) + GAP = tf.expand_dims(GAP, axis=1) + c1 = self.c1(GAP) + c1 = tf.keras.layers.BatchNormalization()(c1) + s1 = tf.nn.sigmoid(c1) + print(s1) + + s1 = tf.broadcast_to(s1, [batch_size, length, channel]) + + + return s1 * inputs + class DynamicPooling(layers.Layer): def __init__(self, pool_size=2): diff --git a/TensorFlow_eaxmple/Model_train_test/model/LossFunction/FTMSE.py b/TensorFlow_eaxmple/Model_train_test/model/LossFunction/FTMSE.py index f0dd64a..4e61cfb 100644 --- a/TensorFlow_eaxmple/Model_train_test/model/LossFunction/FTMSE.py +++ b/TensorFlow_eaxmple/Model_train_test/model/LossFunction/FTMSE.py @@ -12,35 +12,42 @@ import tensorflow.keras.backend as K class FTMSE(tf.keras.losses.Loss): + def call(self, y_true, y_pred): - y_true = tf.cast(y_true, tf.float32) - y_pred = tf.cast(y_pred, tf.float32) + # y_true = tf.cast(y_true, tf.float32) + # y_pred = tf.cast(y_pred, tf.float32) + + # tf.print(y_true) + # tf.print(y_pred) # 需要转为复数形式 - yt_fft = tf.signal.fft(tf.cast(y_true, tf.complex64)) - yp_fft = tf.signal.fft(tf.cast(y_pred, tf.complex64)) + _, length = y_pred.shape - print("yt_amp",yt_fft) - print("yp_fft",yp_fft) + # 打印精确的实部和虚部 + yt_fft = tf.signal.fft(tf.complex(y_true, tf.zeros_like(y_true))) + yp_fft = tf.signal.fft(tf.complex(y_pred, tf.zeros_like(y_pred))) - epoch, length = yp_fft.shape # 幅值 - yt_amp = tf.abs(yt_fft / length) - yp_amp = tf.abs(yp_fft / length) + yt_amp = tf.abs(yt_fft/length) + yp_amp = tf.abs(yp_fft/length) + # yt_amp = tf.abs(yt_fft) + # yp_amp = tf.abs(yp_fft) # 相角 yt_angle = tf.math.angle(yt_fft) yp_angle = tf.math.angle(yp_fft) + # tf.print("yt_amp",yt_amp) + # tf.print("yp_amp",yp_amp) + # tf.print("yt_angle",yt_angle) + # tf.print("yp_angle",yp_angle) + time_loss = K.mean(tf.keras.losses.mean_squared_error(y_true, y_pred),axis=-1) + amp_loss = K.mean(tf.keras.losses.mean_squared_error(yt_amp, yp_amp),axis=-1) + angle_loss = K.mean(tf.keras.losses.mean_squared_error(yt_angle, yp_angle),axis=-1) + tf.print("time_loss:", time_loss, "amp_loss", amp_loss, "angle_loss", angle_loss) - time_loss = tf.keras.losses.mean_squared_error(y_true, y_pred) - amp_loss = tf.keras.losses.mean_squared_error(yt_amp, yp_amp) - angle_loss = tf.keras.losses.mean_squared_error(yt_angle, yp_angle) - print(time_loss) - print(amp_loss) - print(angle_loss) - ftLoss = time_loss + amp_loss - # ftLoss = time_loss + amp_loss + angle_loss + ftLoss = time_loss + amp_loss*5 + # ftLoss = time_loss + 5 * amp_loss + 0.25 * angle_loss # ftLoss = time_loss - + # return ftLoss