当前位置:   article > 正文

TensorFlow入门教程(12)TensorFlow RNN_tensorflow self.sess

tensorflow self.sess

#
#作者:韦访
#博客:https://blog.csdn.net/rookie_wei
#微信:1007895847
#添加微信的备注一下是CSDN的
#欢迎大家一起学习
#

1、概述

上一讲,我们学习了循环神经网络RNN,并且用RNN实现了二进制减法,实际上TensorFlow集成了RNN,我们只要调用其对应的API就可以很方便的使用RNN来解决问题了。这一讲,我们来看看怎么使用TensorFlow的RNN,作为对比,先做一个和上一讲一样功能的二进制减法,再对MNIST数据集的识别。

环境配置:

操作系统:Win10 64位

显卡:GTX 1080ti

Python:Python3.7

TensorFlow:1.15.0

 

 

2、TensorFlow 封装的RNN

先来看看TensorFlow封装的RNN怎么使用。

cell类

TensorFlow共定义了几个cell类,分别如下,

BasicRNNCell、BasicLSTMCell、LSTMCell、GRUCell、MultiRNNCell。

BasicRNNCell是最基本的RNN。

BasicLSTMCell则实现了LSTM的基本版,LSTM是RNN算法的改进,以后会有专门的博客介绍。

LSTMCell则实现了LSTM的高级版。

GRUCell则实现了GRU算法,GRU也是RNN的改进版,以后也会介绍。

MultiRNNCell则是多层RNN的实现,以后,我们用它来实现音乐文件中,将背景音乐和原唱的声音分离的功能。

构建RNN

得到RNN后,就可以构建RNN了,TensorFlow中可以静态构建和动态构建RNN,分别对应函数static_rnn和dynamic_rnn,至于他们俩有什么区别我就没去了解了。

 

3、二进制减法

现在,我们用TensorFlow来实现上一讲的二进制减法。

十进制转二进制

十进制转二进制的代码还是跟以前的一样,代码如下,

  1. #二进制的位数,这里只计算8位的
  2. binary_dim = 8
  3. #8位二进制的最大数,即28次方
  4. largest_number = pow(2,binary_dim)
  5. #int2binary用于整数到二进制表示的映射
  6. #比如十进制数2的二进制表示,可以写为int2binary[2]
  7. int2binary = {}
  8. #这里将十进制数0-255转成二进制表示,
  9. # 再将其存到int2binary中,所以十进制数2的二进制才可以用int2binary[2]表示
  10. binary = np.unpackbits(
  11. np.array([range(largest_number)],dtype=np.uint8).T,axis=1)
  12. for i in range(largest_number):
  13. int2binary[i] = binary[i]

批量获取数据

在深度学习中,推荐训练数据都是以mini batch的形式,即小批量数据。所以这里我们将数据的获取方式改为批量获取,代码如下,

  1. # 批量获取数据
  2. def get_data(batch_size):
  3. x_data = []
  4. y_data = []
  5. for i in range(batch_size):
  6. # 生成一个被减数a,a的范围在[0,256)的整数
  7. a_int = np.random.randint(largest_number)
  8. # 生成减数b,减数的范围在[0, 128)的整数。
  9. b_int = np.random.randint(largest_number / 2)
  10. # 如果被减数比减数小,则互换,
  11. # 我们暂时不考虑负数,所以要确保被减数比减数大
  12. if a_int < b_int:
  13. tmp = a_int
  14. b_int = a_int
  15. a_int = tmp
  16. # 将其转为二进制的形式
  17. a = int2binary[a_int]
  18. b = int2binary[b_int]
  19. x_data.append([[a, b]])
  20. # 这里c保存的是a-b的答案的二进制形式
  21. c_int = a_int - b_int
  22. y_data.append([int2binary[c_int]])
  23. x_data = np.concatenate(x_data)
  24. y_data = np.concatenate(y_data)
  25. return x_data, y_data

定义占位符

接下来的做法就跟我们以前做的TensorFlow模型的步骤差不多了,先定义占位符,

  1. # 定义占位符,用于存放输入数据x和y
  2. self.x_in = tf.placeholder(tf.float32, [None, n_steps, n_input])
  3. self.y_in = tf.placeholder(tf.float32, [None, n_output])

