专栏首页ATYUN订阅号利用TensorFlow生成图像标题

利用TensorFlow生成图像标题

图像标题生成器模型结合了计算机视觉和机器翻译的最新进展,利用神经网络生成现实的 图像标题。神经图像标题模型被训练,以最大限度地产生给定输入图像的字幕的可能性。并且可以用来生成新的图像描述。例如,下面是使用 MS COCO数据集.训练的神经图像标题生成器可能生成的标题。

在这篇文章中,我们将通过一个中级水平的教程,介绍如何使用谷歌的 Show和Tell 模型在Flickr30k数据集上训练图像标题生成器。我们使用 TensorFlow框架来构建、培训和测试我们的模型,因为它相对容易使用,并且拥有一个不断增长的在线社区。

为什么生成标题?

最近在计算机视觉和自然语言处理任务中应用深度神经网络的成功,启发了人工智能研究人员在这些以前分离领域的交集中探索新的研究机会。标题生成模型必须平衡对视觉线索和自然语言的理解。 这两个传统上不相关领域的交叉点有可能在很大程度上实现变革。虽然这项技术有一些简单的应用,比如为YouTube视频生成摘要,或为未标注的图像加标题,但更有创意的应用程序可以极大地提高大部分人的生活质量。与传统的计算机视觉试图使世界更容易访问和理解计算机一样,这项技术有潜力使我们的世界更容易理解。它可以作为一名导游,甚至可以作为日常生活的视觉辅助工具,比如来自意大利人工智能公司Eyra.的Horus 可穿戴设备

一些装配要求

在我们开始之前,我们需要做一些准备。 首先,您需要安装Tensorflow。如果这是你第一次使用Tensorflow,我们建议你先回顾一下下面的文章:Hello, TensorFlow! Building and training your first TensorFlow model.。 您将需要pandas、opencv2和Jupyter libraries来运行相关的代码。但是,为了简化安装过程,我们强烈建议您遵循GitHub  repo上的Docker安装指令。 您还需要下载图像嵌入和图片说明,用于Flickr30k数据集。下载链接也提供在GitHub   repo上。 现在,让我们开始吧!

图像标题生成器模型

我们将要培训的模型,每个图像将由一个深度卷积神经网络编码成一个4,096维向量表示。随后用一种生成RNN或递归神经网络的语言对其进行解码,以自然语言描述。

标题生成作为图像分类的扩展

图像分类是具有很多历史的计算机视觉任务,背后有许多强大的模型。要求模型可以将图像中呈现的形状和对象的相关视觉信息拼凑起来,将图像放入对象类别中。其他计算机视觉任务的机器学习模型,例如对象检测和图像分割等,不仅识别信息何时存在,而且还通过学习如何解释2D空间调和两种理解,确定物体的信息在图像中的位置。

利用转移学习

我们可以利用预先存在的模型来帮助标题图像。转移学习允许我们接受神经网络中不同任务的数据转换,并将其应用到我们的数据中。在我们的案例中,VGG-16图像分类模型采用224x224像素图像,生成一个4096维特征向量,用于对图像进行分类。 我们可以从VGG- 16模型中获取表示(称为图像嵌入),并使用它来训练我们的模型的其余部分。对于本文的范围,我们已经抽象了VGG- 16的架构,并预先计算了4,096维度的特性,以加速训练。 加载VGG图像特征和image 标题相对简单:

def get_data(annotation_path, feature_path):
    annotations = pd.read_table(annotation_path, sep='	', header=None, names=['image', 'caption'])
    return np.load(feature_path,'r'), annotations['caption'].values

了解标题

现在我们有了一个图像表示,我们需要我们的模型来学习将其解码成一个可以理解的标题。由于文本的串行特性,我们在RNN / LSTM网络中利用递归式(学习更多,阅读“理解 LSTM 网络”)。这些网络被训练用来预测在给定的单词和图像表示序列中的下一个单词。 长短期记忆(LSTM)细胞允许模型更好地选择在标题词序列中使用什么信息,记住什么,以及忘记哪些信息。TensorFlow提供了一个包装器函数,为给定的输入和输出维度生成一个LSTM层。 为了将单词转换为适合于LSTM输入的固定长度表示,我们使用嵌入层来学习将单词映射到256维特性(或单词嵌入)。单词嵌入帮助我们把单词表示为向量,类似的单词向量在语义上是相似的。要了解更多的词汇嵌入是如何捕捉不同单词之间的关系的,请参阅“利用深度学习获取语义含义”。链接地址为https://www.oreilly.com/learning/capturing-semantic-meanings-using-deep-learning 在VGG- 16图像分类器中,卷积层提取一个4,096维的表示,通过一个最终的softmax层进行分类。由于LSTM单元期望将256维文本特性作为输入,我们需要将图像表示转换为用于目标标题的表示。为此,我们利用另一个嵌入层,学习将4,096维图像特征映射到256维文本特征的空间中。

