深度学习应用方面繁多,涉及的知识、函数众多,本文只针对时序神经网络模型,并且是基于数据的回归问题进行阐述与解析,不涉及图像、文本等应用场景的介绍。

首先是引入库

引入库:

import numpy as np  
import matplotlib.pyplot as plt
import pandas as pd
import tensorflow as tf
from tensorflow.keras.layers import GRU, LSTM, Activation, Dense, Dropout, BatchNormalization, ReLU # 网络层
from tensorflow.keras.models import Sequential, load_model 
from tensorflow.keras.optimizers import Adam, RMSprop, Adagrad, Adamax, Nadam  # 优化器
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping # 回调函数

其次是准备数据准备

数据可以是NumPy arrays 或者 tf.data.Dataset objects

NumPy arrays这种形式需要读取数据进内存。
TensorFlow Dataset objects 这种形式可以从硬盘读取数据流,而不用将数据全部放在内存,是高性能的选项。

如何读入数据集:
tf.keras.preprocessing.image_dataset_from_directory 读入图像
tf.keras.preprocessing.text_dataset_from_directory 读入文本
tf.data.experimental.make_csv_dataset 是从CSV文件中读入数据

这里我用的是NumPy arrays作为数据形式。

数据预处理:

  1. 标准归一化
    将数据缩放到零均值单位方差的形式。
def Data_pre_process(data):
    mean = data.mean(axis = 0)  # 按列取均值
    mean_data = data - mean # 零均值化
    std = data.std(axis = 0)  # 按列求标准差
    std_data = mean_data/std  # 标准化(array的广播)
    return std_data, mean, std

上述代码是对数据进行标准归一化,将data的每

def Data_reverse(data, mean, std):
    std_data = np.multiply(data, std) # 广播后,按对应位置相乘。
    mean_data = std_data + mean
    return mean_data
  1. 离差归一化
def MinMax_process(data): # data type = np.array
    data_min = data.min(axis = 0)
    data_max = data.max(axis = 0)
    proed_data = (data - data_min) / (data_max-data_min)
    return proed_data, data_min, data_max
def MinMax_reverse(proed_data, data_min, data_max):  # data type = np.array
    data = proed_data *(data_max - data_min) + data_min
    return data

因为在模型之外进行数据预处理毕竟麻烦并且影响了模型的便携性,所以 Keras 也提供预处理层,包括文本向量化,特征正规化,图像的缩放、剪切以及数据增强。这些层的使用是调用 layer.adapt(data) 方法进行的。此处不再介绍集成的函数化方法,这些方法在官方文档都有解释。

建立模型

建立GRU或者LSTM神经网络:

def gru_model():
    model = Sequential()  #序列模型
    model.add(GRU(units = 60, batch_input_shape = (17,50,7), return_sequences = True, stateful=True)) # 第一层需要指定输入形状
    model.add(GRU(units = 60, return_sequences = True, stateful=True))
    model.add(GRU(units = 60, return_sequences = True, stateful=True))    
    # model.add(LSTM(units = 60, return_sequences = True, stateful=True))
    # model.add(LSTM(units = 60, return_sequences = True, stateful=True))
    # model.add(ReLU(max_value=1.0))
    # model.add(Dense(units = 60, activation = 'sigmoid'))
    model.add(Dense(units = 6)) 
    model.compile(loss = 'mse', optimizer = 'Nadam', metrics =[tf.keras.metrics.MeanSquaredError()]) # 编译模型
    # 损失函数有: mean_squared_error, mean_absolute_error,huber_loss,log_cosh
    return model

batch_input_shape = (17,50,7) 中,17为Batch的数目,50为时间步长度,7为特征的维数。

此时用于训练该神经网络的训练集形状应该与batch_input_shape相同。

由于输出需要拟合的特征数目为6,所以在模型结尾使用Dense(units = 6)映射层。

return_sequences = True,表示输出是返回序列,False表示返回最后一个时刻的状态,如果该层后面还需要接RNN层,则需要将其设置为True。

stateful = True,表示每个batch的最后一个样本状态将作为下一个batch的初始状态。

GRU的参考文档:https://keras.io/api/layers/recurrent_layers/gru/ LSTM的参考文档:https://keras.io/api/layers/recurrent_layers/lstm/ 建立的GRU神经网络的结构为:

时序自回归lstm 时序数据回归_深度学习

BP神经网络的建立:

