Tensorflow构建单层/多层LSTM网络对MNIST数据集分类

本文详细介绍了如何使用TensorFlow构建单层和多层LSTM网络,以及如何将LSTM与GRU网络结合,用于MNIST手写数字识别任务。通过实例代码展示了网络结构、参数设置、训练过程以及测试准确率,旨在说明RNN在序列数据处理中的应用。
摘要由CSDN通过智能技术生成
#-*- codeing = utf-8 -*-
#@Time :2021/5/20 19:40
#@Author :Onion
#@File :LSTMMNISTDemo.py
#@Software :PyCharm

import tensorflow as tf
import os
from tensorflow.examples.tutorials.mnist import input_data
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
# 获取MNIST数据
# tf.disable_v2_behavior()
mnist = input_data.read_data_sets("./MNIST_data", one_hot=True)
tf.compat.v1.disable_eager_execution()
tf.compat.v1.reset_default_graph()

# MNIST数据的大小为28*28,把输入的x当成28个时间段,每段内容为28个值
# 这28个时序一次送入RNN中
n_input = 28    # 序列的长度(时间段)
n_steps = 28    # 序列的个数
n_hidden = 128  # 隐藏层的个数(128个cell)
n_classes = 10  # MNIST的输出为10个数,(0~9)表示分类

# 参数设置
learning_rate = 0.001
training_iters = 100000
batch_size = 128
display_step = 10

# 定义占位符
X = tf.compat.v1.placeholder("float",[None,n_steps,n_input])
Y = tf.compat.v1.placeholder("float",[None,n_classes])
# 使用unstack将原始的输入28*28调整成具有28个元素的list,每个元素为1*28的数组
X1 = tf.unstack(X, n_steps, 1)


# 构建LSTM网络
# num_units 表示LSTM单元中的单位数,即Cell的个数
# RNN以前是非常难以训练的, 因为随时间传递的状态C如果有一个小的误差delta, 这个误差会在传递的过程中指数级别增加或者减少, 造成输出爆炸(Explosion)或者消失(Vanish)LSTM的forget GATE就是解决这个问题用的. 刚开始初始化成1, LSTM不会传递任何状态C, 因为forget GATE把C归零了. 这避免了刚开始训练就有输出爆炸或者消失的问题.
lstm_cell = tf.compat.v1.nn.rnn_cell.BasicLSTMCell(num_units=n_hidden,forget_bias=1.0)

# 输出
outputs,states = tf.compat.v1.nn.static_rnn(lstm_cell,X1,dtype=tf.float32)

# 全连接函数dense,将LSTM的Cell层的输出做一次全连接,并将激活函数设置为None表示线性激活
# 全连接层之前的作用是提取特征、分类
# 全连接层的每一个结点都与上一层的所有结点相连,用来把前边提取到的特征综合起来。
pred = tf.compat.v1.layers.dense(outputs[-1],n_classes,activation=None)

# 损失函数,(输出值与Y标签之间的损失值)
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred,labels=Y))
# 优化器
optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)