建立和训练模型

这就是 Show和Tell Model 的样子:

在这个图中,{ s0,s1,…,sN }代表我们试图预测的标题的单词和{ wes1,wes1,…,wesn - 1 }是每个单词的嵌入向量。LSTM的输出{ p1,p2,…pN }是由模型为句子中的下一个字生成的概率分布。通过训练将每个单词的对数概率的负和最小化。

def build_model(self):
        # declaring the placeholders for our extracted image feature vectors, our caption, and our mask
        # (describes how long our caption is with an array of 0/1 values of length `maxlen`  
        img = tf.placeholder(tf.float32, [self.batch_size, self.dim_in])
        caption_placeholder = tf.placeholder(tf.int32, [self.batch_size, self.n_lstm_steps])
        mask = tf.placeholder(tf.float32, [self.batch_size, self.n_lstm_steps])
        
        # getting an initial LSTM embedding from our image_imbedding
        image_embedding = tf.matmul(img, self.img_embedding) + self.img_embedding_bias
        
        # setting initial state of our LSTM
        state = self.lstm.zero_state(self.batch_size, dtype=tf.float32)

       total_ loss = 0.0
        with tf.variable_scope('RNN'):
            for i in range(self.n_lstm_steps): 
                if i > 0:
                   #if this isn't the first iteration of our LSTM we need to get the word_embedding corresponding
                   # to the (i-1)th word in our caption 
                    with tf.device('/cpu:0'):
                        current_embedding = tf.nn.embedding_lookup(self.word_embedding, caption_placeholder[:,i-1]) + self.embedding_bias
                else:
                     #if this is the first iteration of our LSTM we utilize the embedded image as our input 
                     current_embedding = image_embedding
                if i > 0: 
                    # allows us to reuse the LSTM tensor variable on each iteration
                    tf.get_variable_scope().reuse_variables()

                out, state = self.lstm(current_embedding, state)

                print (out,self.word_encoding,self.word_encoding_bias)
                
                if i > 0:
                    #get the one-hot representation of the next word in our caption 
                    labels = tf.expand_dims(caption_placeholder[:, i], 1)
                    ix_range=tf.range(0, self.batch_size, 1)
                    ixs = tf.expand_dims(ix_range, 1)
                    concat = tf.concat([ixs, labels],1)
                    onehot = tf.sparse_to_dense(
                            concat, tf.stack([self.batch_size, self.n_words]), 1.0, 0.0)

                    #perform a softmax classification to generate the next word in the caption
                    logit = tf.matmul(out, self.word_encoding) + self.word_encoding_bias
                    xentropy = tf.nn.softmax_cross_entropy_with_logits(logits=logit, labels=onehot)
                    xentropy = xentropy * mask[:,i]

                    loss = tf.reduce_sum(xentropy)
                    total_loss += loss

            total_loss = total_loss / tf.reduce_sum(mask[:,1:])
            return total_loss, img,  caption_placeholder, mask

使用推理生成标题

在训练之后,我们有一个模型,给出了一个单词出现在下一个标题的概率,给出了图像和之前的所有单词。我们如何使用这个来产生新的标题? 最简单的方法是输入一个输入图像,然后迭代输出下一个最可能的单词,建立一个标题。

def build_generator(self, maxlen, batchsize=1):
        #same setup as `build_model` function 
        img = tf.placeholder(tf.float32, [self.batch_size, self.dim_in])
        image_embedding = tf.matmul(img, self.img_embedding) + self.img_embedding_bias
        state = self.lstm.zero_state(batchsize,dtype=tf.float32)

       #declare list to hold the words of our generated captions
        all_words = []
        print (state,image_embedding,img)
        with tf.variable_scope('RNN'):
           # in the first iteration we have no previous word, so we directly pass in the image embedding
           # and set the `previous_word` to the embedding of the start token ([0]) for the future iterations
            output, state = self.lstm(image_embedding, state)
            previous_word = tf.nn.embedding_lookup(self.word_embedding, [0]) + self.embedding_bias

            for i in range(maxlen):
                tf.get_variable_scope().reuse_variables()

                out, state = self.lstm(previous_word, state)


               # get a one-hot word encoding from the output of the LSTM
                logit = tf.matmul(out, self.word_encoding) + self.word_encoding_bias
                best_word = tf.argmax(logit, 1)

                with tf.device('/cpu:0'):
                   # get the embedding of the best_word to use as input to the next iteration of our LSTM 
                    previous_word = tf.nn.embedding_lookup(self.word_embedding, best_word)

                previous_word += self.embedding_bias

                all_words.append(best_word)

        return img, all_words

