tensorflow lstm从隐状态到预测值_Tensorflow之循环神经网络(RNN)

9b4c6db30e690af1fceaaaf72c44d632.png

<废话框>这次要说的是循环神经网络(Recurrent Neural Networks,RNN)。传统的神经网络模型中,是从输入层到隐含层再到输出层,层与层之间是全连接的,每层之间的节点是无连接的。他们都只能单独的取处理一个个的输入,前一个输入和后一个输入是完全没有关系的。但是,某些任务需要能够更好的处理序列的信息,即前面的输入和后面的输入是有关系的。但是普通的神经网络对于很多问题却无能无力。例如,你要预测句子的下一个单词是什么,一般需要用到前面的单词,因为一个句子中前后单词并不是独立的,而RNN就是擅长处理序列数据......</废话框>

(上皆废话,阁下但略无妨)

在这篇文章,你可以了解到如何使用Tensorflow框架搭建RNN,此文章不会出现RNN内部原理的内容,如果是打算来研究RNN的而不是使用的小伙伴就可以节省时间离开这篇陋文了,关于原理的话先上个维基百科意思一下,其实知乎上也有很多把这个讲得很通俗易懂的文章,大家可以去搜一搜

万事先导包,当个调包侠真舒服(可能饿死):

import 

numpy和tensorflow就不说了,导入pylab主要是为了可视化,numpy的话一般装了python就自动安装了,其它两个库如果有没安装的可以用pip安装一下

然后定义一些全局变量,方便后续代码编写:

data_size = 100
timesteps = 16
hidden_size = 20
batch_size = data_size-timesteps+1

这次是想用一个简单的RNN来拟合预测一个sin函数,反正每次都是很简单的东西,入门教程这种东西,一复杂读者一般看着就会略懵,比如讲个RNN,一上来就RNN结合NLP,凉凉,总要考虑有些还没有任何NLP基础的人吧,但是!sin函数大家肯定是知道的。

data_size如其变量名,就是输入数据的多少了嘛

因为sin函数可以自己随意整,不是实际世界,想要多少就多少

timesteps 也就是时间步长,可以理解为LSTM的个数,如下图,timesteps的值就为4

c350c5a80573e5db6849ae8fa1607e58.png
图one

hidden_size 即隐藏层的大小,就像普通BP神经网络隐藏层有多少个神经元一样

batch_size 一次训练使用数据的多少,这里为了方便,就一次把所有数据扔进去了,即data_size-timesteps+1,为什么是这么个数值呢?你想想看,预测一个值需要前面timesteps个隐藏状态作为基础,所以这里将数据处理成data_size-timesteps+1组数据了

数据生成及预处理的代码如下:

def get_data(raw_data,timesteps):
    x = [];y = []
    for i in range(len(raw_data)-timesteps+1):
        x.append(raw_data[i:i+timesteps])
        y.append(raw_data[i+timesteps-1])
    return np.array(x),np.array(y)
raw_x = np.linspace(-10,10,data_size)
raw_data = np.sin(raw_x)
noise = np.random.normal(0,0.02,raw_data.shape) # 不加点噪声都不敢说话
x_data,y_data = get_data(raw_data+noise,timesteps)

get_data函数什么意思呢?举个栗子:

>>> get_data([1,2,3,4,5,6],3)
(array([[1, 2, 3],
       [2, 3, 4],
       [3, 4, 5],
       [4, 5, 6]]), 
array([3, 4, 5, 6]))

可以看出:

  • x:[1,2,3]->y:[3]
  • x:[2,3,4]->y:[4]
  • x:[3,4,5]->y:[5]
  • x:[4,5,6]->y:[6]

x的最后一个数值等于y,且刚好得到data_size-timesteps+1比数据,以此作为RNN的输入

来个图帮助理解下:

9671b840acbd3de5d02009b725f747de.png
图two

而其余几个生成sin函数的数据的代码就不多阐述了

重点来了,RNN的代码:

先附个全的:

