第七章:新版tensorflow入门,RNN与LSTM

1、概述

传统的神经网络对线性回归、逻辑回归都有比较好的效果。卷积神经网络主要应用与计算机视觉技术。使用过滤器对图片的边缘特征值进行检测。在之前的章节中使用cnn对文本分类其实是借用了计算机视觉的一些原理,过滤器的尺寸也有着特殊的设置。在人工智能领域还有一种应用场景,就是序列模型。

之前的算法总体上来讲都是概率分布学的,没有将数据的前后关系包含其中,而在实际的情况下,很多数据都是有时序关系的。比如自然语言,同样的词可以组成两个完全意思相反的句子。词的顺序就非常关键。类似的情况还出现在语音、天气、股票等数据中。甚至在某种程度上,我们也会认为图片是有先后顺序的,当然这只是学术界的一些解释。真实的行业应用还需要看最终的效果。

在本章中将使用RNN(循环神经网络)来进行mnist手写图片的分类。

2、关于RNN

RNN是一种典型的序列模型,其结构如下图所示


在上图中我们可以看到左侧的图是RNN的简单描述方式,右侧的部分是RNN的展开形式。在RNN中x作为一个有序数据依次输入到神经网络中,而每一个RNN的每一个处理单元会将对应的输入和上一次的输出来组合处理,这样RNN就有了记忆功能,可以记住之前的一些信息。RNN每一个中间状态都有输出,是否使用得看具体场景,一般来讲RNN的形式一般有以下几种:

1、多对一

理论上也存在一对多和一对一的RNN,但是一对一的RNN其实就是传统的DNN,没有序列的概念,同样如果输入只有一个也谈不上序列。多对一主要应用在分类上。

2、多对多

多对多主要应用在seq2seq(序列到序列)生成,如风格化文章编写、自动翻译等。

2、LSTM

lstm是RNN中神经元应用的最多的一种形式、这种形式源于传统RNN模型的缺点,传统RNN模型由于只具有记忆功能所以对于序列的信息提取不是很精准、而且在反向传播时很容易出现梯度消失和梯度爆炸的情况。这就是长期依赖所产生的问题,神经元不但需要记住同样需要忘记。所以LSTM的引入就变得非常的重要。

长短期记忆网络(Long Short Term Memory networks) - 通常叫做 “LSTMs” —— 是 RNN 中一个特殊的类型。由Hochreiter & Schmidhuber (1997)提出,广受欢迎,之后也得到了很多人们的改进调整。LSTMs 被广泛地用于解决各类问题,并都取得了非常棒的效果。


lstm有三个门来对信息进行拟合分别为

1、遗忘门


2、记忆门


3、输出门


3、使用RNN对mnist手写图片进行分类

我们可以将图片看成是每一行像素看成一个序列进行N行组合得到。所以可以采用RNN模型进行处理、一般来讲在RNN的外围都会有一个输入和输出层,主要是用来规整数据将其变为我们所希望的输入与输出形态的。

请参照如下结构:


该图片来源于

https://medium.com/the-artificial-impostor/notes-understanding-tensorflow-part-2-f7e5ece849f5

在输入层中我们将每一个序列的28个像素扩充为128个像素值,在输出的部分将128个隐藏层又转化为10个one-hot的输出进行分类。

4、tensorflow实现

在本次tensorflow的实现方法中,我们采用low-api的形式进行代码编写,当然也可以根据自己的喜好采用基于estimator的形式进行编写。

  • 读取数据

与cnn的读取方式一致,不再赘述请参照以下代码:

# mnist数据集
import tensorflow  as tf
mnist = tf.contrib.learn.datasets.load_dataset("mnist")
import numpy as np
train_data = mnist.train.images 
print(train_data.shape)
train_labels = np.asarray(mnist.train.labels, dtype=np.int32)
print(train_labels.shape)
eval_data = mnist.test.images 
print(eval_data.shape)
eval_labels = np.asarray(mnist.test.labels, dtype=np.int32)
print(eval_labels.shape)
  • 定义超参数

需要按照上面的模型来定义参数,本次超参数的定义如下:

1、lr_rate : 学习率 采用 0.01

2、batch_size: 每个batch训练的图片数量采用100

