RNN之tensorflow-BasicLSTMCell+mnist手写字符数据集分类+github完整代码

RNN之tensorflow-BasicLSTMCell+mnist手写字符数据集分类+github完整代码

一、原理部分

关于RNN的详细介绍,请看博文
详解循环神经网络RNN原理+tensorflow实现
关于LSTM:
我们知道RNN包含了之前任意时刻的输入,但是这样会造成梯度消失或者梯度爆炸,同时不能够很好地学习特征,因此采用LSTM
(1)对输入(x,h)控制(通过乘以sigmod后[0-1]的小数);
(2)控制之前“积累”状态需要遗忘的程度;
(3)控制当前时间步是否需要输出。
来达到更加灵活的控制。
框图如下:
在这里插入图片描述
详见如下两篇博文,讲述很详细。
BasicLSTMCell中num_units参数解释
下面这篇文章对tf.nn.rnn_cell.BasicLSTMCell类中关于如何得到上图所示变量的过程解释很清楚。
深度学习笔记2:关于LSTM神经网络输入输出的理解

二、代码详解

1、代码分析

一共包含两个文件
一个是RNN_LSTM_Classfication.py
一个是simple_RNN.py

RNN_LSTM_Classfication.py

头文件以及数据载入,数据载入解释见博文tensorflow运行卷积神经网络的一些ERROR

from tensorflow import keras, Session, transpose, global_variables_initializer
from modular.simple_RNN import simple_RNN
from modular.compute_accuracy import compute_accuracy
from modular.random_choose import corresponding_choose
(train_x_image, train_y), (test_x_image, test_y) = keras.datasets.mnist.load_data(path='/home/xiaoshumiao/.keras/datasets/mnist.npz')
train_y = keras.utils.to_categorical(train_y)
test_y=keras.utils.to_categorical(test_y)

参数设置

epochs = 1000
n_classes = 10
batch_size = 200#number
chunk_size = 28
n_chunk = 28
rnn_size = 128#the lenth of a hidden_neural_layer or the number of hidden_neural
learning_rate = 0.001

实例一个自己定义的RNN类

rnn = simple_RNN(chunk_size, n_chunk, rnn_size, batch_size, n_classes, learning_rate)

Sessin()

with Session() as sess:
    sess.run(global_variables_initializer())
    for i in range(epochs):
        train_data = corresponding_choose(train_x_image, batch_size, m=0)
        train_x_betch = train_data.row_2(train_x_image) / 255.
        train_y_betch = train_data.row(train_y)
        sess.run(rnn.train,feed_dict={rnn.X:train_x_betch,rnn.y:train_y_betch})
        if i % 20 ==0:
            test_data = corresponding_choose(test_x_image, 200, m=0)
            test_x_betch = test_data.row_2(test_x_image) / 255.
            test_y_betch = test_data.row(test_y)
            b = sess.run(rnn.result, feed_dict={rnn.X: test_x_betch})
            c = sess.run(compute_accuracy(b, transpose(test_y_betch)))
            print(c)

simple_RNN.py

头文件导入

from tensorflow import placeholder,float32,transpose, nn, reduce_mean, multiply, log, reduce_sum, train
from add_layer import add_layer
from tensorflow.python.ops.rnn import dynamic_rnn

数据输入

class simple_RNN(object):
    def __init__(self,chunk_size,n_chunk,hidden_chunk_size, batch_size,  n_class, learning_rate):
        self.X = placeholder(float32,[None,n_chunk,chunk_size])#200,28,28
        self.y = placeholder(float32,[None, n_class])

定义一个cell
初始化状态值(结构见上面的两篇链接)
构建rnn计算图并得到最后一个时间步输出。

self.LSTM_cell = nn.rnn_cell.BasicLSTMCell(hidden_chunk_size, forget_bias=1.0, state_is_tuple=True)
self.init_state = self.LSTM_cell.zero_state(batch_size, float32)
self.output, self.states = dynamic_rnn(self.LSTM_cell, self.X, initial_state=self.init_state, dtype=float32)

得到输出后连接一层全连接层,得到10维输出。

self.result = add_layer(transpose(self.states[1]), hidden_chunk_size, n_class, activation_function=nn.softmax)

用训练全连接网络的方法训练全连接层的输出

self.loss = reduce_mean(-reduce_sum(multiply(transpose(self.y),log(self.result)),reduction_indices=[0]))
self.train = train.AdamOptimizer(learning_rate).minimize(self.loss)

2、问题解决

(1)、
第一个问题也是困扰很久的问题,因为我是根据莫烦python学习的RNN,根据莫烦老师的讲解,我们先手动计算得到因层128维向量,然后再带入cell。但是我查阅博文发现,tf.nn.rnn_cell.BasicLSTMCell函数中的num_units就是定义的隐层神经元个数(着这因层输出向量的维数),而在构建RNN计算图dynamic_rnn的时候,我们需要输入的却是原始数据。同时参考上面链接的两篇博客,LSTM的输入是原始数据和上一时刻的隐含神经元输出。所以综上所述,我们不需要实现手动计算隐层神经元的结果。
同时,在tf.nn.rnn_cell.BasicLSTMCell中可以找到
在这里插入图片描述
因此,不需要对输入数据做处理。

(2)、

test_data = corresponding_choose(test_x_image, 200, m=0)

一开始测试的时候样本batch_size和训练样本不符合,所以也设置200,或者再改都可以。

(3)、
初始化变量的时候,不要用别的,就老老实实用
global_variables_initializer()

三、实验结果+github

实现结果如下:
在这里插入图片描述
总体来看实验结果还很可观的。

完整代码(调用的其他自己写的库文件),以及一些其他程序注释,需要注意的地方,都一并放在github上,有需要的可以去看一下。

https://github.com/wangjunhe8127/tensorflow-BasicLSTMCell-mnist

May the force be with you!

发布了32 篇原创文章 · 获赞 7 · 访问量 2158

猜你喜欢

转载自blog.csdn.net/def_init_myself/article/details/105372941
今日推荐