在 TensorFlow 中使用多对多 LSTM 进行视频分类

Posted

技术标签:

【中文标题】在 TensorFlow 中使用多对多 LSTM 进行视频分类【英文标题】:Video classification using many to many LSTM in TensorFlow 【发布时间】:2018-07-12 05:09:12 【问题描述】:

我必须构建一个二元分类器来预测输入视频是否包含动作。 模型的输入将是形状:[batch, frames, height, width, channel] 在这里,batch 是视频的数量,frames 是该视频中的图像数量(对于每个视频都是固定的),height 是该图像中的行数,width 是该图像中的列数,channel 是 RGB 颜色。 我在 Andrej Karpathy 博客中发现多对多递归神经网络最适合此应用程序:http://karpathy.github.io/2015/05/21/rnn-effectiveness/

因此,我需要在 TensorFlow 中实现:

我通过本教程学习了如何实现 LSTM:https://github.com/nlintz/TensorFlow-Tutorials/blob/master/07_lstm.py#L52 但是,它只使用最后一个张量来实现多对一 LSTM 并预测输出并减少损失:outputs[-1] 而且,我想使用许多张量(比如说 4 个)来预测输出并使用它们来减少损失。

这是我的实现:

import tensorflow as tf
from tensorflow.contrib import rnn
import numpy as np

# Training Parameters
batch = 5 # number of examples
frames = time_step_size = 20
height = 60
width = 80
channel = 3

lstm_size = 240
num_classes = 2

# Creating random data

input_x = np.random.normal(size=[batch, frames, height, width, channel])
input_y = np.zeros((batch, num_classes))
B = np.ones(batch)
input_y[:,1] = B

X = tf.placeholder("float", [None, frames, height, width, channel], name='InputData')
Y = tf.placeholder("float", [None, num_classes], name='LabelData')

with tf.name_scope('Model'):
    XR = tf.reshape(X, [-1, height*width*channel]) # shape=(?, 14400)
    X_split3 = tf.split(XR, time_step_size, 0) # 20 tensors of shape=(?, 14400)

    lstm = rnn.BasicLSTMCell(lstm_size, forget_bias=1.0, state_is_tuple=True)
    outputs, _states = rnn.static_rnn(lstm, X_split3, dtype=tf.float32) # 20 tensors of shape=(?, 240)
    logits = tf.layers.dense(outputs[-1], num_classes, name='logits') # shape=(?, 2)

prediction = tf.nn.softmax(logits)

# Define loss and optimizer
with tf.name_scope('Loss'):
    loss_op = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=Y))

with tf.name_scope('optimizer'):
    optimizer = tf.train.AdamOptimizer(learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-08, use_locking=False, name='Adam')
train_op = optimizer.minimize(loss_op)

# Evaluate model (with test logits, for dropout to be disabled)
correct_pred = tf.equal(tf.argmax(prediction, 1), tf.argmax(Y, 1))
with tf.name_scope('Accuracy'):
    accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    logits_output = sess.run(logits, feed_dict=X: input_x)
    print(logits_output.shape) # shape=(5, 2)

    sess.run(train_op, feed_dict=X: input_x, Y: input_y)

    loss, acc = sess.run([loss_op, accuracy], feed_dict=X: input_x, Y: input_y)
    print("Loss: ", loss) # loss:  1.46626135e-05
    print("Accuracy: ", acc) # Accuracy:  1.0

问题: 1. 我需要帮助来实现多对多 LSTM 并预测某些帧后的输出(比如说 4),但是,我只使用最后一个张量 outputs[-1] 来减少损失。有 20 个张量,framestime_step_size 各一个。如果我每 5 个张量变换一次:outputs[4], outputs[9], outputs[14], outputs[-1],我将得到 4 个 logits。那么,我将如何减少这四个方面的损失呢? 2. 另一个问题是,我必须实现二元分类器,但我只有想要识别的动作视频。因此,input_y 是标签的一种热门表示形式,其中第一列始终为 0,第二列始终为 1(我必须确定的操作),并且我没有任何示例视频,其中第一列的值为 1。你认为它会起作用吗? 3. 为什么在上面的实现中,仅在一次迭代中精度为 1?

谢谢

【问题讨论】:

你应该考虑序列到序列模型,像这样tensorflow.org/tutorials/seq2seq 【参考方案1】:

对于 1.,Dense 采用任意数量的批次维度,因此您应该能够一次将所有步骤转换为 logits(然后同样对批次进行操作,直到您获得每个步骤的最终损失,然后聚合,例如取平均值)。

对于 2. 和 3.,您似乎需要找到一些反面例子。有一篇关于“积极和未标记 (PU)”学习和“一类分类”的文献可能会有所帮助。

【讨论】:

步数是指张量(outputs)吗?我正在使用 tf.layers.dense(outputs[-1], num_classes, name='logits') 将最后一个张量 (outputs[-1]) 转换为 logits。有 20 个张量,framestime_step_size 各一个。如果我每 5 个张量变换一次:outputs[4], outputs[9], outputs[14], outputs[-1],我将得到 4 个 logits。那么,我将如何减少这四个方面的损失呢?我不确定您所说的“批量操作,直到每一步都得到最终损失,然后聚合,例如取平均值”是什么意思。你能不能给一些代码来解释一下。

以上是关于在 TensorFlow 中使用多对多 LSTM 进行视频分类的主要内容,如果未能解决你的问题,请参考以下文章

Keras 中的多对一和多对多 LSTM 示例

我们如何在 Keras 中定义一对一、一对多、多对一和多对多的 LSTM 神经网络? [复制]

多对多 lstm 实现 - 值错误

为二进制分类调整 tensorflow LSTM 代码

多对多时间序列预测问题的 RNN 架构

具有不同序列长度的多对多序列预测