模型更新

This commit is contained in:
kevinding1125 2023-06-20 20:06:44 +08:00
parent 9d72cb9592
commit a35ccc2f63
5 changed files with 207 additions and 108 deletions

View File

@ -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,7 +29,7 @@ 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)
@ -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,7 +147,9 @@ 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
x = tf.keras.layers.Flatten()(LSTM)
@ -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)

View File

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

View File

@ -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

View File

@ -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):

View File

@ -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)
# 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