用Tensorflow建立image caption 模型(一)

前言:

  写这篇博客的目的是一开始想要使用Tensorflow建立一个image caption模型,在一开始觉得不就是一个LSTM模型,因为之前有用Tensorflow实现过CNN结构,所以觉得并不会很难。但实际上,在这个过程中也遇到了不少困难。
按照我自己的学习顺序,这个系列的博客将分为三个部分,最终将构建一个基于Tensorflow的简单的image caption模型:

  1. 就是本篇博客,搬运于另一个博主,加上了自己的理解做了一些扩展性的,主要是对语言模型有关的注释。这篇博客主要是为了了解一些LSTM一些基本的结构。
  2. 这个系列第二篇部分,同样搬运于另一个博主,这篇博客将《tensorflow 实战》用Tensorflows实现的循环神经网络语言模型大大简化,增加了书上例子的可读性,在我学习的过程中给了我很多帮助。
  3. 这个系列的第三部分,也是最后一部分,参考了上述两篇博客和Assignment3中的部分,最后算是整合成了一个符合自己预期的模型,也是自己收获最多的一部分。
  4. 最后感谢所有我在学习过程中互联网上间接或直接提供帮助的朋友,世界因为你们而美好。无法一一罗列,所有参考资料会放在文章最后

第一部分 基本的LSTM结构

在这个部分,将使用MNSIT_data数据集和LSTM构建一个基本的分类模型。直接上代码,具体内容见代码中的注释,代码中有些不好理解的部分,可见文末的一些链接中。

'''读取数据'''
from __future__ import print_function
import tensorflow as tf
from tensorflow.contrib import rnn
# Import MNIST data
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./MNIST_data", one_hot=True)
#看看数据的样子
print(mnist.train.images.shape)
print(tf.__version__)
# (55000, 784)
# 1.3.0
'''预先定义一些参数'''
lr = 1e3
batch_size = tf.placeholder(tf.int32,[])  #这样可以使用不同的batch_size
input_size = 28    #每个时刻输入的特征的维度,如果是语言模型,可以理解为词向量的维度
timestep_size = 28   # 时序的长度。在语言模型中
hidden_size = 256  # 隐含层节点数
layer_num = 2 #  LSTM layer的层数  
class_num = 10 #  最后输出分类的类别,在语言模型中,这个参数就是单词表的大小。
# 输入输出
_X = tf.placeholder(tf.float32, [None, 784])
y = tf.placeholder(tf.float32, [None, class_num])
keep_prob= tf.placeholder(tf.float32, [])
'''构建模型'''
# 先处理数据,将[None,784] => [batchsize,timestep_size,input_size]
#实际上输入可以直接规定成这样的格式

X = tf.reshape(_X,[-1,timestep_size, input_size]) 

# 构建模型有两种方法,
#法一:
#定义一个LSTM_cell
# lstm_cell = rnn.BasicLSTMCell(
#     hidden_size, 
#     forget_bias = 1.0, 
#     state_is_tuple = True
# )

# lstm_cell = rnn.DropoutWrapper(   
#     cell = lstm_cell, 
#     input_keep_prob = 1.0,
#     output_keep_prob = keep_prob
# )
# #多层LSTM
# mlstm_cell = rnn.MultiRNNCell([lstm_cell] * layer_num, state_is_tuple = True)

#法二:
##上边注释的等价于
def lstm_cell():
    cell = rnn.LSTMCell(hidden_size,  reuse=tf.get_variable_scope().reuse)
    return rnn.DropoutWrapper(cell, output_keep_prob = keep_prob)

mlstm_cell = tf.contrib.rnn.MultiRNNCell([lstm_cell() for _ in range(layer_num)], state_is_tuple = True)


#lstm的传播过程中会保存中间的状态, state_is_tuple的意思就是回返回一个元祖(c_state,m_state),其中分别代表
#(主线的状态,支线的状态),
#下边是对state进行初始化,   这是全0,也可以自定义  ,但这为什么是batch_size大小的呢/.?????
init_state = mlstm_cell.zero_state(batch_size, dtype=tf.float32)

#outputs  一个list.保留每一步的output
#state = (c_state,m_state),只保留最后一次的状态   这个实际上并不太懂
# 在这里state[1] = output[-1]
#time_major : 每一个时间步是不是在主要的维度,比如现在X.shape = [batch_size,timestep_size, input_size]
#             中时间点在第二个位置,也就是次要的维度,所以这里time_major为False
# outputs, state = tf.nn.dynamic_rnn(mlstm_cell, inputs = X , initial_state = init_state, time_major = False)

# h_state = state[-1][1]

outputs = list()
state = init_state
with tf.variable_scope('RNN'):
    for timestep in range(timestep_size):
        if timestep > 0:
            tf.get_variable_scope().reuse_variables()
        # 这里的state保存了每一层 LSTM 的状态
        (cell_output, state) = mlstm_cell(X[:, timestep, :],state)
        outputs.append(cell_output)
h_state = outputs[-1]

'''定义输出层和损失、准确率'''
#定义输出与softmax链接的权重
W = tf.Variable(tf.truncated_normal([hidden_size , class_num], stddev = 0.1), dtype = tf.float32)
bias = tf.Variable(tf.constant(0.1,shape = [class_num]), dtype = tf.float32)
y_pre = tf.nn.softmax(tf.matmul(h_state, W) + bias)
cross_entropy = -tf.reduce_mean(y * tf.log(y_pre))
train_op = tf.train.AdamOptimizer(lr).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_pre,1), tf.argmax(y,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
'''训练过程'''
sess = tf.Session()
sess.run(tf.global_variables_initializer())
for i in range(2000):
    _batch_size = 128
    batch = mnist.train.next_batch(_batch_size)
    if (i+1)%200 == 0:
        train_accuracy = sess.run(accuracy, feed_dict={
            _X:batch[0], y: batch[1], keep_prob: 1.0, batch_size: _batch_size})
        # 已经迭代完成的 epoch 数: mnist.train.epochs_completed
        print("Iter%d, step %d, training accuracy %g" % ( mnist.train.epochs_completed, (i+1), train_accuracy))
    sess.run(train_op, feed_dict={_X: batch[0], y: batch[1], keep_prob: 0.5, batch_size: _batch_size})
# 计算测试数据的准确率
print("test accuracy %g" % sess.run(accuracy, feed_dict={
    _X: mnist.test.images, y: mnist.test.labels, keep_prob: 1.0, batch_size:mnist.test.images.shape[0]}))

不好理解的部分:
1. RNN里的正则化
2. tf.contrib.rnn.DropoutWrapper的理解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值