TensorFlow1 :RNN实现mnist手写体数字识别

网上tensorflow框架下RNN例程,要么过于简单要么过于复杂。本文采用mnist的60000万训练集、10000测试集构建、测试可以识别手写体数字的RNN网络,并达到不错效果(98%左右)。本文将分步讲解代码,提供测试训练集、整体代码。

可以看到准确还是挺高的,损失也挺低。图中是迭代(批)次与准确率曲线
RNN过程
要理解RNN网络的输入输出形式、时间步概念

训练测试集
1、tensorflow中可以自动下载
2、本文直接加载我已预处理的本地已有数据集,可以直接下载预处理后的mnist训练测试集(免费),数据集预处理也是构建神经网络重要一步。(测试集形式60000x784(28乘28为784)和60000x10(10个标签对应的概率),原来为60000x785)。测试集同。
训练集:手写体数字图片(28×28)与对应标签0~9。
RNN网络结构:many to one
输入:每个时间步输入图片的一行(或一列)28个像素组成的向量,
时间步总数𝑇_𝑥为行数(或列数)。
输出:第𝑇_𝑥个时间步输出10维向量,对应0~9十个数字的概率
代码说明
(1)首先导入tensorflow、numpy、绘图库

import tensorflow as tf
import numpy as np
np.set_printoptions(suppress=True)
import matplotlib.pyplot as plt

(2)参数设置

learning_rate = 0.001
batch_size = 100
batch_size_1 = 1280
n_input = 28 # MNIST data input (img shape: 28*28)
n_steps = 28 # timesteps
n_hidden = 130 # hidden layer num of features
n_classes = 10 # MNIST total classes (0-9 digits)
bb = 2500

其中:
learning_rate是学习速率,设置为0.001,不能太高

batch_size、batch_size_1:每批样本数,rnn也可以使用随机梯度下降进行训练,一批批的灌数据进去,而不是每一次把整个数据集都灌进去。batch_size = 100,batch_size_1 = 1280。测试时一次输入100个,训练时一次输入1280个

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

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

hidden_num:隐层节点个数,设置为130

n_classes:类别数,10个数字就是设置为10

bb:迭代次数,即进行几个批训练

(3)导入训练测试集

#导入训练集
x_1 = np.loadtxt(open("mnist/mnist_train_x.csv",'rb'),delimiter=",",skiprows=0) /255
y_1 = np.loadtxt(open("mnist/mnist_train_y.csv",'rb'),delimiter=",",skiprows=0) 


#导入测试集并放入3维矩阵
x_2 = np.loadtxt(open("mnist/mnist_test_x.csv",'rb'),delimiter=",",skiprows=0) /255
y_2 = np.loadtxt(open("mnist/mnist_test_y.csv",'rb'),delimiter=",",skiprows=0) 

(4)定义输入输出

# 开始我们先创建两个占位符placeholder
x = tf.placeholder("float64", [None, n_steps, n_input])
y = tf.placeholder("float64", [None, n_classes])

使用两个占位符
x是输入占位符,希望输入的时候把每个图像都组成28*28的向量。

y是输出,每个输出是一个长度为10的向量,10个数字的概率

state_size=None,output_size=None先设为未知大小。
前者是隐层的大小,后者是输出的大小。比如我们通常是将一个batch送入模型计算,设输入数据的形状为(batch_size, input_size=[n_steps, n_input])=[None, n_steps, n_input],那么计算时得到的隐层状态就是(batch_size, state_size),输出就是(batch_size, output_size)。

(5)定义权值和偏置

# Define weights  
weights = {'wih': tf.Variable(tf.random_normal([n_input, n_hidden],dtype=tf.float64)), 
         'who': tf.Variable(tf.random_normal([n_hidden, n_classes],dtype=tf.float64))}
biases = {'bih': tf.Variable(tf.random_normal([n_hidden],dtype=tf.float64)),
    'bho': tf.Variable(tf.random_normal([n_classes],dtype=tf.float64))}

wih 输入与隐层的权值,who隐层与输出的权值
bih 输入与隐层的偏置,w=bho隐层与输出的偏置

(6)定义RNN网络
tensorflow中实现了以下模块 :tf.nn.rnn_cell,直接调用就可以了

如果要学习TensorFlow中的RNN,第一站应该就是去了解“RNNCell”,它是TensorFlow中实现RNN的基本单元,每个RNNCell都有一个call方法,使用方式是:(output, next_state) = call(input, state)。每调用一次RNNCell的call方法,就相当于在时间上“推进了一步”,这就是RNNCell的基本功能。

多步时用outputs, final_states = tf.nn.dynamic_rnn(rnn_cell,x,dtype=tf.float64)

在代码实现上,RNNCell只是一个抽象类,我们用的时候都是用的它的两个子类BasicRNNCell和BasicLSTMCell。顾名思义,前者是RNN的基础类,后者是LSTM的基础类。

下面举个例子

import tensorflow as tf

batch_size = 32 # batch大小
input_size = 100 # 输入向量xt维度
state_size = 128 # 隐藏状态ht维度

# 创建BasicRNNCell, num_inits是state_size
cell = tf.nn.rnn_cell.BasicRNNCell(num_units = state_size) 
print cell.state_size

# 初始化状态 shape = (batch_size, state_size)
h0 = cell.zero_state(batch_size, tf.float32)

