【深度学习】循环神经网络(RNN)的tensorflow实现


循环神经网络又被成为时间递归神经网络(Recurrent Neural Networks),传统神经网络,每一个时间步隐含层神经元之间没有连接。但RNN中每一个时间步的隐含层输入由当前时间步的输入和上一时间步的隐含层输出共同决定,因此历史数据的影响不会消失,而是会继续存活。

一、循环神经网络原理

1.1、RNN的网络结构

RNN网络结构如下图所示
在这里插入图片描述
每一个RNN cell都包括输入部分,隐含层部分和输出部分。RNN cell的数量等于时间步数量,前一个RNN cell的隐含层部分连接到下一个RNN cell的隐含层。RNN cell的输出连接到CTC层,然后输出预测数据。

每一时间步的RNN cell的具体结构图如下所示:
在这里插入图片描述
如图所示,第 t t 时间步对应的RNN cell的网络结构。
输入层:输入层节点数为输入样本特征维度。输入为 X t = { x t 1 , x t 2 ,   , x t n } {X_t} = \left\{ {x_t^1,x_t^2, \cdots ,x_t^n} \right\} ,就是说输入层节点数为 n n

隐含层:隐含层节点数可以自己设定,上图中隐含层节点数为 n n 。隐含层输入数据为:
S t = X t U + S t 1 W {S_t} = {X_t} \cdot U + {S_{t - 1}} \cdot W

输出层:上图中输出层节点数为 r r ,输出层输入为:
O t = S t V {O_t} = {S_t} \cdot V

W W 为连接相邻时间步隐含层的权重矩阵,维度为 m × m m×m U U 为连接输入层与隐含层的权重矩阵,维度为 n × m n×m V V 为连接隐含层到输出层的权重矩阵,维度为 m × r m×r

1.2、RNN的特点

(1)、不像传统的深度神经网络,在不同的层使用不同的参数,循环神经网络在所有步骤中共享参数(U、V、W)。这个反映一个事实,我们在每一步上执行相同的任务,仅仅是输入不同。这个机制极大减少了我们需要学习的参数的数量(参考资料【1】)。
(2)、RNN每一步都有输出,但是根据任务的不同,这个并不是必须的。任务的需要,可以通过调整RNN的输出与CTC层之间的连接实现。

1.3、RNN的训练

循环神经网络的训练类似于传统神经网络的训练,也使用反向传播算法。因为循环神经网络在所有时刻的参数是共享的,但是每个输出的梯度不仅依赖当前时刻的计算,还依赖之前时刻的计算,所以RNN的训练采用BPTT(Backpropagation Through Time)方法(参考资料【1,2】)。

二、循环神经网络的tensorflow实现

本博文使用tensorflow实现RNN对sine函数的回归。
python代码地址:https://github.com/shiluqiang/RNN_regression

import numpy as np
import tensorflow as tf
import random

tf.reset_default_graph() ##用于清除默认图形堆栈并重置全局默认图形

def build_data(feature_len):  #构造2000个序列长度为n的正弦序列,前1500个作为训练集,后500个作为测试集
    xs=[]
    ys=[]
    for i in range(2000):
        k=random.uniform(1,50)
        x=[[np.sin(k + j)] for j in range(0,feature_len)]
        y=[np.sin(k + feature_len)]
        xs.append(x)
        ys.append(y)
    train_x=np.array(xs[0:1500])
    train_y=np.array(ys[0:1500])
    test_x=np.array(xs[1500:])
    test_y=np.array(ys[1500:])
    return train_x,train_y,test_x,test_y