def bp_model():
    model = Sequential()
    model.add(Dense(units = 30,  input_dim = 7 , activation='relu'))
    model.add(Dense(units = 40, activation='relu'))
    model.add(Dense(units = 6,activation='tanh'))
    model.compile(loss = 'mean_squared_error', optimizer = 'Nadam')  #  mean_squared_error, mean_absolute_error,huber_loss,log_cosh
    return model

激活函数通常用的有relu,tanh,sigmoid三种。

建立的BP神经网络的结构为:

时序自回归lstm 时序数据回归_神经网络_02

训练模型与测试模型

显示训练与验证误差曲线的函数:

def visualize_loss(history, title):
    loss = history.history["loss"]
    val_loss = history.history["val_loss"]
    epochs = range(len(loss))
    plt.figure()
    plt.plot(epochs, loss, "b", label="Training loss")
    plt.plot(epochs, val_loss, "r", label="Validation loss")
    plt.title(title)
    plt.xlabel("Epochs")
    plt.ylabel("Loss")
    plt.legend()
    plt.show()

神经网络训练的信息主要是通过model.fit()函数返回到一个结构体中的history字典中,我们定义这个结构体名字为history,则读取history.history中的loss信息也就是训练的损失值,其中记录了每一步训练的损失函数值,再读取val_loss信息也就是验证的损失值,训练步数即为loss的长度,再利用plt.plot()绘图。

下面是主程序,仅为示例:

#读入训练集
train_ins_input = pd.read_csv('input_train.csv')
train_ins_output = pd.read_csv('output_train.csv')

# 读入测试集
test_ins_input = pd.read_csv('input_test.csv')
test_ins_output = pd.read_csv('output_test.csv')

#将所有集合并(为了统一归一化)
ins_input = np.concatenate((train_ins_input.values[:850,:], test_ins_input.values[:850,:]))
ins_output = np.concatenate((train_ins_output.values[:850,:], test_ins_output.values[:850,:]))

# 标准归一化
ins_input_norm, input_mean, input_std = Data_pre_process(ins_input)
ins_output_norm, output_mean, output_std = Data_pre_process(ins_output)

# # 使用离差归一化
# ins_input_norm, input_min, input_max = MinMax_process(ins_input)
# ins_output_norm, output_min, output_max = MinMax_process(ins_output)

# 测试数据  标准化后的测试集输入
x_test = ins_input_norm[850:,:]
# 改变为神经网络模型的输入形状
x_test = x_test.reshape(17,50,7)

# 按Batch变形
ins_input_norm = ins_input_norm.reshape(34,50,7)
ins_output_norm = ins_output_norm.reshape(34,50,6)

# 建立神经网络模型
model = gru_model()
# model = bp_model()

# 显示神经网络模型结构
model.summary()

# 提前停止训练,回调函数
custom_early_stopping = EarlyStopping(
    monitor='loss', 
   patience=3000, # 容忍步数
     min_delta=0.001,  # 最小调整量
    mode='max'
)

#保存模型,回调函数
mcp_save = ModelCheckpoint('best_model.h5', save_best_only = True, monitor='val_loss', mode ='min')

#训练模型, 训练集与测试集按0.5, 对半分, 训练步数2000.
history = model.fit(ins_input_norm, ins_output_norm, epochs = 2000, verbose = 2, validation_split = 0.5, callbacks=[mcp_save, custom_early_stopping]) 



#显示训练与验证误差曲线
visualize_loss(history, "Training and Validation Loss")

# 模型预测
y_pre_norm = model.predict(x_test)
y_pre_norm = y_pre_norm.reshape(850,6)

#反归一化
y_pre = Data_reverse(y_pre_norm, np.array(output_mean), np.array(output_std))
# y_pre = MinMax_reverse(y_pre_norm, np.array(output_min), np.array(output_max))


# 计算测试集误差并绘图
ave_error = np.abs(y_pre - test_ins_output.values[:850,:])
plt.figure()
plt.plot(range(850),ave_error[:,0],'b')
plt.plot(range(850),ave_error[:,1],'r')
plt.plot(range(850),ave_error[:,2],'g')

# 输出测试集 均值误差与均方差、标准差
mse = np.square(ave_error)
mse = mse.sum(axis=0)/np.shape(mse)[0]
ave_error = ave_error.sum(axis = 0)/np.shape(ave_error)[0]
print(ave_error)
print(mse)
std = np.sqrt(mse)
print(std)

模型的保存与读取

# 读入保存的模型测试
model = tf.keras.models.load_model('best_model.h5')
model.summary()

# 保存模型
model.save('best_model.h5')