# 计算平均错误率
correct_prediction = tf.equal(tf.argmax(pred,1), tf.argmax(Y,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

init = tf.compat.v1.global_variables_initializer()
with tf.compat.v1.Session() as sess:
    sess.run(init)
    step = 1
    # Keep training until reach max iterations
    while step * batch_size < training_iters:
        batch_x, batch_y = mnist.train.next_batch(batch_size)
        # Reshape data to get 28 seq of 28 elements
        batch_x = batch_x.reshape((batch_size, n_steps, n_input))
        # Run optimization op (backprop)
        sess.run(optimizer, feed_dict={X: batch_x, Y: batch_y})
        if step % display_step == 0:
            # 计算批次数据的准确率
            acc = sess.run(accuracy, feed_dict={X: batch_x, Y: batch_y})
            # Calculate batch loss
            # 这里返回值不可以用loss来命名变量,因为计算loss的时候必须是一个Tensor,如果把loss改了,返回的就是一个float,会报错
            newloss = sess.run(loss, feed_dict={X: batch_x, Y: batch_y})
            print ("Iter " + str(step*batch_size) + ", Minibatch Loss= " + \
                  "{:.5f}".format(newloss) + ", Training Accuracy= " + \
                  "{:.5f}".format(acc))
        step += 1
    print (" Finished!")

    # 计算准确率 for 128 mnist test images
    test_len = 128
    test_data = mnist.test.images[:test_len].reshape((-1, n_steps, n_input))
    test_label = mnist.test.labels[:test_len]
    print ("Testing Accuracy:", \
        sess.run(accuracy, feed_dict={X: test_data, Y: test_label}))

在这里插入图片描述
多层的也很简单,在单层的基础上用tf.compat.v1.nn.rnn_cell.MultiRNNCell([lstm_cell]*hidden_layer_nums)就可以完成多层LSTM网络的构建了

#-*- codeing = utf-8 -*-
#@Time :2021/5/21 0:31
#@Author :Onion
#@File :MultiLSTMMNISTDemo.py
#@Software :PyCharm

import tensorflow as tf
import os
from tensorflow.examples.tutorials.mnist import input_data
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
# 获取MNIST数据
# tf.disable_v2_behavior()
mnist = input_data.read_data_sets("./MNIST_data", one_hot=True)
tf.compat.v1.disable_eager_execution()
tf.compat.v1.reset_default_graph()

# MNIST数据的大小为28*28,把输入的x当成28个时间段,每段内容为28个值
# 这28个时序一次送入RNN中
n_input = 28    # 序列的长度(时间段)
n_steps = 28    # 序列的个数
n_hidden = 128  # 单个隐藏层的cell的个数(128个cell)
n_classes = 10  # MNIST的输出为10个数,(0~9)表示分类
hidden_layer_nums = 3# 三层LSTM网络

# 参数设置
learning_rate = 0.001
training_iters = 100000
batch_size = 128    # 每一批128张图片
display_step = 10 # 每训练10次打印一次结果

# 定义占位符
X = tf.compat.v1.placeholder("float",[None,n_steps,n_input])
Y = tf.compat.v1.placeholder("float",[None,n_classes])
# 使用unstack将原始的输入28*28调整成具有28个元素的list,每个元素为1*28的数组
X1 = tf.unstack(X, n_steps, 1)


# 构建LSTM网络
# num_units 表示LSTM单元中的单位数,即Cell的个数
# RNN以前是非常难以训练的, 因为随时间传递的状态C如果有一个小的误差delta, 这个误差会在传递的过程中指数级别增加或者减少, 造成输出爆炸(Explosion)或者消失(Vanish)LSTM的forget GATE就是解决这个问题用的. 刚开始初始化成1, LSTM不会传递任何状态C, 因为forget GATE把C归零了. 这避免了刚开始训练就有输出爆炸或者消失的问题.
lstm_cell = tf.compat.v1.nn.rnn_cell.BasicLSTMCell(num_units=n_hidden,forget_bias=1.0)

# 构建3层LSTM网络
lstm_cells = tf.compat.v1.nn.rnn_cell.MultiRNNCell([lstm_cell]*hidden_layer_nums)
# 输出
outputs,states = tf.compat.v1.nn.static_rnn(lstm_cells,X1,dtype=tf.float32)

# 全连接函数dense,将LSTM的Cell层的输出做一次全连接,并将激活函数设置为None表示线性激活
# 全连接层之前的作用是提取特征、分类
# 全连接层的每一个结点都与上一层的所有结点相连,用来把前边提取到的特征综合起来。
pred = tf.compat.v1.layers.dense(outputs[-1],n_classes,activation=None)
# 损失函数,(输出值与Y标签之间的损失值)

loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred,labels=Y))
# 优化器
optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)