定义网络

接着,定义我们的网络结构,我们使用RNN+全连接网络的方式,代码如下,

  1. # 定义网络结构,RNN+全连接网络
  2. def net(self):
  3. # cell = tf.nn.rnn_cell.BasicRNNCell(n_hidden)
  4. # outputs, states = tf.nn.dynamic_rnn(cell, self.x_in, dtype=tf.float32)
  5. # self.pre = tf.layers.dense(inputs=states, units=n_input, activation=tf.nn.relu)
  6. cell = tf.nn.rnn_cell.BasicLSTMCell(n_hidden)
  7. outputs, states = tf.nn.dynamic_rnn(cell, self.x_in, dtype=tf.float32)
  8. self.pred = tf.layers.dense(inputs = states[1], units = n_input, activation =tf.nn.relu)

我们上面用的是BasicLSTMCell,因为在LSTM比基础的RNN效果好,你们可以试试使用BasicRNNCell网络,使用上面注释了的代码即可。

定义损失函数和优化器

因为是回归问题,所以我们使用均方误差作为损失函数,而优化器则使用梯度下降法,梯度下降法也是有很多变种的,以后的博客我们再详谈,代码如下,

  1. # 定义损失函数和优化器
  2. def loss_opt(self):
  3. # 因为是回归问题,所以损失函数使用均方误差
  4. self.loss = tf.reduce_mean((self.pred - self.y_in) ** 2)
  5. self.opt = tf.train.AdamOptimizer(learning_rate).minimize(self.loss)

测试精度

接着,我们来写测试精度的函数,用模型的预测值和真实值对比,代码如下,

  1. # 检测精度
  2. def accuracy(self):
  3. eq = tf.equal(tf.round(self.pred), tf.round(self.y_in))
  4. self.acc = tf.reduce_mean(tf.cast(eq, tf.float32))

创建会话

创建会话和初始化变量的代码如下,

  1. # 定义会话和初始化变量
  2. def session(self):
  3. self.sess = tf.Session()
  4. self.sess.run(tf.global_variables_initializer())

关闭会话

因为我们这里不用with关键字,所以创建会话以后还要关闭会话,代码如下,

  1. # 关闭会话
  2. def close_session(self):
  3. self.sess.close()

训练模型

训练模型,往网络里塞数据就可以了,

  1. # 训练模型
  2. def run(self, x, y):
  3. self.sess.run(self.opt, feed_dict={
  4. self.x_in: x,
  5. self.y_in: y,
  6. })

Log打印

每隔一定步数的时候,打印一下当前的loss值等状态,

  1. # 打印
  2. def log(self, step, x, y):
  3. loss, pre, acc = self.sess.run([self.loss, self.pred, self.acc], feed_dict={
  4. self.x_in: x,
  5. self.y_in: y,
  6. })
  7. print('--------------------------------')
  8. print('step:', step, ' loss:', loss, ' acc:', acc)
  9. for yy, pp in zip(y[:1], pre[:1]):
  10. print('y:', yy.astype(float))
  11. print('p:', np.round(pp))

Main函数

万事俱备,调用即可,代码如下,

  1. def main(argv=None):
  2. rnn_o = Rnn()
  3. for step in range(train_steps):
  4. # 批量获取数据
  5. x, y = get_data(batch_size)
  6. # 训练模型
  7. rnn_o.run(x, y)
  8. # 打印
  9. if step % 500 == 0:
  10. x, y = get_data(batch_size)
  11. rnn_o.log(step, x, y)
  12. #关闭会话
  13. rnn_o.close_session()

完整的代码在博客末尾给链接。

运行结果

4、识别MNIST

MNIST数据集的图片的大小是(28, 28),我们将它当成28个时间段,没个时间段的内容为28个值,将这个28个时序送入RNN网络中。

定义占位符

老规矩,先定义占位符,

  1. # 定义占位符
  2. self.x_in = tf.placeholder(tf.float32, [None, n_steps, n_input])
  3. self.y_in = tf.placeholder(tf.float32, [None, n_classes])

