NLP之RNN-LSTM-GRU的tensorflow实现

1、RNN--LSTM--GRU序列的tensorflow实现(单层)

        这里只需要定义一个即可,其余的cell进行替换即:

                BasicRNNCell是最基本的一种cell    --(替换为)-->    RNNCell、BasicLSTMCell、LSTMCell、GRUCell

tf.nn.dynamic_rnn(cell, inputs, sequence_length=None, initial_state=None, 
        dtype=None, parallel_iterations=None,swap_memory=False,time_major=False, scope=None)
    
    参数:
    --cell: RNNCell的一个实例
    --inputs: RNN输入
    --time_major == False(默认): 则是一个shape为[batch_size, max_time, input_size]的Tensor,或者这些元素的嵌套元组
      time_major == True: 则是一个shape为[max_time, batch_size, input_size]的Tensor,或这些元素的嵌套元组
      (time_major =True更有效,因为它避免了RNN计算开始和结束时的转置.但是,大多数TensorFlow数据都是batch-major,因此默认情况下,此函数接受输入并以batch-major形式发出输出)
    --sequence_length: (可选)大小为[batch_size],数据的类型是int32/int64向量。
    --initial_state: (可选)RNN的初始state(状态)。
    
    返回值:一对(outputs, state)
    --outputs: RNN输出Tensor
        --如果time_major == False(默认),这将是shape为[batch_size, max_time, cell.output_size]的Tensor
        --如果time_major == True,这将是shape为[max_time, batch_size, cell.output_size]的Tensor
    --state: 最终的状态
        --一般情况下state的形状为 [batch_size, cell.output_size ]
        --如果cell是LSTMCells,则state将是包含每个单元格的LSTMStateTuple的元组,state的形状为[2,batch_size, cell.output_size]
import tensorflow as tf
import numpy as np

n_steps = 2 # 相当于一句话只有两个字
n_inputs = 3 # 每个字用一个 1*3 的一维向量表示
n_neurons = 5 # 也就是 hidden_size ,rnn个数为5 > 一句话长度2


X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])

# basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
basic_cell = tf.contrib.rnn.LSTMCell(num_units=n_neurons)
seq_length = tf.placeholder(tf.int32, [None])
outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32,sequence_length=seq_length)

init = tf.global_variables_initializer()
X_batch = np.array([
        # shape: 4*2*3  
        # 输入四句话  每句话两个字  每个字用1*3 的一维向量表示
        [[0, 1, 2], [9, 8, 7]], # instance 1
        [[1, 1, 1], [0, 0, 0]], # instance 2
        [[6, 7, 8], [6, 5, 4]], # instance 3
        [[9, 0, 1], [3, 2, 1]], # instance 4
    ])

seq_length_batch = np.array([2, 1, 2, 2])  # 规定每个样本的timestep的大小,如[3, 4, 5], [0, 0, 0]就只保留[3, 4, 5]的部分

with tf.Session() as sess:
    init.run()
    outputs_val, states_val = sess.run([outputs, states], feed_dict={X: X_batch, seq_length: seq_length_batch})

    # print("outputs_val.shape:", outputs_val.shape, "states_val.shape:", states_val.shape)
    print("outputs_val:", outputs_val, "states_val:", states_val)


"""  basic--rnn--cell
outputs_val: 
[
[ [ 0.16252275 -0.21838261  0.5071136  -0.8777064   0.9440784 ]
  [ 0.75742805  0.9998758   0.99818695 -0.9387361   0.9999933 ] ]

[ [ 0.07687274  0.5346504   0.45065388 -0.3090447   0.7222854 ]
  [ 0.          0.          0.          0.          0.        ] ]

[ [ 0.55537814  0.99757946  0.9980729  -0.997187    0.999999  ]
  [ 0.6576928   0.9756552   0.9704857  -0.9092402   0.999601  ] ]

[ [ 0.9929467   0.9967808   0.9811955   0.999846   -0.8645005 ]
  [ 0.28238386  0.96665514  0.96925664 -0.4429886   0.9281155 ] ]
]

states_val: 
[[ 0.75742805  0.9998758   0.99818695 -0.9387361   0.9999933 ]
 [ 0.07687274  0.5346504   0.45065388 -0.3090447   0.7222854 ]
 [ 0.6576928   0.9756552   0.9704857  -0.9092402   0.999601  ]
 [ 0.28238386  0.96665514  0.96925664 -0.4429886   0.9281155 ]]
"""