class RNN():
    x = tf.placeholder(shape=[None,timesteps,1],dtype=tf.float32)
    y = tf.placeholder(shape=[None,1],dtype=tf.float32)

    W = tf.Variable(tf.random_normal([hidden_size,1]))
    b = tf.Variable(tf.constant(0.1, shape=[1]))

    cell = tf.nn.rnn_cell.BasicRNNCell(num_units=hidden_size)
    output,h = tf.nn.dynamic_rnn(cell,x,dtype=tf.float32)

    prediction = tf.matmul(output[:,-1], W) + b

    loss = tf.losses.mean_squared_error(y, prediction)
    trainstep = tf.train.AdamOptimizer(1e-3).minimize(loss)

再分开:

    x = tf.placeholder(shape=[None,timesteps,1],dtype=tf.float32)
    y = tf.placeholder(shape=[None,1],dtype=tf.float32)

这两个应该很熟悉,不熟悉的话请回顾一下Tensorflow基础,这里要注意的是,要把输入的数据reshape成[batchsize, timesteps, 数据的维度]这种格式

W 

权重W和偏置b的定义,这个像全连接神经网络一样,多少隐藏层多大W定义多大啦。

    cell = tf.nn.rnn_cell.BasicLSTMCell(num_units=hidden_size)
    output,h = tf.nn.dynamic_rnn(cell,x,dtype=tf.float32)

cell是什么,就是单个的神经元啦,第一句代码就是使用BasicRNNCell得到hidden_size个Cell啦。然后我们再回到这个图:

b9c8f16962f4217d4ad73fa5a6d0d681.png
Pic three

t时刻的隐藏状态是由t-1时刻的隐藏状态和t时刻的输入决定的,即

所以上面这个图是这样得到所有的h的:

timesteps为4则需要分四步进行

02d3998a8d0db2c01070e2c1537d8934.png
Pic four

而欲计算

,则代码如下:
h0 = cell.zero_state(batch_size, np.float32)
output1, h1 = cell.call(inputs, h0)
output2, h2 = cell.call(inputs, h1)
...
output4, h4 = cell.call(inputs, h3)

而实际我们只关心组后的

,Tensorflow提供了一个方便的函数dynamic_rnn,直接完成上述所有操作,也就是我们实际代码的第二行。

翻上去不容易,我再贴一下这句代码:

    output,h = tf.nn.dynamic_rnn(cell,x,dtype=tf.float32)

根据您Cell用的不同,返回的两个值会有所出入

如果是BasicRNNCell的话,那么Cell调用call函数返回值output和h是一样的,连内存地址都一样的那种一样,因为在Tensor flow源码中,这个函数返回的两个值是同一个引用。如果是一次性计算完的话(也就是使用dynamic_rnn函数的话),返回的output是

的集合,而返回的h就是最后一个隐藏状态,也就是说output[-1]等于h

如果是BasicLSTMCell的话(也就是我正用的这个),那么Cell调用call函数返回值output等于h[1],返回的h是一个元组,h[0]等于通过激励函数计算过的h[1]。同理如果是一次性计算完的话,output[:,-1,:]等于h[1]

然后就是计算预测值,loss和优化器了:

    prediction = tf.matmul(output[:,-1], W) + b

    loss = tf.losses.mean_squared_error(y, prediction)
    trainstep = tf.train.AdamOptimizer(1e-3).minimize(loss)

都是老套路了不解释了,不懂参考Tensorflow基础

然后继续套路式代码

也不解释了,总不可能说一次Tensorflow就要解释一次Session是什么嘛,希望理解2333
rnet = RNN()
sess = tf.Session()
sess.run(tf.global_variables_initializer())

为了方便实时看到训练的过程,使用Matplotlib可视化训练过程:

pl.figure(figsize=(10,4))
pl.ion()
raw_x = raw_x[timesteps-1:]

raw_x是为了画图用的,至于为什么是timesteps-1?读者自己思考吧

最后一步,训练!

for step in range(100):
    _,yp = sess.run([rnet.trainstep,rnet.prediction],feed_dict={rnet.x:x_data[:,:,None],rnet.y:y_data[:,None]})
    print('The {}th train step'.format(step))
    pl.cla()
    pl.plot(raw_x,yp,color='r')
    pl.scatter(raw_x,y_data,color='b')
    pl.grid()
    pl.pause(0.01)

