TensorFlow实现RNN网络(十六)

时间:2023-02-03 21:21:03

TensorFlow实现RNN神经网络

之前实现过一个利用RNN实现一个二进制加法的操作。这个其实也是一样的做法。

只不过变成了图片。

TensorFlow实现RNN网络(十六)

首先要进行一个预处理,之后经过一个全连接层,然后经过一个切分,一个图形是28x28x1,那么就会把他切分成一行一行的,也就是每一个图片进行LSTM层的时候,是一行一行进去的,保留和遗弃飞信息都是前一行的。最后就是输出了。

TensorFlow实现RNN网络(十六)

接下来就是代码的实现了:

import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data
import numpy as np
import matplotlib.pyplot as plt

mnist = input_data.read_data_sets('data/' , one_hot = True)

数据准备,用的数据还是之前的mnist数据集。

diminput = 28 dimhidden = 128 dimoutput = 10 nstep = 28 weights = {
    'hidden' : tf.Variable(tf.random_normal([diminput , dimhidden],stddev=0.1)),
    'out' : tf.Variable(tf.random_normal([dimhidden , dimoutput],stddev=0.1))
}
biases = {
    'hidden' : tf.Variable(tf.random_normal([dimhidden])),
    'out' : tf.Variable(tf.random_normal([dimoutput]))
}

输入的是一个28x28x1的一个图片。在权值有两个,一个是输入隐层的,一个就是最后出来的时候还有一层。


def RNN(x , w , b , nstep ):
    new_x = tf.transpose(x , [1 , 0 , 2])
    x = tf.reshape(new_x , [-1 , diminput])
    h = tf.add(tf.matmul(x , w['hidden']) , b['hidden'])
    hsplit = tf.split(h , int(nstep) , 0)
    lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(dimhidden , forget_bias=1.0)
    lstm_o , lstm_s = tf.nn.static_rnn(lstm_cell , hsplit , dtype = tf.float32)
    return tf.add(tf.matmul(lstm_o[-1] , w['out']) , b['out'])
    pass

LSTM层的权值也设定是128个,但是不需要我们自己写了,他已经封装好。

首先要把所有选出来的样本全部都切分成一行一行的list。 然后一次选28行出来,因为一个图片就是28x28,选28行刚刚好就是一个图片。然后把选出来的这28行传进去。

    new_x = tf.transpose(x , [1 , 0 , 2])
    x = tf.reshape(new_x , [-1 , diminput])

这里首先做一个调换。因为这个图片是3维的,分别代表层数,高,宽,用0,1,2代表。transpose就是把一维和二维换过来,原来是1x28x28,换了就是28x1x28,这样是为了后面的操作没有歧义。因为如果不换的话,直接变成一个二维的他不知道是按照行切还是列切。这样换一下再使用reshape就可以把图片全部都拼成二维的。

h = tf.add(tf.matmul(x , w['hidden']) , b['hidden'])

然后经过一个隐层的前向传播。其实也可以先切分后经过隐层,但是这样就麻烦了,而且前后顺序没有区别。

hsplit = tf.split(h , int(nstep) , 0)

这个就是一个切分,按照nstep也就是一张图片的高度进行切分。这里的TensorFlow版本不同这个函数会有很大的差别。比如我用的是1.2TensorFlow,所以参数就调换过来了。

    lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(dimhidden , forget_bias=1.0)
    lstm_o , lstm_s = tf.nn.static_rnn(lstm_cell , hsplit , dtype = tf.float32)
这里就是进行一个RNN的操作了。上面是定义参数,神经元的数量,下面就是进行一个RNN网络的计算。

learning_rate = 0.01 x = tf.placeholder(tf.float32 , [None , nstep , diminput])
y = tf.placeholder(tf.float32 , [None , dimoutput])
rnn = RNN(x , weights , biases , nstep)
pred = rnn
cost   = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))
optm   = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
accr   = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(pred,1), tf.argmax(y,1)), tf.float32))
init   = tf.global_variables_initializer()
total_batch = 100 training_epochs = 100 batch_size      = 16 display_step    = 1 sess = tf.Session()
sess.run(init)
for epoch in range(1000):
    avg_cost = 0.  total_batch = 100  # Loop over all batches  for i in range(total_batch):
        batch_xs, batch_ys = mnist.train.next_batch(batch_size)
        batch_xs = batch_xs.reshape((batch_size, nstep, diminput))
        feeds = {x: batch_xs, y: batch_ys}
        sess.run(optm, feed_dict=feeds)
        avg_cost += sess.run(cost, feed_dict=feeds)/total_batch
    # Display logs per epoch step  train_acc = sess.run(accr, feed_dict=feeds)
    print(" Training accuracy: %.3f" % (train_acc))
    print(avg_cost)

这里的计算和之前的全连接没有什么不同,和CNN就是一个函数的不同。

完整代码:

import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data
import numpy as np
import matplotlib.pyplot as plt

mnist = input_data.read_data_sets('data/' , one_hot = True)

diminput = 28
dimhidden = 128
dimoutput = 10
nstep = 28
weights = {
    'hidden' : tf.Variable(tf.random_normal([diminput , dimhidden],stddev=0.1)),
    'out' : tf.Variable(tf.random_normal([dimhidden , dimoutput],stddev=0.1))
}
biases = {
    'hidden' : tf.Variable(tf.random_normal([dimhidden])),
    'out' : tf.Variable(tf.random_normal([dimoutput]))
}

def RNN(x , w , b , nstep ):
    new_x = tf.transpose(x , [1 , 0 , 2])
    x = tf.reshape(new_x , [-1 , diminput])
    h = tf.add(tf.matmul(x , w['hidden']) , b['hidden'])
    hsplit = tf.split(h , int(nstep) , 0)
    lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(dimhidden , forget_bias=1.0)
    lstm_o , lstm_s = tf.nn.static_rnn(lstm_cell , hsplit , dtype = tf.float32)
    return tf.add(tf.matmul(lstm_o[-1] , w['out']) , b['out'])
    pass  learning_rate = 0.01
x = tf.placeholder(tf.float32 , [None , nstep , diminput])
y = tf.placeholder(tf.float32 , [None , dimoutput])
rnn = RNN(x , weights , biases , nstep)
pred = rnn
cost   = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))
optm   = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
accr   = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(pred,1), tf.argmax(y,1)), tf.float32))
init   = tf.global_variables_initializer()
total_batch = 100
training_epochs = 100
batch_size      = 16
display_step    = 1
sess = tf.Session()
sess.run(init)
for epoch in range(1000):
    avg_cost = 0.
    total_batch = 100
    # Loop over all batches  for i in range(total_batch):
        batch_xs, batch_ys = mnist.train.next_batch(batch_size)
        batch_xs = batch_xs.reshape((batch_size, nstep, diminput))
        feeds = {x: batch_xs, y: batch_ys}
        sess.run(optm, feed_dict=feeds)
        avg_cost += sess.run(cost, feed_dict=feeds)/total_batch
    # Display logs per epoch step  train_acc = sess.run(accr, feed_dict=feeds)
    print(" Training accuracy: %.3f" % (train_acc))
    print(avg_cost)


结果输出:

一开始是比较低的,比较权值设置的不好:

TensorFlow实现RNN网络(十六)

cost函数还是很大的,而且准确率都是小于百分之50。

而训练了1000次之后,准确度差不多是百分之一百了:

TensorFlow实现RNN网络(十六)

完!