"""  lstm--rnn
outputs_val: 
[ [[-0.1515024   0.0414015  -0.02425683  0.05317516 -0.11273739]
  [-0.7172007   0.04799957 -0.00251973 -0.00678627 -0.19663692]]

 [[-0.15052094 -0.04909014 -0.06310479 -0.06192669 -0.02642662]
  [ 0.          0.          0.          0.          0.        ]]

 [[-0.5171155  -0.01278513 -0.00652955 -0.04567356 -0.44855824]
  [-0.77111876 -0.04901093 -0.02271985 -0.19334537 -0.20367831]]

 [[-0.09574735 -0.10946438 -0.019915   -0.39390936  0.02905519]
  [-0.29410264 -0.23854323 -0.14803335 -0.4029409  -0.01784849]]
] 

states_val: 
LSTMStateTuple(
	c=array(
	   [[-0.9987148 ,  0.06223609, -1.0173999 , -0.00715793, -0.20007385],
        [-0.27164963, -0.09219637, -0.19096293, -0.10495596, -0.03995872],
        [-1.2989509 , -0.06663355, -1.4104235 , -0.22700138, -0.21344885],
        [-0.41951478, -0.40118104, -1.2497861 , -0.65628904, -0.02131107]],
        dtype=float32),

    h=array(
       [[-0.7172007 ,  0.04799957, -0.00251973, -0.00678627, -0.19663692],
        [-0.15052094, -0.04909014, -0.06310479, -0.06192669, -0.02642662],
        [-0.77111876, -0.04901093, -0.02271985, -0.19334537, -0.20367831],
        [-0.29410264, -0.23854323, -0.14803335, -0.4029409 , -0.01784849]],
         dtype=float32)
)
"""

说明:就 basic--rnn--cell进行说明

        outputs是最后一层的输出,即 [batch_size,step,n_neurons] = [4,2,5] 

        states是每一层的最后一个step的输出,即三个结构为 [batch_size,n_neurons] = [4,5] 的tensor,继续观察数据,states中的最后一个array,正好是outputs的最后那个step的输出

分析:    

        tf.nn.dynamic_rnn()的time_major是默认的false,故输入X应该是一个[batch_size,step,input_size]=[4,2,3] 的tensor,注意我们这里调用的是BasicRNNCell,只有一层循环网络。

        outputs是最后一层每个step的输出,它的结构是[batch_size,step,n_neurons]=[4,2,5] 

        states是每一层的最后那个step的输出,由于本例中,我们的循环网络只有一个隐藏层,所以它就代表这一层的最后那个step的输出,因此它和step的大小是没有关系的,我们的X有4个样本组成,隐层神经元个数为n_neurons是5,因此states的结构就是[batch_size,n_neurons]=[4,5] ,最后我们观察数据,states的每条数据正好就是outputs的最后一个step的输出。

2、RNN--LSTM--GRU序列的tensorflow多层实现(basic--rnn--cell    和     basic--lstm--cell)

import tensorflow as tf
import numpy as np

 
n_steps = 2 # 步长,句子的字数
n_inputs = 3 # 输入,每个字的向量维度
n_neurons = 5 # 每一层的神经元数
n_layers = 3 # 构建的rnn层数


X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
seq_length = tf.placeholder(tf.int32, [None])
# layers = [tf.contrib.rnn.BasicRNNCell(num_units=n_neurons, activation=tf.nn.relu) for layer in range(n_layers)]
layers = [tf.contrib.rnn.BasicLSTMCell(num_units=n_neurons, activation=tf.nn.relu) for layer in range(n_layers)]

# 建造多层cell列表
multi_layer_cell = tf.contrib.rnn.MultiRNNCell(layers)

outputs, states = tf.nn.dynamic_rnn(multi_layer_cell, X, dtype=tf.float32, sequence_length=seq_length)

init = tf.global_variables_initializer()

X_batch = np.array([
        # step 0    step 1
        [[0, 1, 2], [9, 8, 7]], # instance 1
        [[3, 4, 5], [0, 0, 0]], # instance 2 (padded with zero vectors)
        [[6, 7, 8], [6, 5, 4]], # instance 3
        [[9, 0, 1], [3, 2, 1]], # instance 4
    ])