# 计算平均错误率
# 【Tensorflow】 tf.equal(tf.argmax(y, 1),tf.argmax(y_, 1))用法
# 作用:输出正确的预测结果
# 利用tf.argmax()按行求出真实值y_、预测值y最大值的下标,用tf.equal()求出真实值和预测值相等的数量,也就是预测结果正确的数量,tf.argmax()和tf.equal()一般是结合着用
correct_prediction = tf.equal(tf.argmax(pred,1), tf.argmax(Y,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

init = tf.compat.v1.global_variables_initializer()
with tf.compat.v1.Session() as sess:
    sess.run(init)
    step = 1
    # Keep training until reach max iterations
    while step * batch_size < training_iters:
        batch_x, batch_y = mnist.train.next_batch(batch_size)
        # Reshape data to get 28 seq of 28 elements
        batch_x = batch_x.reshape((batch_size, n_steps, n_input))
        # Run optimization op (backprop)
        # 在run执行的时候,内部做了128次运算,每一次取batch_x(128)个中的一个,传入X,并unpack成X1,,做这样的运算在内部进行了128次
        sess.run(optimizer, feed_dict={X: batch_x, Y: batch_y})
        if step % display_step == 0:
            # 计算批次数据的准确率
            acc = sess.run(accuracy, feed_dict={X: batch_x, Y: batch_y})
            # Calculate batch loss
            # 这里返回值不可以用loss来命名变量,因为计算loss的时候必须是一个Tensor,如果把loss改了,返回的就是一个float,会报错
            newloss = sess.run(loss, feed_dict={X: batch_x, Y: batch_y})
            print ("Iter " + str(step*batch_size) + ", Minibatch Loss= " + \
                  "{:.5f}".format(newloss) + ", Training Accuracy= " + \
                  "{:.5f}".format(acc))
        step += 1
    print (" Finished!")

    # 计算准确率 for 128 mnist test images
    test_len = 128
    test_data = mnist.test.images[:test_len].reshape((-1, n_steps, n_input))
    test_label = mnist.test.labels[:test_len]
    print ("Testing Accuracy:", \
        sess.run(accuracy, feed_dict={X: test_data, Y: test_label}))

在这里插入图片描述
当然,还可以将单层的GRU网络和多层的LSTM网络连接起来构成一个多层的RNN网络

#-*- codeing = utf-8 -*-
#@Time :2021/5/21 0:56
#@Author :Onion
#@File :MixRNNDemo.py
#@Software :PyCharm

#-*- codeing = utf-8 -*-
#@Time :2021/5/20 19:40
#@Author :Onion
#@File :LSTMMNISTDemo.py
#@Software :PyCharm

# 构建GRU和LSTM混合的网络
import tensorflow as tf
import os
from tensorflow.examples.tutorials.mnist import input_data
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
# 获取MNIST数据
# tf.disable_v2_behavior()
mnist = input_data.read_data_sets("./MNIST_data", one_hot=True)
tf.compat.v1.disable_eager_execution()
tf.compat.v1.reset_default_graph()

# MNIST数据的大小为28*28,把输入的x当成28个时间段,每段内容为28个值
# 这28个时序一次送入RNN中
n_input = 28    # 序列的长度(时间段)
n_steps = 28    # 序列的个数
n_hidden = 128  # 隐藏层的cell的个数(128个cell)
n_classes = 10  # MNIST的输出为10个数,(0~9)表示分类

# 参数设置
learning_rate = 0.001
training_iters = 100000
batch_size = 128    # 每一批128张图片
display_step = 10 # 每训练10次打印一次结果
hidden_layer_nums =3
# 定义占位符
X = tf.compat.v1.placeholder("float",[None,n_steps,n_input])
Y = tf.compat.v1.placeholder("float",[None,n_classes])
# 使用unstack将原始的输入28*28调整成具有28个元素的list,每个元素为1*28的数组
X1 = tf.unstack(X, n_steps, 1)


# 构建单层GRU网络
gru_cell = tf.compat.v1.nn.rnn_cell.GRUCell(num_units=n_hidden*2)
# 构建3层LSTM网络
# num_units 表示LSTM单元中的单位数,即Cell的个数
# RNN以前是非常难以训练的, 因为随时间传递的状态C如果有一个小的误差delta, 这个误差会在传递的过程中指数级别增加或者减少, 造成输出爆炸(Explosion)或者消失(Vanish)LSTM的forget GATE就是解决这个问题用的. 刚开始初始化成1, LSTM不会传递任何状态C, 因为forget GATE把C归零了. 这避免了刚开始训练就有输出爆炸或者消失的问题.
lstm_cell = tf.compat.v1.nn.rnn_cell.BasicLSTMCell(num_units=n_hidden,forget_bias=1.0)
lstm_cells = tf.compat.v1.nn.rnn_cell.MultiRNNCell([lstm_cell]*hidden_layer_nums)

# 将3层LSTM网络和单层的GRU网络连接成一个4层的RNN网络
RNN_cells =  tf.compat.v1.nn.rnn_cell.MultiRNNCell([lstm_cells.gru])
# 输出
outputs,states = tf.compat.v1.nn.static_rnn(lstm_cell,X1,dtype=tf.float32)

# 全连接函数dense,将LSTM的Cell层的输出做一次全连接,并将激活函数设置为None表示线性激活
# 全连接层之前的作用是提取特征、分类
# 全连接层的每一个结点都与上一层的所有结点相连,用来把前边提取到的特征综合起来。
pred = tf.compat.v1.layers.dense(outputs[-1],n_classes,activation=None)

# 损失函数,(输出值与Y标签之间的损失值)
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred,labels=Y))
# 优化器
optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)

