深度学习应用方面繁多,涉及的知识、函数众多,本文只针对时序神经网络模型,并且是基于数据的回归问题进行阐述与解析,不涉及图像、文本等应用场景的介绍。
首先是引入库
引入库:
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
作为数据形式。
数据预处理:
- 标准归一化
将数据缩放到零均值单位方差的形式。
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
- 离差归一化
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神经网络的结构为:
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神经网络的结构为:
训练模型与测试模型
显示训练与验证误差曲线的函数:
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')