定义网络

接着,定义网络结构,还是RNN+全连接网络,代码如下,

  1. # 定义网络结构,RNN+全连接网络
  2. def net(self):
  3. # cell = tf.nn.rnn_cell.BasicLSTMCell(n_hidden)
  4. # outputs, states = tf.nn.dynamic_rnn(cell, self.x_in, dtype=tf.float32)
  5. # self.pred = tf.layers.dense(inputs=states[1], units=n_classes, activation=tf.nn.relu)
  6. cell = tf.nn.rnn_cell.BasicLSTMCell(n_hidden)
  7. x1 = tf.unstack(self.x_in, n_steps, 1)
  8. outputs, states = tf.nn.static_rnn(cell, x1, dtype=tf.float32)
  9. self.pred = tf.layers.dense(inputs = states[1], units = n_classes, activation =tf.nn.relu)

上面说过,TensorFlow构建RNN有动态和静态的方法,二进制减法中我们使用了动态的方法,这里我们就用静态的方法,注释部分是用动态的方法,你们也可以使用注释部分的代码。

 

定义损失函数和优化器

因为识别MNIST是分类问题,所以我们这里使用交叉熵作为损失函数,代码如下,

  1. # 定义损失函数和优化器
  2. def loss_opt(self):
  3. # 因为是分类问题,所以损失函数使用交叉熵
  4. self.loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=self.pred, labels=self.y_in))
  5. self.opt = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(self.loss)

测试精度

跟以前一样,没什么好说的,

  1. # 检测精度
  2. def accuracy(self):
  3. eq = tf.equal(tf.argmax(self.pred, 1), tf.argmax(self.y_in, 1))
  4. self.acc = tf.reduce_mean(tf.cast(eq, tf.float32))

训练模型

我们获取的MNIST的图片shape是(, 784),我们需要先将它转成(, 28, 28)的形式,再输入网络中,代码如下,

  1. # 训练模型
  2. def run(self, x, y):
  3. # 将输入数据shape从(, 784)变成(, 28, 28)
  4. x = x.reshape((x.shape[0], n_steps, n_input))
  5. self.sess.run(self.opt, feed_dict={self.x_in: x, self.y_in: y})

Log打印

  1. # 打印
  2. def log(self, step, x, y):
  3. # 将输入数据shape从(, 784)变成(, 28, 28)
  4. x = x.reshape((x.shape[0], n_steps, n_input))
  5. acc, loss = self.sess.run([self.acc, self.loss], feed_dict={self.x_in: x, self.y_in: y})
  6. print("step: ", step, ", Minibatch Loss= " ,
  7. "{:.6f}".format(loss) , ", Training Accuracy= " ,
  8. "{:.5f}".format(acc))

创建和关闭会话

  1. # 定义会话和初始化变量
  2. def session(self):
  3. self.sess = tf.Session()
  4. self.sess.run(tf.global_variables_initializer())
  5. # 关闭会话
  6. def close_session(self):
  7. self.sess.close()

Main函数

都定义好以后,在main函数中使用即可,代码如下,

  1. #下载并导入MNIST数据集
  2. mnist = input_data.read_data_sets("mnist_data/", one_hot=True)
  3. #定义训练次数和batch长度
  4. train_steps = 40000
  5. batch_size = 32
  6. def main(argv=None):
  7. rnn_o = Rnn()
  8. #开始训练
  9. for step in range(train_steps):
  10. #批量获取MNIST数据
  11. x, y = mnist.train.next_batch(batch_size)
  12. rnn_o.run(x, y)
  13. if step % 500 == 0:
  14. x, y = mnist.test.next_batch(batch_size)
  15. rnn_o.log(step, x, y)
  16. # 关闭会话
  17. rnn_o.close_session()
  18. print (" Finished!")

运行结果

5、完整代码

完整代码链接如下,

https://mianbaoduo.com/o/bread/Y5iamZw=

 

下一讲,我们来学习反向传播BP的过程。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/851438
推荐阅读
相关标签
  

闽ICP备14008679号