# 设置state输出的是第几步的值
seq_length_batch = np.array([2, 1, 2, 2])

with tf.Session() as sess:
    init.run()
    outputs_val, states_val = sess.run([outputs, states], feed_dict={X: X_batch, seq_length: seq_length_batch})


    print("outputs_val.shape:", outputs, "states_val.shape:", states)
    print("outputs_val:", outputs_val, "states_val:", states_val)
  
"""  basic--rnn--cell
outputs_val: 
[
 [[0.         0.         0.         0.94110525 0.52952904]
  [0.         1.2490433  0.         0.77188766 0.93011624]]

 [[0.         0.2254023  0.         1.6372365  1.0218552 ]
  [0.         0.         0.         0.         0.        ]]

 [[0.         0.52909493 0.         2.268035   1.3782274 ]
  [0.5089346  1.392092   0.7507003  0.         1.2562542 ]]

 [[0.         0.22220033 0.         0.16814911 0.        ]
  [0.         0.4996884  0.         0.6632186  0.375664  ]]
] 
states_val: 
(array([[2.9295716 , 3.2567546 , 5.9846582 , 0.        , 0.        ],
       [0.20362723, 1.506877  , 3.6396174 , 0.86225355, 0.        ],
       [5.772155  , 3.4167778 , 7.1355224 , 0.        , 0.        ],
       [0.27910823, 1.291137  , 1.3769454 , 0.        , 0.        ]],
      dtype=float32), 
 array([[0.        , 0.88036937, 0.8558484 , 2.0480504 , 0.        ],
       [1.177788  , 0.63505435, 0.7038198 , 2.1659842 , 0.        ],
       [0.        , 0.7422787 , 0.9139857 , 1.0455277 , 0.37688923],
       [0.24041918, 0.2875983 , 0.5586405 , 0.9000643 , 0.        ]],
      dtype=float32), 
 array([[0.        , 1.2490433 , 0.        , 0.77188766, 0.93011624],
       [0.        , 0.2254023 , 0.        , 1.6372365 , 1.0218552 ],
       [0.5089346 , 1.392092  , 0.7507003 , 0.        , 1.2562542 ],
       [0.        , 0.4996884 , 0.        , 0.6632186 , 0.375664  ]],
      dtype=float32)
)

"""