# 进行一次计算,得到output和h1
output, h1 = cell(inputs,h0)
print h1.shape, output.shape
------------------------------------------------------------------------------
输出结果
128
(32, 128) (32, 128)

(7)计算预计输出、准确率

correct_pred=tf.equal(tf.argmax(tf.matmul(final_states,weights['who']) + biases['bho'],1),tf.argmax(y,1))

获得以final_states为输入,weights,bias为偏置的概率分布。
返回结果是[batch_size,n_classes]的形状,表示batch里面的每个样本的预测输出。
(8)计算残差、损失:

cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=tf.matmul(final_states,weights['who'])+ biases['bho'],labels=y))

使用交叉熵
(9)计算准确率

accuracy=tf.reduce_mean(tf.cast(correct_pred,"float")

(10)启动sess、初始化变量:
sess=tf.Session()
sess.run(tf.initialize_all_variables())
(11)循环训练、绘图

a = np.zeros(shape=(bb,1))
for i in range(bb):
  x_3,y_3 = next_batch(x_1,y_1,batch_size_1)
  x_3 = np.reshape(x_3,[batch_size_1,28,28])
  x_4,y_4 = next_batch(x_2,y_2,batch_size)
  x_4 = np.reshape(x_4,[batch_size,28,28])
  sess.run(train, feed_dict={x: x_3, y: y_3})
  loss =  sess.run(cost, feed_dict={x: x_3, y: y_3})
  acc = sess.run(accuracy,feed_dict={x:x_4,y:y_4})
  a[i]=acc
  print(acc,loss) 
  pass
x = np.linspace(0, 1, bb)
plt.plot(x*bb, a)
plt.show()

整体代码

# (C)pengchengIT 2021
import tensorflow as tf
import numpy as np
np.set_printoptions(suppress=True)
import matplotlib.pyplot as plt
#定义一些模型打参数
learning_rate = 0.001
batch_size = 100
batch_size_1 = 1280
n_input = 28 # MNIST data input (img shape: 28*28)
n_steps = 28 # timesteps
n_hidden = 130 # hidden layer num of features
n_classes = 10 # MNIST total classes (0-9 digits)
bb = 2500

#导入训练集
x_1 = np.loadtxt(open("mnist/mnist_train_x.csv",'rb'),delimiter=",",skiprows=0) /255
y_1 = np.loadtxt(open("mnist/mnist_train_y.csv",'rb'),delimiter=",",skiprows=0) 


#导入测试集并放入3维矩阵
x_2 = np.loadtxt(open("mnist/mnist_test_x.csv",'rb'),delimiter=",",skiprows=0) /255
y_2 = np.loadtxt(open("mnist/mnist_test_y.csv",'rb'),delimiter=",",skiprows=0) 

#随机抓取一批数据
def next_batch(train_data, train_target, batch_size):  
    #打乱数据集
    index = [ i for i in range(0,len(train_target)) ]  
    np.random.shuffle(index);  
    #建立batch_data与batch_target的空列表
    batch_data = []; 
    batch_target = [];  
    #向空列表加入训练集及标签
    for i in range(0,batch_size):  
        batch_data.append(train_data[index[i]]);  
        batch_target.append(train_target[index[i]])  
    return batch_data, batch_target #返回

#定义网络
# 开始我们先创建两个占位符placeholder
x = tf.placeholder("float64", [None, n_steps, n_input])
y = tf.placeholder("float64", [None, n_classes])
# Define weights  
weights = {'wih': tf.Variable(tf.random_normal([n_input, n_hidden],dtype=tf.float64)), 
         'who': tf.Variable(tf.random_normal([n_hidden, n_classes],dtype=tf.float64))}
biases = {'bih': tf.Variable(tf.random_normal([n_hidden],dtype=tf.float64)),
    'bho': tf.Variable(tf.random_normal([n_classes],dtype=tf.float64))}
rnn_cell = tf.nn.rnn_cell.BasicRNNCell(n_hidden)

#输出、损失、训练、准确率
outputs, final_states = tf.nn.dynamic_rnn(rnn_cell,x,dtype=tf.float64)
cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=tf.matmul(final_states,weights['who'])+ biases['bho'],labels=y))
train=tf.train.RMSPropOptimizer(learning_rate).minimize(cost)
correct_pred=tf.equal(tf.argmax(tf.matmul(final_states,weights['who']) + biases['bho'],1),tf.argmax(y,1))
accuracy=tf.reduce_mean(tf.cast(correct_pred,"float"))


sess=tf.compat.v1.Session()
sess.run(tf.compat.v1.global_variables_initializer())
a = np.zeros(shape=(bb,1))
for i in range(bb):
  x_3,y_3 = next_batch(x_1,y_1,batch_size_1)
  x_3 = np.reshape(x_3,[batch_size_1,28,28])
  x_4,y_4 = next_batch(x_2,y_2,batch_size)
  x_4 = np.reshape(x_4,[batch_size,28,28])
  sess.run(train, feed_dict={x: x_3, y: y_3})
  loss =  sess.run(cost, feed_dict={x: x_3, y: y_3})
  acc = sess.run(accuracy,feed_dict={x:x_4,y:y_4})
  a[i]=acc
  print(acc,loss) 
  pass
x = np.linspace(0, 1, bb)
plt.plot(x*bb, a)
plt.show()


  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值