sin函数可以看做是一个序列的图线,并且sin函数是一个连续的曲线,循环神经网络的预测是离散的时刻取值,为了模拟出sin函数这种连续的图线,所以需要将连续的sin函数曲线离散化,也就是在某一个区间内找到有限个点来大致描绘出sin函数曲线的样子。
构造数据
为了模拟出sin函数,那么首先需要对sin函数的数据进行采样,TRAINING_EXAMPLES
为训练数据的个数,设置为10000个点,每隔SAMPLE_GAP
取一个点,该值设置为0.01,TESTING_EXAMPLES
为测试样本的个数。那么对于我们选取的[0,test_end]这段序列中,我们选取[0,test_start)这段抽取数据作为训练数据,而测试集的数据在[test_start,test_end]。
test_start = (TRAINING_EXAMPLES + TIMESTEPS) * SAMPLE_GAP
test_end = test_start + (TESTING_EXAMPLES + TIMESTEPS) * SAMPLE_GAP
接下来就也要根据上面生成的时间信息去生成数据,通俗的就是知道x,需要找到sin(x)的值。
对于np.linspace
这个函数,是构成了一个等差序列的数组,起始点为第一个参数,终止点是第二个参数,第三个参数是等差数列中的d。经过sin函数一求就可以得到(0,test_start)这个区间的sin函数的采样点了,同理得到(test_start,test_end)区间的sin函数的采样点。
train_X, train_y = generate_data(np.sin(np.linspace(
0, test_start, TRAINING_EXAMPLES + TIMESTEPS, dtype=np.float32)))
test_X, test_y = generate_data(np.sin(np.linspace(
test_start, test_end, TESTING_EXAMPLES + TIMESTEPS, dtype=np.float32)))
我们得到这两段sin函数的取样点怎么构造输入数据呢,根据generate_data
函数就可以得到输入数据。其实也很简单,就是根据前面一小段数据预测下一个点,就这样不停从训练数据构造n个小段。这样就明确了数据了。这儿采取的根据前TIMESTEPS-1
个采样点来预测第TIMESTEPS
点的值
def generate_data(seq):
"""
构造输入数据
:param seq:
:return:
"""
X = []
y = []
for i in range(len(seq) - TIMESTEPS):
X.append([seq[i: i + TIMESTEPS]])
y.append([seq[i + TIMESTEPS]])
return np.array(X, dtype=np.float32), np.array(y, dtype=np.float32)
创建模型
接下来就是常规的构造模型了
def lstm_model(X, y, is_training):
# 使用多层的LSTM结构。
cell = tf.nn.rnn_cell.MultiRNNCell([
tf.nn.rnn_cell.BasicLSTMCell(HIDDEN_SIZE)
for _ in range(NUM_LAYERS)])
# 使用TensorFlow接口将多层的LSTM结构连接成RNN网络并计算其前向传播结果。
outputs, _ = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32)
output = outputs[:, -1, :]
# 对LSTM网络的输出再做加一层全链接层并计算损失。注意这里默认的损失为平均
# 平方差损失函数。
predictions = tf.contrib.layers.fully_connected(
output, 1, activation_fn=None)
# 只在训练时计算损失函数和优化步骤。测试时直接返回预测结果。
if not is_training:
return predictions, None, None
# 计算损失函数。
loss = tf.losses.mean_squared_error(labels=y, predictions=predictions)
# 创建模型优化器并得到优化步骤。
train_op = tf.contrib.layers.optimize_loss(
loss, tf.train.get_global_step(),
optimizer="Adagrad", learning_rate=0.1)
return predictions, loss, train_op
验证模型
得到模型之后,需要将模型应用到测试数据,并且画图观测预测的图线是否符合一个sin函数
def run_eval(sess, test_X, test_y):
# 将测试数据以数据集的方式提供给计算图。
ds = tf.data.Dataset.from_tensor_slices((test_X, test_y))
ds = ds.batch(1)
X, y = ds.make_one_shot_iterator().get_next()
# 调用模型得到计算结果。这里不需要输入真实的y值。
with tf.variable_scope("model", reuse=True):
prediction, _, _ = lstm_model(X, [0.0], False)
# 将预测结果存入一个数组。
predictions = []
labels = []
for i in range(TESTING_EXAMPLES):
p, l = sess.run([prediction, y])
predictions.append(p)
labels.append(l)
# 计算rmse作为评价指标。
predictions = np.array(predictions).squeeze()
labels = np.array(labels).squeeze()
rmse = np.sqrt(((predictions - labels) ** 2).mean(axis=0))
print("Root Mean Square Error is: %f" % rmse)
# 对预测的sin函数曲线进行绘图。
plt.figure()
plt.plot(predictions, label='predictions')
plt.plot(labels, label='real_sin')
plt.legend()
plt.show()