LSTM模型预测cos函数

运行环境

python3.6.7、tensorflow1.4.0

思路

这里用numpy对cos函数进行间隔采样,取10000个点作为训练数据,再接着取1000个点作为测试数据。对于取出的数据,放入一个数组中,即一个离散的cos函数的序列,对于这个序列,取对应的点作为输出y,再对应地取点前面的10个点作为此点对应的输入X,即在此时刻根据这10个点X来预测对应的一个点y,自定义一个函数generate_data来完成从序列中生成输入数据X和输出数据y的功能。

这里的模型采用了一个两层LSTM模型,隐藏结点设为30个,最后在LSTM模型后设定了一个全连接层,输出预测结果。训练次数设定为5000次,训练开始前根据初始的参数观察模型在测试集上的预测结果,经过5000次训练后再观察模型在测试集上的预测结果,进行对比。

源代码

# -*- coding: UTF-8 -*-
#Author:Yinli

import numpy as np
import tensorflow as tf
from matplotlib import pyplot as plt

# LSTM中隐藏结点的个数和层数
HIDDEN_SIZE = 30
NUM_LAYERS = 2

# 训练序列长度和训练轮数以及batch大小
TIMESTEPS = 10
TRAINING_STEPS = 5000
BTACH_SIZE = 32

# 训练数据和测试数据个数以及采样间隔
TRAINING_EXAMPLES = 10000
TESTING_EXAMPLES = 1000
SAMPLE_GAP = 0.01

# 从给定的序列中抽取输入数据和输出数据
def generate_data(seq):
    x = []
    y = []
    # 每次取从i开始包括i的10项作为输入,第i+10项作为输出
    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)


# LSTM模型
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)
    ])

    # 将LSTM结构连接成RNN网络计算前向传播结果
    outputs, _ = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32)
    # 因为结果中包括了每一步的输出结果,这里只关心最后一步的输出结果
    output = outputs[:,-1,:]

    # 结果传入一个全连接层,得到预测结果
    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


# 评估训练结果
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()

    # 复用训练的参数
    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)

    # 计算均方差
    predictions = np.array(predictions).squeeze()
    labels = np.array(labels).squeeze()
    rmse = np.sqrt(((predictions-labels) ** 2).mean(axis=0))
    print("Mean Square Error is: %f" % rmse)

    # 将结果绘制出来并显示
    plt.figure()

    plt.subplot(211)
    plt.ylim(-1,1)
    plt.plot(predictions)
    plt.ylabel('predictions')

    plt.subplot(212)
    plt.ylim(-1,1)
    plt.plot(labels,'g')
    plt.ylabel('real_sin')

    plt.show()

def main():
    # 计算测试数据的起始和终点
    test_start = (TRAINING_EXAMPLES + TIMESTEPS) * SAMPLE_GAP
    test_end = test_start + (TESTING_EXAMPLES + TIMESTEPS) * SAMPLE_GAP
    # 从0到测试数据起点生成一个序列用来生成训练数据
    train_X, train_y = generate_data(
        np.cos(np.linspace(0, test_start, TRAINING_EXAMPLES + TIMESTEPS, dtype=np.float32)))
    # 从测试数据起点到终点生成一个序列用来生成测试数据
    test_X, test_y = generate_data(
        np.cos(np.linspace(test_start, test_end, TESTING_EXAMPLES + TIMESTEPS, dtype=np.float32)))

    # 将训练数据转化为数据集的形式
    ds = tf.data.Dataset.from_tensor_slices((train_X, train_y))
    ds = ds.repeat().shuffle(1000).batch(BTACH_SIZE)
    X, y = ds.make_one_shot_iterator().get_next()

    # 调用模型
    with tf.variable_scope("model"):
        _, loss, train_op = lstm_model(X, y, True)

    with tf.Session() as sess:
        # 初始化参数
        sess.run(tf.global_variables_initializer())

        # 训练前查看模型在测试数据上的表现
        run_eval(sess, test_X, test_y)
        # 循环训练
        for i in range(TRAINING_STEPS):
            _, l = sess.run([train_op, loss])
            if i % 1000 == 0:
                print("训练轮数:", str(i), ",此时损失为:", str(l))
        # 训练结束后查看模型在测试数据上的表现
        run_eval(sess, test_X, test_y)

if __name__ == '__main__':
    main()

运行结果

训练之前的测试集结果
5000次训练后的测试集结果
程序输出

结果分析

从输出的图像上可以看到,没有训练之前,测试集的数据经过模型输出的结果均在初始值0.0附近,和正确的cos函数图像丝毫不吻合。在经过5000次训练之后,可以看到测试集经过模型输出的预测结果和正确结果之间的均方差大有下降,在图上可视化的结果也可以看到预测值和正确值的图像高度吻合。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容