在许多情况下,这是可行的,但通过“greedily”接受最可能的词语,我们最终可能不会得到最可能的标题。 一种可能的避免方法是使用一种叫做“Beam Search”的方法。这使得一个人可以在保持推理计算的同时探索更大的空间。在下面的例子中,该算法维护了一个k = 2候选句子的列表,其中每个垂直时间步由每个粗体字的路径显示。

限制和讨论

神经图像标题生成器为学习从图像映射到human-level图像标题提供了一个有用的框架。通过对大量图像描述对的训练,模型学习从视觉特征获取相关的语义信息。 然而,在静态图像中,嵌入我们的标题生成器将侧重于我们的图像的特征,这对图像分类很有用,不一定对标题生成有用。为了提高每个功能中包含的任务相关信息的数量,我们可以训练图像嵌入模型(VGG16网络用于编码特征)作为标题生成模型的一部分,允许我们对图像编码器进行微调,以更好地适应生成标题的作用。 另外,如果我们仔细观察所生成的标题,我们会注意到它们很平凡,很普通。拿这个可能的图片标题举例:

这绝对是“giraffe standing next to a tree.”。然而,如果我们看看其他的图片,我们可能会注意到,它会生成一张“a giraffe  next to a tree”的标题,因为长颈鹿在训练集中经常出现在树旁。 本文为编译文章,作者Raul  Puri和Daniel Ricciardelli,原网址为 https://www.oreilly.com/learning/caption-this-with-tensorflow

本文分享自微信公众号 - ATYUN订阅号(atyun_com),作者:项, 晓珊

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-07-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 谷歌开源AI图像分割模型,用Cloud TPU快速准确地进行图像分割

    自去年起,谷歌的TPU芯片是谷歌云平台客户可以使用的最新一代芯片,专为人工智能推理和训练任务量身定制,如图像识别,自然语言处理和强化学习。

    AiTechYun
  • DeepMind的人工智能系统学会了绘画

    近日,在伦敦举行的深度学习峰会会议上,DeepMind研究科学家Ali Eslami提出了一个非常有趣的项目,名为“人工智能和创造力”。

    AiTechYun
  • 刷脸付款才刚刚开始,刷静脉付款就来了

    如今,一部手机就可以解决支付问题,因此有越来越多的人出门不带钱包了。从密码付款到扫码付款,再到指纹付款。但是苹果在近日的新品发布会上展示的Face ID,使刷脸...

    AiTechYun
  • 手把手教你用TensorFlow实现看图说话 | 教程+代码

    王新民 编译整理 量子位 出品 | 公众号 QbitAI 看图说话这种技能,我们人类在幼儿园时就掌握了,机器们前赴后继学了这么多年,也终于可以对图像进行最简单的...

    量子位
  • 上线三年却很“鸡肋”的微信声音锁究竟做错了什么?

    栏目简介:激荡六十年,人工智能已经起航。然而在未来面前,我们都还是孩子。究竟是“奇点临近”?还是泡沫行将破灭?为了解惑,《AI名人堂》将汇聚领航者智慧,和你一起...

    AI科技大本营
  • 10.17 VR圈大事件:《Elle》杂志起用AR技术;PSVR被发现可兼容PC、Xbox和Wii U

    VRPinea
  • tensorflow ‘/biases/Adam_1’not in ckpt file

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_25737169/article/d...

    DoubleV
  • 第二十期技术雷达正式发布——给你有态度的技术解析!

    技术雷达是ThoughtWorks每半年发布一期的技术趋势报告,它不仅是一份持续的技术成熟度评估,其产生还源于ThoughtWorks另一个更大宏大的使命—IT...

    ThoughtWorks
  • 【机器学习笔记之二】决策树的python实现

    本文结构: 是什么? 有什么算法? 数学原理? 编码实现算法? ---- 1. 是什么? 简单地理解,就是根据一些 feature 进行分类,每个节点提一个问题...

    Angel_Kitty
  • Smart template的控件能否当成普通控件来用

    只要弄清楚Smart control的原理,就能回答这个问题。

    Jerry Wang

扫码关注云+社区

领取腾讯云代金券