# 计算平均错误率
# 【Tensorflow】 tf.equal(tf.argmax(y, 1),tf.argmax(y_, 1))用法
# 作用:输出正确的预测结果
# 利用tf.argmax()按行求出真实值y_、预测值y最大值的下标,用tf.equal()求出真实值和预测值相等的数量,也就是预测结果正确的数量,tf.argmax()和tf.equal()一般是结合着用
correct_prediction = tf.equal(tf.argmax(pred,1), tf.argmax(Y,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

init = tf.compat.v1.global_variables_initializer()
with tf.compat.v1.Session() as sess:
    sess.run(init)
    step = 1
    # Keep training until reach max iterations
    while step * batch_size < training_iters:
        batch_x, batch_y = mnist.train.next_batch(batch_size)
        # Reshape data to get 28 seq of 28 elements
        batch_x = batch_x.reshape((batch_size, n_steps, n_input))
        # Run optimization op (backprop)
        # 在run执行的时候,内部做了128次运算,每一次取batch_x(128)个中的一个,传入X,并unpack成X1,,做这样的运算在内部进行了128次
        sess.run(optimizer, feed_dict={X: batch_x, Y: batch_y})
        if step % display_step == 0:
            # 计算批次数据的准确率
            acc = sess.run(accuracy, feed_dict={X: batch_x, Y: batch_y})
            # Calculate batch loss
            # 这里返回值不可以用loss来命名变量,因为计算loss的时候必须是一个Tensor,如果把loss改了,返回的就是一个float,会报错
            newloss = sess.run(loss, feed_dict={X: batch_x, Y: batch_y})
            print ("Iter " + str(step*batch_size) + ", Minibatch Loss= " + \
                  "{:.5f}".format(newloss) + ", Training Accuracy= " + \
                  "{:.5f}".format(acc))
        step += 1
    print (" Finished!")

    # 计算准确率 for 128 mnist test images
    test_len = 128
    test_data = mnist.test.images[:test_len].reshape((-1, n_steps, n_input))
    test_label = mnist.test.labels[:test_len]
    print ("Testing Accuracy:", \
        sess.run(accuracy, feed_dict={X: test_data, Y: test_label}))

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲代码的洋葱头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值