class RNN_Sine():
    '''定义RNN_Sine类
    '''
    def __init__(self,n_steps,n_inputs,batch_size,hidden_size,input_train_feature,input_train_label,input_test_feature,input_test_label,n_output):
        self.batch_size = batch_size # RNN模型中RNNcell的个数
        self.hidden_size = hidden_size # RNN cell 隐含层节点数
        self.n_steps = n_steps #RNN每个节点输入特征的长度
        self.n_inputs = n_inputs #特征中每个元素的长度
        self.input_train_feature = input_train_feature #数据特征
        self.input_train_label = input_train_label #数据标签
        self.input_test_feature = input_test_feature
        self.input_test_label = input_test_label
        self.n_output = n_output #CTC层输出节点数
    
    def seq_predict_model(self,X,W,b):
        ## 初始化RNN单元
        X = tf.transpose(X,[1,0,2])  ##交换batch_size和n_steps
        X = tf.reshape(X,[-1,self.n_inputs]) ##(n_steps*batch_size,n_inputs)  
        X = tf.split(X,self.n_steps,0)  ## n_steps * (batch_size, n_inputs)
        rnn_cell = tf.contrib.rnn.BasicRNNCell(num_units = self.batch_size)
        init_state = rnn_cell.zero_state(self.batch_size,dtype = tf.float32)
        outputs,states = tf.contrib.rnn.static_rnn(rnn_cell,X,initial_state = init_state) ## outputs -- [n_steps,batch_size,hidden_size]
        y_pred = tf.matmul(outputs[-1],W) + b
        return y_pred
        
    def fit(self):
        '''RNN模型训练
        '''
        #1.声明输入输出的占位符
        X = tf.placeholder('float',[None,self.n_steps,self.n_inputs],name = 'X')
        Y = tf.placeholder('float',[None,self.n_output],name = 'Y')
        # 2.输出层参数
        W = tf.Variable(tf.random_normal([self.hidden_size,self.n_output]))
        b = tf.Variable(tf.random_normal([self.n_output]))
        # 3.构造RNN计算图
        y_pred = self.seq_predict_model(X,W,b)
        # 4.声明代价函数和优化算法
        loss = tf.sqrt(tf.square(tf.subtract(Y,y_pred)))
        train_op = tf.train.GradientDescentOptimizer(0.001).minimize(loss)
        # 5.构造迭代过程并预测结果
        trX = self.input_train_feature
        trY = self.input_train_label
        teX = self.input_test_feature
        teY = self.input_test_label
        
        with tf.Session() as sess:
            tf.initialize_all_variables().run()
            for i in range(50):
                for end in range(batch_size,len(trX),batch_size):
                    begin = end - batch_size
                    x_value = trX[begin:end]
                    y_value = trY[begin:end]
                    #通过session.run接口触发执行
                    sess.run(train_op,feed_dict={X:x_value,Y:y_value})
                    test_indices=np.arange(len(teX)) #在训练的过程中开始测试
                    np.random.shuffle(test_indices)
                    test_indices=test_indices[0:self.batch_size]
                    x_value=teX[test_indices]
                    y_value=teY[test_indices]
                    val_loss=np.mean(sess.run(loss,feed_dict={X:x_value,Y:y_value}))    #使用均方差作为代价函数
                print ('Run %s'%i,val_loss)

                    
if __name__ == '__main__':
    print('--------------------1. Parameters Setting--------------------')
    n_steps = 10 ##每个RNN cell输入特征长度
    n_inputs = 1 ##特征中每个元素的大小
    batch_size = 10  ##rnn网络的节点数
    hidden_size = 10 ##RNN cell中隐含层节点数
    n_output = 1       
    print('-----------------------2. Load Data---------------------------')
    input_train_feature,input_train_label,input_test_feature,input_test_label = build_data(n_steps)
    print('-------------------3.Model Training------------------')
    rnn = RNN_Sine(n_steps,n_inputs,batch_size,hidden_size,input_train_feature,input_train_label,input_test_feature,input_test_label,n_output)
    rnn.fit()

参考资料

1、https://blog.csdn.net/gzj_1101/article/details/79189286
2、https://blog.csdn.net/zhaojc1995/article/details/80572098

猜你喜欢

转载自blog.csdn.net/Luqiang_Shi/article/details/85160982