训练个100次差不多,sin函数多简单呀,久之无益。

循环体内:

  • 第一行:训练并计算预测值
  • 第二行:在控制台打印,告诉我们训练到第几步了
  • 其余行:训练可视化(Matplotlib的知识,相信读者都会 理直气壮.jpg)

最终训练出的模型大概长这样吧

9a435922b01090d3026dd80a7606404b.png
Last pic

是长红色(shai)的那样,不是蓝色的那样,蓝色的是原始数据

其余要说的:

  • 此次使用的网络是单层的RNN(毕竟是个sin函数,不能太过分是吧?搞复杂了overfitting也不好处理是吧),如果您想搭建多层的话:

将这一句代码:

cell = tf.nn.rnn_cell.BasicLSTMCell(num_units=hidden_size)

替换成如下即可:

def get_cells(): return tf.nn.rnn_cell.BasicRNNCell(num_units=hidden_size)
cell = tf.nn.rnn_cell.MultiRNNCell([get_cells() for _ in range(layers_size)])
  • 模型的保存

这篇文章里面我并没有写模型保存的部分,所以我来给你讲道理,我们写个代码都追求什么模块化呀,封装什么的,我觉得写文章亦是如此(其实是为懒找借口)。模型的保存和恢复我已经有文章写过了,相当于对那个知识进行封装了,所以以后写直接调用那篇文章就行了~~~

所以!!!如果想保存模型的小伙伴,Call文章Tensorflow模型保存


最后附上完整代码:(方便您复制呐)

import numpy as np
import tensorflow as tf
import pylab as pl

data_size = 100
timesteps = 16
hidden_size = 20
batch_size = data_size-timesteps+1

def get_data(raw_data,timesteps):
    x = [];y = []
    for i in range(len(raw_data)-timesteps+1):
        x.append(raw_data[i:i+timesteps])
        y.append(raw_data[i+timesteps-1])
    return np.array(x),np.array(y)

raw_x = np.linspace(-10,10,data_size)
raw_data = np.sin(raw_x)
noise = np.random.normal(0,0.02,raw_data.shape)    # 不加点噪声都不敢说话
x_data,y_data = get_data(raw_data+noise,timesteps)


class RNN():
    x = tf.placeholder(shape=[None,timesteps,1],dtype=tf.float32)
    y = tf.placeholder(shape=[None,1],dtype=tf.float32)

    W = tf.Variable(tf.random_normal([hidden_size,1]))
    b = tf.Variable(tf.constant(0.1, shape=[1]))

    cell = tf.nn.rnn_cell.BasicLSTMCell(num_units=hidden_size)
    output,h = tf.nn.dynamic_rnn(cell,x,dtype=tf.float32)

    prediction = tf.matmul(output[:,-1], W) + b

    loss = tf.losses.mean_squared_error(y, prediction)
    trainstep = tf.train.AdamOptimizer(1e-3).minimize(loss)

rnet = RNN()
sess = tf.Session()
sess.run(tf.global_variables_initializer())

pl.figure(figsize=(10,4))
pl.ion()
raw_x = raw_x[timesteps-1:]


