文章目录


多个LSTM-每个LSTM的输入特征时间窗不同,将其输出进行连接,再通过一个Dense层

数据

数据

代码
#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@author: liujie
@software: PyCharm
@file: Multi-LSTM.py
@time: 2020/11/14 11:36
"""
'''
    使用LSTM处理回归问题,每个输入特征的时间窗维度不一样,因此可以看作利用了多个LSTM特征提取器
'''
import warnings
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error,mean_absolute_error
from sklearn.preprocessing import MinMaxScaler

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers,optimizers,metrics,losses
from keras.layers.recurrent import LSTM

# 读取数据
def read_data(filepath):
    data = pd.read_excel(filepath,header=0)
    data = data.iloc[:,1:12]    # 数据
    label = data.iloc[:,-1]
    print('The Data : \n',data)
    return data,label

# 归一化
def min_max_scaler(data,label):
    label = np.array(label)
    data_scaler = MinMaxScaler()
    data = data_scaler.fit_transform(data)

    label_scaler = MinMaxScaler()
    label = label_scaler.fit_transform(label.reshape(-1, 1))

    return data,label

# 转换为n_lstm的输入与输出
def n_lstm_data(data,data_length,delay_factor):
    x0 = []
    x1 = []
    x2 = []
    x3 = []
    x4 = []
    x5 = []
    x6 = []
    y = []
    for index in range(max(delay_factor),data_length):
        # 每一列数据的滞后参数不同
        x0.append(data[index - delay_factor[0] : index + 1,0:1])
        x1.append(data[index - delay_factor[1] : index + 1,1:2])
        x2.append(data[index - delay_factor[2] : index + 1,2:3])
        x3.append(data[index - delay_factor[3] : index + 1,3:4])
        x4.append(data[index - delay_factor[4] : index + 1,4:5])
        x5.append(data[index - delay_factor[5] : index + 1,5:6])
        x6.append(data[index-0 : index +1,6:-1])
        y.append(data[index,-1])

    x0 = np.array(x0)
    x1 = np.array(x1)
    x2 = np.array(x2)
    x3 = np.array(x3)
    x4 = np.array(x4)
    x5 = np.array(x5)
    x6 = np.array(x6)
    y = np.array(y)
    print('x0~x6.shape,y.shape\n',x0.shape,x1.shape,x2.shape,x3.shape,x4.shape,x5.shape,x6.shape,y.shape)

    return x0,x1,x2,x3,x4,x5,x6,y

# 构造数据,并分割数据集-根据原始数据集构建符合神经网络的数据集
def make_dataset(data,test_num):
    feature_num = data.shape[1] - 1
    data_length = data.shape[0]

    # 转换成模型的输入
    x0, x1, x2, x3, x4, x5, x6, y = n_lstm_data(data,data_length,delay_factor)

    # 分割数据集
    x0_train,x0_test = x0[:-test_num,:],x0[-test_num:,:]
    x1_train,x1_test = x1[:-test_num,:],x1[-test_num:,:]
    x2_train,x2_test = x2[:-test_num,:],x2[-test_num:,:]
    x3_train,x3_test = x3[:-test_num,:],x3[-test_num:,:]
    x4_train,x4_test = x4[:-test_num,:],x4[-test_num:,:]
    x5_train,x5_test = x5[:-test_num,:],x5[-test_num:,:]
    x6_train,x6_test = x6[:-test_num,:],x6[-test_num:,:]
    y_train,y_test = y[:-test_num],y[-test_num:]

    print('数据集长度:',data_length)
    print('测试集长度:',test_num)

    return x0_train,x0_test,x1_train,x1_test,x2_train,x2_test,x3_train,x3_test,x4_train,x4_test,x5_train,x5_test,x6_train,x6_test,y_train,y_test


# 建立N_LSTM模型
def n_lstm_model(delay_factor,rnn_units,dropout):
    # 输入层
    inputs0 = tf.keras.Input(shape=(delay_factor[0]+1,1))
    inputs1 = tf.keras.Input(shape=(delay_factor[1]+1,1))
    inputs2 = tf.keras.Input(shape=(delay_factor[2]+1,1))
    inputs3 = tf.keras.Input(shape=(delay_factor[3]+1,1))
    inputs4 = tf.keras.Input(shape=(delay_factor[4]+1,1))
    inputs5 = tf.keras.Input(shape=(delay_factor[5]+1,1))
    inputs6 = tf.keras.Input(shape=(1,4))

    # LSTM层
    rnn0 = LSTM(rnn_units,activation='relu',return_sequences=False)(inputs0)
    rnn1 = LSTM(rnn_units,activation='relu',return_sequences=False)(inputs1)
    rnn2 = LSTM(rnn_units,activation='relu',return_sequences=False)(inputs2)
    rnn3 = LSTM(rnn_units,activation='relu',return_sequences=False)(inputs3)
    rnn4 = LSTM(rnn_units,activation='relu',return_sequences=False)(inputs4)
    rnn5 = LSTM(rnn_units,activation='relu',return_sequences=False)(inputs5)
    rnn6 = LSTM(rnn_units,activation='relu',return_sequences=False)(inputs6)

    # 将输入张量进行拼接
    rnn = layers.Concatenate(axis=1)([rnn0,rnn1,rnn2,rnn3,rnn4,rnn5,rnn6])

    # droupout层
    dense = layers.Dropout(dropout)(rnn)

    # 输出层
    outputs = layers.Dense(1,activation='relu')(dense)

    # 模型
    model = tf.keras.Model(inputs=[inputs0,inputs1,inputs2,inputs3,inputs4,inputs5,inputs6],outputs=outputs)

    return model


# 反归一化
def inverse_data(label_,data):
    data = np.array(data).reshape(-1,1)
    label_ = np.array(label_).reshape(-1,1)
    data_scaler = MinMaxScaler()
    data_1 = data_scaler.fit(label_)
    data =  data_scaler.inverse_transform(data)
    data = data[:,0]
    return data


# 展示
def plotdata(y_test,y_test_pred):
    # rmse
    rmse = np.sqrt(mean_squared_error(y_test,y_test_pred))

    fig = plt.figure(figsize=(10,5))
    fig.add_subplot()
    plt.plot(y_test,'r--',label = 'test')
    plt.plot(y_test_pred,'b-',label = 'predict')
    plt.legend(loc = 'upper right')
    plt.title('RMSE : %.4f'%rmse)
    plt.show()




if __name__ == '__main__':
    warnings.filterwarnings(action='ignore')
    # 设置美化样式
    plt.style.use('ggplot')

    # 设置参数
    test_num = 200
    dropout = 0.1
    epoch = 50  # 迭代次数
    batch_size = 64     # 批处理数量
    validation_split = 0.1  # 验证集比例
    delay_factor = [0,11,4,1,0,12]      # 滞后参数

    # 读取数据
    filepath = './data/总的数据集.xlsx'
    data,label_ = read_data(filepath)
    # 归一化
    data,label = min_max_scaler(data,label_)
    # 构造数据集
    x0_train, x0_test, x1_train, x1_test, x2_train, x2_test, x3_train, x3_test, x4_train, x4_test, x5_train, x5_test, x6_train, x6_test, y_train, y_test = make_dataset(data,test_num)

    # parameter
    rnn_units = 8 # rnn神经元个数
    save_model = 'n_lstm_model.h5'

    # Model
    model = n_lstm_model(delay_factor,rnn_units,dropout)
    # 编译模型
    model.compile(optimizer=optimizers.Adam(learning_rate=1e-3),
                  loss= tf.losses.MSE,
                  metrics = ['accuracy'])
    # 展示模型结构
    model.summary()

    # 训练模型
    # patience含义是:可以接受多少个epoch内monitor没有改善,之后训练将停止
    early_stop = keras.callbacks.EarlyStopping(monitor='val_loss',patience=10)
    # 保存最好的模型-保存模型或模型权重
    cp = keras.callbacks.ModelCheckpoint(filepath = save_model,monitor='val_loss',save_best_only=True)
    history  = model.fit(x = [x0_train,x1_train,x2_train,x3_train,x4_train,x5_train,x6_train],
                         y = y_train,
                         batch_size=batch_size,
                         epochs = epoch,
                         verbose=1,callbacks=[early_stop,cp],
                         validation_split = 0.1)

    # 迭代图像
    loss = history.history['loss']
    val_loss = history.history['val_loss']
    epochs_range = range(len(loss))
    plt.plot(epochs_range, loss, label = 'Train Loss')
    plt.plot(epochs_range, val_loss, label = 'Val Loss')
    plt.legend(loc = 'upper right')
    plt.title('Train and Val Loss')
    plt.show()

    model.load_weights(save_model)  #加载最好的训练结果

    # 测试集预测结果
    y_test_predict = model.predict([x0_test,x1_test,x2_test,x3_test,x4_test,x5_test,x6_test])
    # 反归一化
    y_test = inverse_data(label_,y_test)
    y_test_predict = inverse_data(label_,y_test_predict)
    # 保存输出结果
    pd.DataFrame(y_test_predict).to_csv('y_test_predict.csv')
    # 画图显示
    plotdata(y_test,y_test_predict)

在这里插入图片描述
在这里插入图片描述

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