Tensorflow - Tutorial (7) : 利用 RNN/LSTM 进行手写数字识别

1. 经常使用类

class tf.contrib.rnn.BasicLSTMCell

BasicLSTMCell 是最简单的一个LSTM类。没有实现clipping,projection layer。peep-hole等一些LSTM的高级变种,仅作为一个主要的basicline结构存在,假设要使用这些高级变种,需用class tf.contrib.rnn.LSTMCell这个类。

使用方式:

lstm = rnn.BasicLSTMCell(lstm_size, forget_bias=1.0, state_is_tuple=True)

Args:

  • num_units: int, The number of units in the LSTM cell.
  • forget_bias: float, The bias added to forget gates.
  • state_is_tuple: If True, accepted and returned states are 2-tuples of the c_state and m_state. If False, they are concatenated along the column axis. The latter behavior will soon be deprecated.
  • activation: Activation function of the inner states.

说明:

  • num_units 是指一个Cell中神经元的个数,并非循环层的Cell个数。

    这里有人可能会疑问:循环层的Cell数目怎么表示?答案是通过例如以下代码中的 time_step_size确定(X_split 中划分出的arrays数量为循环层的Cell个数):

    X_split = tf.split(XR, time_step_size, 0)
  • 在随意时刻 t ,LSTM Cell会产生两个内部状态 ct和ht (关于RNN与LSTM的介绍可參考:循环神经网络与LSTM)。当state_is_tuple=True时,上面讲到的状态ct和ht 就是分开记录,放在一个二元tuple中返回,假设这个參数没有设定或设置成False,两个状态就按列连接起来返回。官方说这样的形式立即就要被deprecated了,全部我们在使用LSTM的时候要加上state_is_tuple=True。

class tf.contrib.rnn.DropoutWrapper

RNN中的dropout和cnn不同,在RNN中。时间序列方向不进行dropout,也就是说从t-1时刻的状态传递到t时刻进行计算时,这个中间不进行memory的dropout。例如以下图所看到的,Dropout仅应用于虚线方向的输入,即仅针对于上一层的输出做Dropout。

因此。我们在代码中定义完Cell之后,在Cell外部包裹上dropout,这个类叫DropoutWrapper,这样我们的Cell就有了dropout功能!

lstm = tf.nn.rnn_cell.DropoutWrapper(lstm, output_keep_prob=keep_prob)

Args:

  • cell: an RNNCell, a projection to output_size is added to it.
  • input_keep_prob: unit Tensor or float between 0 and 1, input keep probability; if it is float and 1, no input dropout will be added.
  • output_keep_prob: unit Tensor or float between 0 and 1, output keep probability; if it is float and 1, no output dropout will be added.
  • seed: (optional) integer, the randomness seed.

class tf.contrib.rnn.MultiRNNCell

假设希望整个网络的层数很多其它(比如上图表示一个两层的RNN,第一层Cell的output还要作为下一层Cell的输入),应该堆叠多个LSTM Cell,tensorflow给我们提供了MultiRNNCell,因此堆叠多层网络仅仅生成这个类就可以:

lstm = tf.nn.rnn_cell.MultiRNNCell([lstm] * num_layers, state_is_tuple=True)

2. 代码

MNIST数据集的格式与数据预处理代码 input_data.py的解说请參考 :Tutorial (2)

# -*- coding: utf-8 -*-
import tensorflow as tf
from tensorflow.contrib import rnn

import numpy as np
import input_data

# configuration
#                        O * W + b -> 10 labels for each image, O[? 28], W[28 10], B[10]
#                       ^ (O: output 28 vec from 28 vec input)
#                       |
#      +-+  +-+       +--+
#      |1|->|2|-> ... |28| time_step_size = 28
#      +-+  +-+       +--+
#       ^    ^    ...  ^
#       |    |         |
# img1:[28] [28]  ... [28]
# img2:[28] [28]  ... [28]
# img3:[28] [28]  ... [28]
# ...
# img128 or img256 (batch_size or test_size 256)
#      each input size = input_vec_size=lstm_size=28

# configuration variables
input_vec_size = lstm_size = 28 # 输入向量的维度
time_step_size = 28 # 循环层长度

batch_size = 128
test_size = 256

def init_weights(shape):
    return tf.Variable(tf.random_normal(shape, stddev=0.01))