"""  lstm--cell
outputs_val: 
[
 [[0.0000000e+00 8.3128671e-04 3.1612897e-03 0.0000000e+00 3.4605121e-04]
  [0.0000000e+00 9.1413833e-04 6.1877295e-03 0.0000000e+00 2.5316293e-04]]

 [[0.0000000e+00 5.5302051e-04 1.2576625e-03 0.0000000e+00 1.6089274e-04]
  [0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00]]

 [[0.0000000e+00 3.9677379e-05 5.1048800e-04 0.0000000e+00 0.0000000e+00]
  [0.0000000e+00 2.8833621e-05 4.3160995e-03 0.0000000e+00 0.0000000e+00]]

 [[0.0000000e+00 4.0190206e-03 0.0000000e+00 0.0000000e+00 0.0000000e+00]
  [0.0000000e+00 2.8899033e-03 8.2549378e-03 0.0000000e+00 0.0000000e+00]]
] 

states_val: 
(LSTMStateTuple(
c=array(
      [[0.0000000e+00, 2.7703049e-03, 1.7620984e+00, 7.7233900e-04, 2.2952499e+00],
       [0.0000000e+00, 0.0000000e+00, 2.4333260e+00, 0.0000000e+00, 5.9484053e-01],
       [0.0000000e+00, 0.0000000e+00, 3.9442434e+00, 8.4212096e-03, 2.1350546e+00],
       [5.6616318e-01, 0.0000000e+00, 7.4903107e-01, 1.7679410e-01, 3.8056388e+00]], dtype=float32), 
h=array(
      [[0.0000000e+00, 2.4237809e-06, 5.5419179e-03, 3.2915897e-04, 4.1679955e-01],
       [0.0000000e+00, 0.0000000e+00, 9.2825890e-02, 0.0000000e+00, 1.3505943e-01],
       [0.0000000e+00, 0.0000000e+00, 1.1048420e-01, 3.3163740e-03, 6.4259231e-01],
       [3.3395720e-01, 0.0000000e+00, 1.4191234e-01, 5.8281716e-02, 1.8665118e+00]], dtype=float32)), 

LSTMStateTuple(
c=array(
      [[0.08610132, 0.11147856, 0.01433742, 0.06254955, 0.        ],
       [0.03402846, 0.03710118, 0.        , 0.02776909, 0.        ],
       [0.11612763, 0.17795445, 0.        , 0.07696477, 0.        ],
       [0.46006948, 0.6286925 , 0.01662218, 0.2087687 , 0.06603457]], dtype=float32), 
h=array(
      [[0.04532592, 0.0596282 , 0.0077831 , 0.03033185, 0.        ],
       [0.01739167, 0.01900657, 0.        , 0.01351981, 0.        ],
       [0.06294775, 0.09843437, 0.        , 0.03604729, 0.        ],
       [0.27324262, 0.42447668, 0.01194939, 0.09189884, 0.03275691]], dtype=float32)), 

LSTMStateTuple(
c=array(
      [[0.0000000e+00, 1.8579917e-03, 1.2345124e-02, 0.0000000e+00, 5.0845230e-04],
       [0.0000000e+00, 1.1119313e-03, 2.5110506e-03, 0.0000000e+00, 3.2198839e-04],
       [0.0000000e+00, 5.9105962e-05, 8.6243059e-03, 0.0000000e+00, 0.0000000e+00],
       [0.0000000e+00, 6.4492221e-03, 1.6449979e-02, 0.0000000e+00, 0.0000000e+00]], dtype=float32), 
h=array(
      [[0.0000000e+00, 9.1413833e-04, 6.1877295e-03, 0.0000000e+00, 2.5316293e-04],
       [0.0000000e+00, 5.5302051e-04, 1.2576625e-03, 0.0000000e+00, 1.6089274e-04],
       [0.0000000e+00, 2.8833621e-05, 4.3160995e-03, 0.0000000e+00, 0.0000000e+00],
       [0.0000000e+00, 2.8899033e-03, 8.2549378e-03, 0.0000000e+00, 0.0000000e+00]], dtype=float32)))
"""

说明:rnn--basic--cell

        outputs是最后一层的输出,即 [batch_size,step,n_neurons]=[4,2,5] 

        states是每一层的最后一个step的输出,即三个结构为 [batch_size,n_neurons]=[4,5]的tensor继续观察数据,states中的最后一个array,正好是outputs的最后那个step的输出。

说明:lstm--cell--basic

        一个LSTM cell有两个状态Ct和ht ,而不是像一个RNN cell一样只有ht 

        在tensorflow中,将一个LSTM cell的Ct 和ht 合在一起,称为LSTMStateTuple。

        因此我们的states包含三个LSTMStateTuple,每一个LSTMStateTuple表示每一层的最后一个step的输出,这个输出有两个信息,一个是ht 表示短期记忆信息,一个是Ct 表示长期记忆信息。维度都是[batch_size,n_neurons] = [4,5],states的最后一个LSTMStateTuple中的ht 就是outputs的最后一个step的输出。

3、总结以上代码流程

        num_units这个参数的大小就是LSTM输出结果的维度。例如num_units=128, 那么LSTM网络最后输出就是一个128维的向量。我们换个角度举个例子,最后再用公式来说明。

        假设在我们的训练数据中,每一个样本 x 是 28*28 维的一个矩阵,那么将这个样本的每一行当成一个输入,通过28个时间步骤展开LSTM,在每一个LSTM单元,我们输入一行维度为28的向量,如下图所示。

        那么,对每一个LSTM单元,参数 num_units=128 的话,就是每一个单元的输出为 128*1 的向量,在展开的网络维度来看,如下图所示,对于每一个输入28维的向量,LSTM单元都把它映射到128维的维度, 在下一个LSTM单元时,LSTM会接收上一个128维的输出,和新的28维的输入,处理之后再映射成一个新的128维的向量输出,就这么一直处理下去,知道网络中最后一个LSTM单元,输出一个128维的向量。

        从LSTM的公式的角度看是什么原理呢?我们先看一下LSTM的结构和公式:

         参数num_units = 128

         最后LSTM单元输出的h就是 128∗1的向量

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值