TensorFlow 16——ch12-RNN 和 LSTM 的实现方式

29 篇文章 0 订阅
19 篇文章 0 订阅

TensorFlow 15——ch12-RNN、LSTM基本结构

RNNCell

RNNCell 是 Tensorflow 中的 RNN 基本单元,是一个抽象类,没有办法实体化,要用的是两个子类,一个是 BasicRNNCell ,一个是 BasicLSTMCell

RNNCell 有一个 call 函数,是 RNN 的单步计算,调用:

(output, next_state) = call(input, state)

初始输入为 x1,初始的隐藏层为 h0,例如:

(output1, h1) = cell.call(x1, h0) # 得到h1
(output2, h2) = cell.call(x2, h1) # 得到h2

RNNCell 的类属性 :

  • state_size 规定了隐藏层的大小
  • output_size 规定了输出向量的大小

RNN 基本单元

import tensorflow as tf
rnn_cell = tf.nn.rnn_cell.BasicRNNCell(num_units=128)
print(rnn_cell.state_size)

在这里插入图片描述

LSMT 基本单元

import tensorflow as tf
lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(num_units=128)
print(lstm_cell.state_size)

在这里插入图片描述

可以看到 BasicLSTMCell 的 state_size 由 ch 两部分组成。

所以一般使用 BasicLSTMCell 的时候,分开这两部分:

import tensorflow as tf
import numpy as np
lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(num_units=128)
inputs = tf.placeholder(np.float32, shape=(32, 100))
h0 = lstm_cell.zero_state(32, np.float32)
output, h1 = lstm_cell.call(inputs, h0)
print(h1.h)
print(h1.c)

在这里插入图片描述

MultiRNNCell

单层 RNN 的能力有限,所以需要多层的 RNN,也就是第一层的输出 h 作为第二层的输入。

可以使用tf.nn.rnn_cell.MultiRNNCell 函数对 RNN 进行堆叠。测试代码如下:

# 返回一个BasicLSTMCell
def get_a_cell():
	return tf.nn.rnn_cell.BasicLSTMCell(128)

# 创建3层的RNN,state_size=(128,128,128),表示3个隐层大小都为128
cell = tf.nn.rnn_cell.MultiRNNCell([get_a_cell() for _ in range(3)])

inputs = tf.placeholder(np.float32, shape=(32, 100))
h0 = cell.zero_state(32, np.float32)
output, h1 = cell.call(inputs, h0)
print(h1)

打印结果(换行是我加的):

在这里插入图片描述

LSTMStateTuple(
c=<tf.Tensor 'cell_0/cell_0/basic_lstm_cell/add_1:0' shape=(32, 128) dtype=float32>, 
h=<tf.Tensor 'cell_0/cell_0/basic_lstm_cell/mul_2:0' shape=(32, 128) dtype=float32>
), 
LSTMStateTuple(
c=<tf.Tensor 'cell_1/cell_1/basic_lstm_cell/add_1:0' shape=(32, 128) dtype=float32>, 
h=<tf.Tensor 'cell_1/cell_1/basic_lstm_cell/mul_2:0' shape=(32, 128) dtype=float32>
), 
LSTMStateTuple(
c=<tf.Tensor 'cell_2/cell_2/basic_lstm_cell/add_1:0' shape=(32, 128) dtype=float32>, 
h=<tf.Tensor 'cell_2/cell_2/basic_lstm_cell/mul_2:0' shape=(32, 128) dtype=float32>
)

BasicRNNCell 的 call

BasicRNNCell 的 call 的 return :

def call(self, inputs, state):
    if self._linear is None:
        self._linear = _Linear([inputs, state], self._num_units, True)
        output = self._activation(self._linear([inputs, state]))
        return output, output

可以看出在 BasicRNNCell 中 output(输出) 和隐状态是一样的,因此需要额外对输出定义新的变换,才能得到图中真正的输出 y 。

而隐状态就是函数中的 output(函数),所以 BasicRNNCell 中 state_size 永远等于 output_size 。

BasicLSTMCell 的 call

BasicLSTMCell 的 call 的 return :

if self._state_is_tuple:
	new_state = LSTMStateTuple(new_c, new_h)
else:
	new_state = array_ops.concat([new_c, new_h], 1)
return new_h, new_state

其中 _state_is_tuple 是一直等于 Ture 的,所以返回的隐状态是 LSTMStateTuple(new_c, new_h) ,而output是 new_h

因此如果处理的是分类问题,还需要对 output 添加单独的 Softmax 层才能得到最后的分类概率输出。

展开时间维度

对单个的 RNNCell ,如果序列长,则需要调用n次call,所以 Tensorflow 提供了一个函数 tf.nn.dynamic_rnn,这个函数相当于就调用了n次call。

def dynamic_rnn(cell, inputs, sequence_length=None, initial_state=None, dtype=None, parallel_iterations=None, swap_memory=False, time_major=False, scope=None):

输入的 inputs 数据格式:

inputs: shape = (batch_size, time_steps, input_size)

  • batch_size:batch的大小
  • time_steps:长度,也就是 time_steps 次call
  • input_size:表示输入数据单个序列单个时间维度上固有的长度
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值