def model(X, W, B, lstm_size):
    # X, input shape: (batch_size, time_step_size, input_vec_size)
    # XT shape: (time_step_size, batch_size, input_vec_size)
    XT = tf.transpose(X, [1, 0, 2])  # permute time_step_size and batch_size,[28, 128, 28]

    # XR shape: (time_step_size * batch_size, input_vec_size)
    XR = tf.reshape(XT, [-1, lstm_size]) # each row has input for each lstm cell (lstm_size=input_vec_size)

    # Each array shape: (batch_size, input_vec_size)
    X_split = tf.split(XR, time_step_size, 0) # split them to time_step_size (28 arrays),shape = [(128, 28),(128, 28)...]

    # Make lstm with lstm_size (each input vector size). num_units=lstm_size; forget_bias=1.0
    lstm = rnn.BasicLSTMCell(lstm_size, forget_bias=1.0, state_is_tuple=True)

    # Get lstm cell output, time_step_size (28) arrays with lstm_size output: (batch_size, lstm_size)
    # rnn..static_rnn()的输出相应于每个timestep。假设仅仅关心最后一步的输出,取outputs[-1]就可以
    outputs, _states = rnn.static_rnn(lstm, X_split, dtype=tf.float32)  # 时间序列上每个Cell的输出:[... shape=(128, 28)..]

    # Linear activation
    # Get the last output
    return tf.matmul(outputs[-1], W) + B, lstm.state_size # State size to initialize the stat

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) # 读取数据

# mnist.train.images是一个55000 * 784维的矩阵, mnist.train.labels是一个55000 * 10维的矩阵
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labels

# 将每张图用一个28x28的矩阵表示,(55000,28,28,1)
trX = trX.reshape(-1, 28, 28)
teX = teX.reshape(-1, 28, 28) 

X = tf.placeholder("float", [None, 28, 28])
Y = tf.placeholder("float", [None, 10])

# get lstm_size and output 10 labels
W = init_weights([lstm_size, 10])  # 输出层权重矩阵28×10
B = init_weights([10])  # 输出层bais

py_x, state_size = model(X, W, B, lstm_size)

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=py_x, labels=Y))
train_op = tf.train.RMSPropOptimizer(0.001, 0.9).minimize(cost)
predict_op = tf.argmax(py_x, 1)

session_conf = tf.ConfigProto()
session_conf.gpu_options.allow_growth = True

# Launch the graph in a session
with tf.Session(config=session_conf) as sess:
    # you need to initialize all variables
    tf.global_variables_initializer().run()

    for i in range(100):
        for start, end in zip(range(0, len(trX), batch_size), range(batch_size, len(trX)+1, batch_size)):
            sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end]})

        test_indices = np.arange(len(teX))  # Get A Test Batch
        np.random.shuffle(test_indices)
        test_indices = test_indices[0:test_size]

        print(i, np.mean(np.argmax(teY[test_indices], axis=1) ==
                         sess.run(predict_op, feed_dict={X: teX[test_indices]})))

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMDA4OTQ0NA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="500" height="300" alt="图 1">

3. 參考资料

时间: 2024-10-12 08:57:35

Tensorflow - Tutorial (7) : 利用 RNN/LSTM 进行手写数字识别的相关文章

第三节,TensorFlow 使用CNN实现手写数字识别

上一节,我们已经讲解了使用全连接网络实现手写数字识别,其正确率大概能达到98%,着一节我们使用卷积神经网络来实现手写数字识别, 其准确率可以超过99%,程序主要包括以下几块内容 [1]: 导入数据,即测试集和验证集 [2]: 引入 tensorflow 启动InteractiveSession(比session更灵活) [3]: 定义两个初始化w和b的函数,方便后续操作 [4]: 定义卷积和池化函数,这里卷积采用padding,使得 输入输出图像一样大,池化采取2x2,那么就是4格变一格 [5]

手写数字识别——利用keras高层API快速搭建并优化网络模型

在<手写数字识别——手动搭建全连接层>一文中,我们通过机器学习的基本公式构建出了一个网络模型,其实现过程毫无疑问是过于复杂了——不得不考虑诸如数据类型匹配.梯度计算.准确度的统计等问题,但是这样的实践对机器学习的理解是大有裨益的.在大多数情况下,我们还是希望能多简单就多简单地去搭建网络模型,这同时也算对得起TensorFlow这个强大的工具了.本节,还是以手写数据集MNIST为例,利用TensorFlow2.0的keras高层API重现之前的网络. 一.数据的导入与预处理 关于这个过程,与上节

Tensorflow实践 mnist手写数字识别

minst数据集                                         tensorflow的文档中就自带了mnist手写数字识别的例子,是一个很经典也比较简单的入门tensorflow的例子,非常值得自己动手亲自实践一下.由于我用的不是tensorflow中自带的mnist数据集,而是从kaggle的网站下载下来的,数据集有些不太一样,所以直接按照tensorflow官方文档上的参数训练的话还是踩了一些坑,特此记录. 首先从kaggle网站下载mnist数据集,一份是

tensorflow 基础学习五:MNIST手写数字识别

MNIST数据集介绍: from tensorflow.examples.tutorials.mnist import input_data # 载入MNIST数据集,如果指定地址下没有已经下载好的数据,tensorflow会自动下载数据 mnist=input_data.read_data_sets('.',one_hot=True) # 打印 Training data size:55000. print("Training data size: {}".format(mnist.

第二节,TensorFlow 使用前馈神经网络实现手写数字识别

一 感知器      感知器学习笔记:https://blog.csdn.net/liyuanbhu/article/details/51622695      感知器(Perceptron)是二分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别,取+1和-1.这种算法的局限性很大: 只能将数据分为 2 类 数据必须是线性可分的 虽然有这些局限,但是感知器是 ANN 和 SVM 的基础,理解了感知器的原理,对学习ANN 和 SVM 会有帮助,所以还是值得花些时间的. 感知器可以表示为

Tensorflow实战 手写数字识别(Tensorboard可视化)

一.前言 为了更好的理解Neural Network,本文使用Tensorflow实现一个最简单的神经网络,然后使用MNIST数据集进行测试.同时使用Tensorboard对训练过程进行可视化,算是打响学习Tensorflow的第一枪啦. 看本文之前,希望你已经具备机器学习和深度学习基础. 机器学习基础可以看我的系列博文: https://cuijiahua.com/blog/ml/ 深度学习基础可以看吴恩达老师的公开课: http://mooc.study.163.com/smartSpec/

利用手写数字识别项目详细描述BP深度神经网络的权重学习

本篇文章是针对学习<深度学习入门>(由日本学者斋藤康毅所著陆羽杰所译)中关于神经网络的学习一章来总结归纳一些收获. 本书提出神经网络的学习分四步:1.mini-batch 2.计算梯度 3.更新参数 4.重复前面步骤 1.从识别手写数字项目学习神经网络 所谓“从数据中学习”是指 可以由数据#自动决定权重#.当解决较为简单的问题,使用简单的神经网络时,网络里的权重可以人为的手动设置,去提取输入信息中特定的特征.但是在实际的神经网络中,参数往往是成千上万,甚至可能上亿的权重,这个时候人为手动设置是

使用AI算法进行手写数字识别

人工智能 ??人工智能(Artificial Intelligence,简称AI)一词最初是在1956年Dartmouth学会上提出的,从那以后,研究者们发展了众多理论和原理,人工智能的概念也随之扩展.由于人工智能的研究是高度技术性和专业的,各分支领域都是深入且各不相通的,因而涉及范围极广 . 人工智能的核心问题包括建构能够跟人类似甚至超越人类的推理.知识.学习.交流.感知.使用工具和操控机械的能力等,当前人工智能已经有了初步成果,甚至在一些影像识别.语言分析.棋类游戏等等单方面的能力达到了超越

C#中调用Matlab人工神经网络算法实现手写数字识别

手写数字识别实现 设计技术参数:通过由数字构成的图像,自动实现几个不同数字的识别,设计识别方法,有较高的识别率 关键字:二值化  投影  矩阵  目标定位  Matlab 手写数字图像识别简介: 手写阿拉伯数字识别是图像内容识别中较为简单的一个应用领域,原因有被识别的模式数较少(只有0到9,10个阿拉伯数字).阿拉伯数字笔画少并且简单等.手写阿拉伯数字的识别采用的方法相对于人脸识别.汉字识别等应用领域来说可以采用更为灵活的方法,例如基于规则的方法.基于有限状态自动机的方法.基于统计的方法和基于神