for step in range(100):
    _,yp = sess.run([rnet.trainstep,rnet.prediction],feed_dict={rnet.x:x_data[:,:,None],rnet.y:y_data[:,None]})
    print('The {}th train step'.format(step))
    pl.cla()
    pl.plot(raw_x,yp,color='r')
    pl.scatter(raw_x,y_data,color='b')
    pl.grid()
    pl.pause(0.01)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: RNN是一种循环神经网络,它在自然语言处理和序列数据处理中非常常见。虽然我们可以从头开始实现RNN,但建议使用现有的库和包来简化代码,并且提高效率。以下是一种使用Python中的tensorflow库实现RNN的示例: 首先,我们需要导入所需的库和模块: import tensorflow as tf 然后,定义RNN的参数: num_units = 128 input_size = 10 batch_size = 32 time_steps = 20 num_classes = 2 接下来,我们创建输入和输出的占位符: inputs = tf.placeholder(tf.float32, [None, time_steps, input_size]) outputs = tf.placeholder(tf.float32, [None, num_classes]) 然后,我们使用tf.keras.layers中的SimpleRNN层来创建RNNrnn_layer = tf.keras.layers.SimpleRNN(units=num_units) rnn_output = rnn_layer(inputs) 接下来,我们使用全连接层,并应用softmax激活函数来得到最终的输出: fc_layer = tf.keras.layers.Dense(num_classes, activation='softmax') outputs_pred = fc_layer(rnn_output) 接下来,我们定义损失函数和优化器: loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=outputs_pred, labels=outputs)) optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss) 然后,我们可以设置会话,并进行训练: sess = tf.Session() sess.run(tf.global_variables_initializer()) for epoch in range(100): batch_inputs, batch_outputs = get_batch_data() feed_dict = {inputs: batch_inputs, outputs: batch_outputs} sess.run(optimizer, feed_dict=feed_dict) 最后,我们可以使用训练好的模型来进行预测: test_inputs, _ = get_batch_data() feed_dict = {inputs: test_inputs} predictions = sess.run(outputs_pred, feed_dict=feed_dict) 这是一个简单的RNN实现的例子。使用现有的库和包可以帮助我们快速地构建和训练RNN模型,并简化了我们的代码。当然,我们可以根据具体需要调整参数和网络结构来优化模型。 ### 回答2: RNN循环神经网络)是一种能够处理序列数据的神经网络模型。在实际应用中,我们可以使用现有的深度学习库中提供的循环神经网络调包来实现RNN模型。 首先,我们需要选择一个适用的深度学习框架,如TensorFlow、PyTorch或Keras。这些框架都提供了对RNN模型的支持,并且具有相应的调包可以导入和使用。 接下来,我们需要导入所选框架中的RNN模型相关的调包。通常,这些调包包含了模型结构定义、数据预处理和模型训练的功能。 在导入调包之后,我们需要定义RNN模型的结构。这一步通常涉及选择RNN层的类型(如SimpleRNNLSTM或GRU)、藏层的大小、输入序列的长度等。根据框架的不同,具体的代码实现方式会有所差异。 接下来,我们可以使用导入的调包进行数据预处理。这可能包括文本向量化、标签编码或者对序列数据进行填充等操作。循环神经网络的输入通常是一个序列,我们需要确保输入的形状与模型的要求相匹配。 最后,我们可以使用导入的调包训练RNN模型。这一步包括设置模型的优化器、损失函数和评估指标,然后使用训练数据进行模型训练。具体的训练过程可以通过调用框架提供的训练函数来完成。 总之,通过调用现有深度学习框架中提供的RNN调包,我们可以方便地实现循环神经网络模型。这些调包提供了RNN模型的结构定义、数据预处理和模型训练等功能,使得我们可以更加专注于模型的应用和优化。 ### 回答3: RNN(Recurrent Neural Network,循环神经网络)是一种常用于处理序列数据的深度学习模型。为了简化RNN的实现过程,我们可以使用一些流行的深度学习库中提供的RNN调包,例如TensorFlow或PyTorch。 以TensorFlow为例,实现一个基本的RNN模型可以分为以下几个步骤: 1.导入必要的库以及数据集。首先,需要导入TensorFlow库,然后准备好要训练和测试的数据集。 2.数据预处理。在输入数据进入RNN之前,通常需要进行一些预处理操作,例如标准化、序列填充等。 3.定义RNN模型。使用TensorFlow提供的调包,我们可以很方便地定义一个RNN模型。可以选择不同类型的循环神经网络单元(例如LSTM或GRU),定义藏层的大小以及输入输出的维度等。 4.设置优化器和损失函数。选择合适的优化器(如Adam或SGD)和适当的损失函数(如交叉熵)来最小化模型的误差。 5.训练模型。使用数据集进行模型训练,通过反向传播和优化器来更新模型的权重和偏差。 6.模型评估。使用测试集来评估模型的性能,比如计算准确率、损失值等。 7.模型应用。训练好的RNN模型可以用于实际应用中,如生成文本、机器翻译、语音识别等。 总结来说,调包可以极大地简化RNN模型的实现过程。我们只需要了解RNN的原理和基本步骤,然后使用调包提供的API进行模型的搭建、训练和评估等操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值