『迷你教程』Keras 六步实现简单循环神经⽹络
⽂章⽬录
了解循环神经⽹络 (RNN) 的⼯作原理以及如何通过 Keras 深度学习库使⽤。
介绍RNN的结构、给定输⼊时,RNN 如何计算输出、如何在 Keras 中为 SimpleRNN 准备数据、如何训练 SimpleRNN 模型。RNN 的依赖项
from pandas import read_csv
import numpy as np
from keras .models import Sequential
from keras .layers import Den , SimpleRNN
from sklearn .preprocessing import MinMaxScaler
from sklearn .metrics import mean_squared_error
import math
import matplotlib .pyplot as plt
Keras SimpleRNN
下⾯的函数返回⼀个模型,该模型包括⼀个SimpleRNN层和⼀个Den⽤于学习顺序数据的层。在input_shape指定的参数(time_steps x features)。我们将简化⼀切并使⽤单变量数据,即只有⼀个特征;下⾯讨论 time_steps。
def create_RNN (hidden_units , den_units , input_shape , activation ):
model = Sequential ()
model .add (SimpleRNN (hidden_units , input_shape =input_shape ,
activation =activation [0]))
model .add (Den (units =den_units , activation =activation [1]))
model .compile (loss ='mean_squared_error', optimizer ='adam')
return model
demo_model = create_RNN (2, 1, (3,1), activation =['linear', 'linear'])
demo_model 返回的对象带有 2 个通过SimpleRNN层创建的隐藏单元和 1 个通过Den层创建的密集单元。在input_shape被设定在3×1和linear激活功能是在两个层为简单起见使⽤。只是回忆⼀下线性激活函数不改变输⼊。⽹络如下所⽰:
如果我们有 隐藏单位( 在上述情况下),则:
输⼊:隐藏单位:输⼊单位的权重:为单位
隐藏单位的权重:)
隐藏单位的偏差:)
密集层的权重:)
致密层的偏压:让我们看看上⾯的权重。注意:由于权重是随机初始化的,所以这⾥粘贴的结果会和你的不⼀样。重要的是要了解正在使⽤的每个对象的结构是什么样的,以及它如何与其他对象交互以产⽣最终输出。
wx = demo_model .get_weights ()[0]
wh = demo_model .get_weights ()[1]
bh = demo_model .get_weights ()[2]
wy = demo_model .get_weights ()[3]
by = demo_model .get_weights ()[4]
print ('wx = ', wx , ' wh = ', wh , ' bh = ', bh , ' wy =', wy , 'by = ', by )
输出结果为
x ∈R
煮羊杂汤h ,R m
w ,以R x m w (R h MXM b (R h m w (R y m b ∈y R
wx =[[0.18662322-1.2369459]] wh =[[0.86981213-0.49338293]
[0.493382930.8698122]] bh =[0.0.] wy =[[-0.4635998]
毛少一横是什么字
[0.6538409]] by =[0.]
现在让我们做⼀个简单的实验,看看来⾃ SimpleRNN 和 Den 层的层是如何产⽣输出的。记住这个数字。
我们将输⼊x三个时间步长,然后让⽹络⽣成⼀个输出。将计算时间步长 1、2 和 3 中隐藏单元的值。初始化为零向量。输出 是从 和 . 由于我们使⽤的是线性单元,因此不需要激活函数。
x = np.array([1,2,3])
# 将输⼊重塑为所需的sample_size x time_steps x特性
x_input = np.reshape(x,(1,3,1))
y_pred_model = demo_model.predict(x_input)
m =2
h0 = np.zeros(m)
h1 = np.dot(x[0], wx)+ h0 + bh
h2 = np.dot(x[1], wx)+ np.dot(h1,wh)+ bh
h3 = np.dot(x[2], wx)+ np.dot(h2,wh)+ bh
o3 = np.dot(h3, wy)+ by
print('h1 = ', h1,'h2 = ', h2,'h3 = ', h3)
print("Prediction from network ", y_pred_model)
print("Prediction from our computation ", o3)
输出结果为
h1 =[[0.18662322-1.23694587]] h2 =[[-0.07471441-3.64187904]] h3 =[[-1.30195881-6.84172557]]
Prediction from network [[-3.8698118]]
Prediction from our computation [[-3.86981216]]
水苍玉在太阳⿊⼦数据集上运⾏ RNN
现在我们了解了 SimpleRNN 和 Den 层是如何组合在⼀起的。让我们在⼀个简单的时间序列数据集上运⾏⼀个完整的 RNN。我们需要按照以下步骤操作
1. 从给定的 URL 读取数据集
2. 将数据拆分为训练集和测试集
3. 准备输⼊所需的 Keras 格式
4. 创建⼀个 RNN 模型并训练它
5. 对训练集和测试集进⾏预测,并在两个集上打印均⽅根误差
6. 查看结果
步骤 1、2:读取数据并拆分为训练和测试
以下函数从给定的 URL 读取训练和测试数据,并将其拆分为给定百分⽐的训练和测试数据。在使⽤MinMaxScaler来⾃ scikit-learn的数据在 0 和 1 之间缩放后,它返回训练和测试数据的⼀维数组。
# 参数split_percent定义了训练⽰例的⽐例
def get_train_test(url, split_percent=0.8):
地下城堡2df = read_csv(url, ucols=[1], engine='python')
data = np.array(df.values.astype('float32'))
scaler = MinMaxScaler(feature_range=(0,1))
data = scaler.fit_transform(data).flatten()
n =len(data)
# 将数据分解为训练和测试
考研政治主观题split =int(n*split_percent)
train_data = data[range(split)]
test_data = data[split:]
return train_data, test_data, data
sunspots_url ='/jbrownlee/Datats/master/monthly-sunspots.csv'
train_data, test_data, data = get_train_test(sunspots_url)
第 3 步:为 Keras 重塑数据
下⼀步是为 Keras 模型训练准备数据。输⼊数组应当成形为:total_samples x time_steps x features。
有很多⽅法可以为训练准备时间序列数据。我们将创建具有⾮重叠时间步长的输⼊⾏。下图显⽰了 time_steps = 2 的⽰例。这⾥
time_steps 表⽰⽤于预测时间序列数据的下⼀个值的先前时间步数。
以下函数get_XY()将⼀维数组作为输⼊并将其转换为所需的输⼊X 和⽬标Y 数组。我们将使⽤ 12time_steps作为太阳⿊⼦数据集,因为太阳⿊⼦通常有 12 个⽉的周期。您可以尝试使⽤ 的其他值time_steps。
# 准备输⼊X和⽬标Y
def get_XY(dat, time_steps):
# Indices of target array
Y_ind = np.arange(time_steps,len(dat), time_steps)
古代戏曲
Y = dat[Y_ind]
# Prepare X
rows_x =len(Y)
X = dat[range(time_steps*rows_x)]
X = np.reshape(X,(rows_x, time_steps,1))
return X, Y
time_steps =12
trainX, trainY = get_XY(train_data, time_steps)
testX, testY = get_XY(test_data, time_steps)
第 4 步:创建 RNN 模型并训练
对于这⼀步,我们可以重⽤create_RNN()上⾯定义的函数。
model = create_RNN(hidden_units=3, den_units=1, input_shape=(time_steps,1),
activation=['tanh','tanh'])
model.fit(trainX, trainY, epochs=20, batch_size=1, verbo=2)
第 5 步:计算并打印均⽅根误差
该函数print_error()计算实际值和预测值之间的均⽅误差。
def print_error(trainY, testY, train_predict, test_predict):
# 错误的预测
train_rm = math.sqrt(mean_squared_error(trainY, train_predict))
test_rm = math.sqrt(mean_squared_error(testY, test_predict))
# 打印RMSE
print('Train RMSE: %.3f RMSE'%(train_rm))
print('Test RMSE: %.3f RMSE'%(test_rm))
# 做出预测
train_predict = model.predict(trainX)
test_predict = model.predict(testX)
# 均⽅误差
print_error(trainY, testY, train_predict, test_predict)
输出结果
Train RMSE:0.058 RMSE
Test RMSE:0.077 RMSE
第六步:查看结果
以下函数绘制实际⽬标值和预测值。红线将训练和测试数据点分开。
# 绘图
def plot_result(trainY, testY, train_predict, test_predict):
梦到电梯actual = np.append(trainY, testY)
predictions = np.append(train_predict, test_predict)
rows =len(actual)
plt.figure(figsize=(15,6), dpi=80)
plt.plot(range(rows), actual)
plt.plot(range(rows), predictions)
流调报告plt.axvline(x=len(trainY), color='r')
plt.legend(['Actual','Predictions'])
plt.xlabel('Obrvation number after given time steps')
plt.ylabel('Sunspots scaled')
plt.title('Actual and Predicted Values. The Red Line Separates The Training And Test Examples') plot_result(trainY, testY, train_predict, test_predict)
⽣成以下图: