[TensorFlow深度学习入门]实战十一·用双向BiRNN(LSTM)做手写数字识别准确率99%+

[TensorFlow深度学习入门]实战十一·用双向BiRNN(LSTM)做手写数字识别准确率99%+

• 首先我们先熟悉BiRNN

tf.nn.static_bidirectional_rnn 函数原型

```tf.nn.static_bidirectional_rnn(
cell_fw,
cell_bw,
inputs,
initial_state_fw=None,
initial_state_bw=None,
dtype=None,
sequence_length=None,
scope=None
)```

cell_fw:用于前向传播的RNNCell.

cell_bw: 用于反向传播的RNNCell.

inputs: A length T list of inputs, each a tensor of shape [batch_size, input_size], or a nested tuple of such elements.（输入 数据为list类型，list中元素为Tensor,每个Tensor的shape为[batch_size, input_size],如有batch_size个文档，每个文档的单词数量为1000，每个单词的词向量维度为100，则该inputs为list(1000tensor(batch_size100))）

initial_state_fw: (optional)前向RNN的初始状态。 This must be a tensor of appropriate type and shape [batch_size, cell_fw.state_size]. If cell_fw.state_size is a tuple, this should be a tuple of tensors having shapes [batch_size, s] for s in cell_fw.state_size.。

initial_state_bw: (optional) Same as for initial_state_fw, but using the corresponding properties of cell_bw.

dtype: (optional) The data type for the initial state. Required if either of the initial states are not provided.

sequence_length: (optional) An int32/int64 vector, size [batch_size], containing the actual lengths for each of the sequences.

scope: VariableScope for the created subgraph; defaults to “bidirectional_rnn”

A tuple (outputs, output_state_fw, output_state_bw) where: outputs is a length T list of outputs (one for each input), which are depth-concatenated forward and backward outputs. output_state_fw is the final state of the forward rnn. output_state_bw is the final state of the backward rnn.

• 代码部分

```import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
import time
import tensorflow as tf
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import cv2

from  tensorflow.examples.tutorials.mnist import  input_data

train_rate=0.002
train_step=1001
batch_size=1000
display_step=10

frame_size=28
sequence_length=28
hidden_num=128
n_classes=10

"""其中：
train_rate是学习速率，这是一个超参数，目前由经验设置的，当然也可以自适应。

batch_size:每批样本数，rnn也可以使用随机梯度下降进行训练，一批批的灌数据进去，而不是每一次把整个数据集都灌进去。

sequence_size:每个样本序列的长度。因为我们希望把一个28x28的图片当做一个序列输入到rnn进行训练，所以我们需要对图片进行序列化。一种最方便的方法就是我们认为行与行之间存在某些关系，于是把图片的每一行取出来当做序列的一个维度。所以这里sequence_size就是设置为28。

frame_size:序列里面每一个分量的大小。因为每个分量都是一行像素，而一行像素有28个像素点。所以frame_size为28。

hidden_num：隐层个数，经验设置为5

n_classes：类别数，10个数字就是设置为10咯"""

x=tf.placeholder(dtype=tf.float32,shape=[None,sequence_length*frame_size],name="inputx")

y=tf.placeholder(dtype=tf.float32,shape=[None,n_classes],name="expected_y")

weights=tf.Variable(tf.random_normal(shape=[2*hidden_num,n_classes]))#因为是双向，输出形状为（-1，2*hidden_num）
bias=tf.Variable(tf.fill([n_classes],0.1))
"""注意：weights是整个网络的最后一层，它的形状为hidden_numXn_class,至于为什么是这个形状，我们下面来说。
bias最后一层的偏置"""

#定义RNN网络
def RNN(x,weights,bias):
x = tf.reshape(x,shape=[-1,sequence_length,frame_size])
#把输入转换为static_bidirectional_rnn接受的形状：输入 数据为list类型，list中元素为Tensor,每个Tensor的shape为[batch_size, input_size]
#先把数据x 的第一维度与第二维度互换
x = tf.transpose(x,[1,0,2])
#变形为（-1，frame_size）形状
x = tf.reshape(x,shape=[-1,frame_size])
#拆分为list，list中元素为Tensor,每个Tensor的shape为[batch_size, input_size]
x = tf.split(x,sequence_length)

lstm_fw_cell = tf.nn.rnn_cell.BasicLSTMCell(hidden_num) # 正向RNN,输出神经元数量为128

lstm_bw_cell = tf.nn.rnn_cell.BasicLSTMCell(hidden_num) # 反向RNN,输出神经元数量为128

output, fw_state, bw_state = tf.nn.static_bidirectional_rnn(lstm_fw_cell, lstm_bw_cell, x, dtype=tf.float32)
print(len(output))
#生成hidden_num个隐层的RNN网络
#这是一个深度RNN网络,对于每一个长度为sequence_length的序列[x1,x2,x3,...,]的每一个xi,都会在深度方向跑一遍RNN,每一个都会被这hidden_num个隐层单元处理。
h = tf.matmul(output[int(sequence_length/2)],weights)+bias#output长度为sequence_length，我们取中间位置的输出，双向的结果都可以兼顾到
#此时output就是一个[batch_size,sequence_length,rnn_cell.output_size]形状的tensor
return (h)
#我们取出最后每一个序列的最后一个分量的输出output[:,-1,:],它的形状为[batch_size,rnn_cell.output_size]也就是:[batch_size,hidden_num]所以它可以和weights相乘。这就是2.5中weights的形状初始化为[hidden_num,n_classes]的原因。然后再经softmax归一化。

predy=RNN(x,weights,bias)

cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=predy,labels=y))

correct_pred=tf.equal(tf.argmax(predy,1),tf.argmax(y,1))
accuracy=tf.reduce_mean(tf.to_float(correct_pred))

testx,testy=mnist.test.next_batch(batch_size)

saver=tf.train.Saver()

with tf.Session() as sess:
srun = sess.run
init =  tf.global_variables_initializer()
srun(init)
for t in range(train_step):
batch_x,batch_y=mnist.train.next_batch(batch_size)
_cost_val,_ = srun([cost,opt],{x:batch_x,y:batch_y})
if(t%display_step==0):
accuracy_val, cost_val = srun([accuracy,cost],{x:testx,y:testy})
print(t,cost_val,accuracy_val)

saver.save(sess,'./2RNN/ckpt1/mnist1.ckpt',global_step=train_step)```
• 运行结果
```0 2.531533 0.168
10 0.8894601 0.699
20 0.6328424 0.796
30 0.46291852 0.856
...
970 0.022114469 0.992
980 0.03192995 0.99
990 0.021659942 0.988
1000 0.023274422 0.992```
• 结果分析

0 条评论

• [TensorFlow深度学习入门]实战五·用RNN(LSTM)做手写数字识别准确率98%+

参考博客地址，修复了一个小Bug，收敛速度和准确率都略微提升。使用此模型在Kaggle比赛准确率98%+

• [TensorFlow深度学习入门]实战七·简便方法实现TensorFlow模型参数保存与加载（ckpt方式）

TensorFlow模型训练的好网络参数如果想重复高效利用，模型参数保存与加载是必须掌握的模块。本文提供一种简单容易理解的方式来实现上述功能。参考博客地址 备...

• [TensorFlow深度学习入门]实战九·用CNN做科赛网TibetanMNIST藏文手写数字数据集准确率98%+

我们在博文，使用CNN做Kaggle比赛手写数字识别准确率99%+，在此基础之上，我们进行对科赛网TibetanMNIST藏文手写数字数据集训练，来验证网络的正...

• 【Linux】把web项目部署到Linux服务器上

打开eclipse，在已经完成的web项目上面点击右键，选择export，然后选择导出成war包

• CVE-2018-8781：linux内核mmap整数溢出漏洞分析

sudo mknod /dev/MWR_DEVICE c 200 0 sudo chmod 777 /dev/MWR_DEVICE

• 在TensorFlow 2中实现完全卷积网络（FCN）

卷积神经网络（CNN）非常适合计算机视觉任务。使用对大型图像集（如ImageNet，COCO等）进行训练的预训练模型，可以快速使这些体系结构专业化，以适合独特数...

• python platform和pwd模

('Linux', 'gitlab.test.com', '3.10.0-327.el7.x86_64', '#1 SMP Thu Nov 19 22:10:5...

• 虚拟现实有助于改善语言实验效果

据德国马普学会网站2016年1月27日报道，该研究机构的科学家们正在使用虚拟化身研究人们的行为交互方式，这种方法能够很精确地研究人们在交谈时是如何互动的。 人们...