TensorFlow实现RNN神经网络
之前实现过一个利用RNN实现一个二进制加法的操作。这个其实也是一样的做法。
只不过变成了图片。
首先要进行一个预处理,之后经过一个全连接层,然后经过一个切分,一个图形是28x28x1,那么就会把他切分成一行一行的,也就是每一个图片进行LSTM层的时候,是一行一行进去的,保留和遗弃飞信息都是前一行的。最后就是输出了。
接下来就是代码的实现了:
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)
结果输出:
一开始是比较低的,比较权值设置的不好:
cost函数还是很大的,而且准确率都是小于百分之50。
而训练了1000次之后,准确度差不多是百分之一百了:
完!