3、input_size: 原始的训练数据的大小 即图片的列数,设置为28

4、t_steps:每个数据包含的输入序列数 即图片的行数,设置为 28

5、num_class: 分类的最终数量,设置为10

6、rnn_input:  rnn真实的特征输入、这里设定为128

7、lstm_unit: lstm包含的隐藏单元个数

请参照如下代码:

# 定义超参数
lr_rate = 1e-2
batch_size = 100
input_size = 28
t_steps = 28
num_class = 10 
rnn_input = 128
lstm_unit = 128
  • 数据输入

对于数据来讲每张图片都是一个一行784列的数据,该数据为图片输入的原始形态,我们需要将其转化为28*28的图片数据来作为真正的rnn的输入,这里需要注意的是,新版tensorflow在读取mnist数据时不能直接读取one-hot形式必须在后期自行转换:

train_x = tf.placeholder(dtype=tf.float32,shape=[None,input_size*t_steps])
train_y = tf.placeholder(dtype=tf.int32, shape=[None])
train_labels = tf.one_hot(indices=tf.cast(train_y, tf.int32), depth=num_class)
  • 定义网络结构

1、定义输入层

输入层主要是对数据进行重塑

x_for_input = tf.reshape(train_x,[-1,input_size])
o_input = tf.layers.dense(x_for_input,rnn_input,activation=tf.nn.relu)
x_for_rnn = tf.reshape(o_input,[-1,t_steps,rnn_input])

2、定义rnn,lstm,训练、loss、以及准确率

with tf.variable_scope('rnn',reuse=tf.AUTO_REUSE):
    lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(lstm_unit)
    outputs, (h_c, h_n)= tf.nn.dynamic_rnn(
        lstm_cell,
        x_for_rnn,
        time_major=False,
        initial_state=None, 
        dtype=tf.float32)
    output = tf.layers.dense(outputs[:, -1, :], num_class) 
    loss = tf.losses.softmax_cross_entropy(onehot_labels=train_labels, logits=output)  
    train_op = tf.train.AdamOptimizer(lr_rate).minimize(loss)
    accuracy = tf.metrics.accuracy(
        labels=tf.argmax(train_labels, axis=1), predictions=tf.argmax(output, axis=1),)[1]
    init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer()) 
  • 训练网络

请参照一下代码:

sess = tf.Session()
# the local var is for accuracy_op
sess.run(init_op)     # initialize var in graph

for step in range(1200):    # training
    b_x, b_y = mnist.train.next_batch(batch_size)
    _, loss_ = sess.run([train_op, loss], {train_x: b_x, train_y:b_y})
    if step % 50 == 0:      # testing
        accuracy_ = sess.run(accuracy, {train_x:eval_data, train_y: eval_labels})
        print('train loss: %.4f' % loss_, '| test accuracy: %.2f' % accuracy_)

训练效果如下图所示:

train loss: 2.3085 | test accuracy: 0.10
train loss: 0.6070 | test accuracy: 0.43
train loss: 0.2589 | test accuracy: 0.58
train loss: 0.2609 | test accuracy: 0.66
train loss: 0.3123 | test accuracy: 0.72
train loss: 0.0678 | test accuracy: 0.76
train loss: 0.1774 | test accuracy: 0.79
train loss: 0.2189 | test accuracy: 0.80
train loss: 0.2386 | test accuracy: 0.82
train loss: 0.1099 | test accuracy: 0.84
train loss: 0.0312 | test accuracy: 0.85
train loss: 0.1534 | test accuracy: 0.86
train loss: 0.0405 | test accuracy: 0.87
train loss: 0.0796 | test accuracy: 0.87
train loss: 0.0919 | test accuracy: 0.88
train loss: 0.0485 | test accuracy: 0.88
train loss: 0.0639 | test accuracy: 0.89
train loss: 0.1839 | test accuracy: 0.89
train loss: 0.1297 | test accuracy: 0.90
train loss: 0.1187 | test accuracy: 0.90
train loss: 0.0318 | test accuracy: 0.91
train loss: 0.1728 | test accuracy: 0.91
train loss: 0.0183 | test accuracy: 0.91
train loss: 0.0446 | test accuracy: 0.91





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值