教你用PyTorch实现“看图说话”(附代码、学习资源)

本文用浅显易懂的方式解释了什么是“看图说话”(Image Captioning),借助github上的PyTorch代码带领大家自己做一个模型,并附带了很多相关的学习资源。

介绍

深度学习目前是一个非常活跃的领域---每天都会有许多应用出现。进一步学习Deep Learning最好的方法就是亲自动手。尽可能多的接触项目并且尝试自己去做。这将会帮助你更深刻地掌握各个主题,成为一名更好的Deep Learning实践者。

这篇文章将和大家一起看一个有趣的多模态主题,我们将结合图像和文本处理技术来构建一个有用的深度学习应用,即看图说话(Image Captioning)。看图说话是指从一个图像中基于其中的对象和动作生成文本描述的过程。例如:

这种过程在现实生活中有很多潜在的应用场景。一个明显的应用比如保存图片的描述字幕,以便该图片随后可以根据这个描述轻松地被检索出来。

我们开始吧!

注意: 本文假定你了解深度学习的基础知识,以前曾使用CNN处理过图像问题。如果想复习这些概念,可以先阅读下面的文章:

  • Fundamentals of Deep Learning – Starting with Artificial Neural Network
  • Architecture of Convolutional Neural Networks (CNNs) demystified
  • Tutorial: Optimizing Neural Networks using Keras (with Image recognition case study)
  • Essentials of Deep Learning – Sequence to Sequence modelling with Attention (using python)

目录

  • 什么是Image Captioning问题?
  • 解决任务的方法
  • 应用演练
  • 下一步工作

什么是Image Captioning问题?

设想你看到了这张图:

你首先想到的是什么?下面是一些人们可以想到的句子:

A man and a girl sit on the ground and eat . (一个男人和一个女孩坐在地上吃东西) A man and a little girl are sitting on a sidewalk near a blue bag eating . (一个男人和一个小女孩坐在蓝色包旁边的人行道上吃东西) A man wearing a black shirt and a little girl wearing an orange dress share a treat .(一个穿黑色衬衣的男人和一个穿橘色连衣裙的小女孩分享美食)

快速看一眼就足以让你理解和描述图片中发生的事情。从一个人造系统中自动生成这种文字描述就是Image Captioning的任务。

该任务很明确,即产生的输出是用一句话来描述这幅图片中的内容---存在的对象,属性,正在发生的动作以及对象之间的互动等。但是与其他图像处理问题一样,在人造系统中再现这种行为也是一项艰巨的任务。因此需要使用像Deep Learning这样先进复杂的技术来解决该任务。

在继续下文之前,我想特别感谢Andrej Kartpathy等学者,他们富有洞察力的课程CS231n帮助我理解了这个主题。

解决任务的方法

可以把image captioning任务在逻辑上分为两个模块——一个是基于图像的模型,从图像中提取特征和细微的差别, 另一个是基于语言的模型,将第一个模型给出的特征和对象翻译成自然的语句。

对于基于图像的模型而言(即编码器)我们通常依靠CNN网络。对于基于语言的模型而言(即解码器),我们依赖RNN网络。下图总结了前面提到的方法:

通常,一个预先训练好的CNN网络从输入图像中提取特征。特征向量被线性转换成与RNN/LSTM网络的输入具有相同的维度。这个网络被训练作为我们特征向量的语言模型。

为了训练LSTM模型,我们预先定义了标签和目标文本。比如,如果字幕是A man and a girl sit on the ground and eat .(一个男人和一个女孩坐在地上吃东西),则我们的标签和目标文本如下:

这样做是为了让模型理解我们标记序列的开始和结束。

具体实现案例

让我们看一个Pytorch中image captioning的简单实现。我们将以一幅图作为输入,然后使用深度学习模型来预测它的描述。

例子的代码可以在GitHub上找到。代码的原始作者是Yunjey Choi 向他杰出的pytorch例子致敬。

在本例中,一个预先训练好的ResNet-152被用作编码器,而解码器是一个LSTM网络。

要运行本例中的代码,你需要安装必备软件,确保有一个可以工作的python环境,最好使用anaconda。然后运行以下命令来安装其他所需要的库。

git clone https://github.com/pdollar/coco.git cd coco/PythonAPI/ make python setup.py build python setup.py install cd ../../ git clone https://github.com/yunjey/pytorch-tutorial.git cd pytorch-tutorial/tutorials/03-advanced/image_captioning/ pip install -r requirements.txt

设置完系统后,就该下载所需的数据集并且训练模型了。这里我们使用的是MS-COCO数据集。可以运行如下命令来自动下载数据集:

chmod +x download.sh ./download.sh

现在可以继续并开始模型的构建过程了。首先,你需要处理输入:

# Search for all the possible words in the dataset and # build a vocabulary list python build_vocab.py # resize all the images to bring them to shape 224x224 python resize.py

现在,运行下面的命令来训练模型:

python train.py --num_epochs 10 --learning_rate 0.01

来看一下被封装好的代码中是如何定义模型的,可以在model.py文件中找到:

import torch import torch.nn as nn import torchvision.models as models from torch.nn.utils.rnn import pack_padded_sequence from torch.autograd import Variable

class EncoderCNN(nn.Module): def __init__(self, embed_size): """Load the pretrained ResNet-152 and replace top fc layer.""" super(EncoderCNN, self).__init__() resnet = models.resnet152(pretrained=True) modules = list(resnet.children())[:-1] # delete the last fc layer. self.resnet = nn.Sequential(*modules) self.linear = nn.Linear(resnet.fc.in_features, embed_size) self.bn = nn.BatchNorm1d(embed_size, momentum=0.01) self.init_weights() def init_weights(self): """Initialize the weights.""" self.linear.weight.data.normal_(0.0, 0.02) self.linear.bias.data.fill_(0) def forward(self, images): """Extract the image feature vectors.""" features = self.resnet(images) features = Variable(features.data) features = features.view(features.size(0), -1) features = self.bn(self.linear(features)) return features class DecoderRNN(nn.Module): def __init__(self, embed_size, hidden_size, vocab_size, num_layers): """Set the hyper-parameters and build the layers.""" super(DecoderRNN, self).__init__() self.embed = nn.Embedding(vocab_size, embed_size) self.lstm = nn.LSTM(embed_size, hidden_size, num_layers, batch_first=True) self.linear = nn.Linear(hidden_size, vocab_size) self.init_weights() def init_weights(self): """Initialize weights.""" self.embed.weight.data.uniform_(-0.1, 0.1) self.linear.weight.data.uniform_(-0.1, 0.1) self.linear.bias.data.fill_(0) def forward(self, features, captions, lengths): """Decode image feature vectors and generates captions.""" embeddings = self.embed(captions) embeddings = torch.cat((features.unsqueeze(1), embeddings), 1) packed = pack_padded_sequence(embeddings, lengths, batch_first=True) hiddens, _ = self.lstm(packed) outputs = self.linear(hiddens[0]) return outputs def sample(self, features, states=None): """Samples captions for given image features (Greedy search).""" sampled_ids = [] inputs = features.unsqueeze(1) for i in range(20): # maximum sampling length hiddens, states = self.lstm(inputs, states) # (batch_size, 1, hidden_size), outputs = self.linear(hiddens.squeeze(1)) # (batch_size, vocab_size) predicted = outputs.max(1)[1] sampled_ids.append(predicted) inputs = self.embed(predicted) inputs = inputs.unsqueeze(1) # (batch_size, 1, embed_size) sampled_ids = torch.cat(sampled_ids, 1) # (batch_size, 20) return sampled_ids.squeeze()

现在测试我们的模型:

python sample.py --image='png/example.png'

对于样例图片,我们的模型给出了这样的输出:

<start> a group of giraffes standing in a grassy area . <end> <start>一群长颈鹿站在草地上<end>

以上就是如何建立一个用于image captioning的深度学习模型。

下一步工作

以上模型只是冰山一角。关于这个主题已经有很多的研究。目前在image captioning领域最先进的模型是微软的CaptionBot。可以在他们的官网上看一个系统的demo.

我列举一些可以用来构建更好的image captioning模型的想法:

  • 加入更多数据 当然这也是深度学习模型通常的趋势。提供的数据越多,模型效果越好。可以在这里找到其他的数据集: http://www.cs.toronto.edu/~fidler/slides/2017/CSC2539/Kaustav_slides.pdf
  • 使用Attention模型 正如这篇文章所述(Essentials of Deep Learning – Sequence to Sequence modelling with Attention), 使用attention模型有助于微调模型的性能
  • 转向更大更好的技术 研究人员一直在研究一些技术,比如使用强化学习来构建端到端的深度学习系统,或者使用新颖的attention模型用于“视觉哨兵(visual sentinel)”。

结语

这篇文章中,我介绍了image captioning,这是一个多模态任务,它由解密图片和用自然语句描述图片两部分组成。然后我解释了解决该任务用到的方法并给出了一个应用演练。 对于好奇心强的读者,我还列举了几条可以改进模型性能的方法。

希望这篇文章可以激励你去发现更多可以用深度学习解决的任务,从而在工业中出现越来越多的突破和创新。如果有任何建议/反馈,欢迎在下面的评论中留言!

原文标题:Automatic Image Captioning using Deep Learning (CNN and LSTM) in PyTorch

原文链接:https://www.analyticsvidhya.com/blog/2018/04/solving-an-image-captioning-task-using-deep-learning/

译者简介

和中华,留德软件工程硕士。由于对机器学习感兴趣,硕士论文选择了利用遗传算法思想改进传统kmeans。目前在杭州进行大数据相关实践。加入数据派THU希望为IT同行们尽自己一份绵薄之力,也希望结交许多志趣相投的小伙伴。

翻译组招募信息

工作内容:将选取好的外文前沿文章准确地翻译成流畅的中文。如果你是数据科学/统计学/计算机专业的留学生,或在海外从事相关工作,或对自己外语水平有信心的朋友,数据派翻译组欢迎你们加入!

你能得到:提高对于数据科学前沿的认知,提高对外文新闻来源渠道的认知,海外的朋友可以和国内技术应用发展保持联系,数据派团队产学研的背景为志愿者带来好的发展机遇。

其他福利:和来自于名企的数据科学工作者,北大清华以及海外等名校学生共同合作、交流。

原文发布于微信公众号 - 数据派THU(DatapiTHU)

原文发表时间:2018-04-25

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏灯塔大数据

原创译文 | 为网络新人而准备——七步理解深度学习

导读:上一期给大家介绍让你成为优秀数据科学家的42个步骤。深入掌握数据准备,机器学习,SQL数据科学等。今天我们从细节上来把握,七步进入深度学习(文末更多往期译...

3417

关于情绪分析项目的10个提议

在我的统计学硕士学位论文项目过程中,我专注于情感分析的问题。情感分析是自然语言处理的一个应用,目的是识别情感(积极的vs消极的vs中性的),主观性(客观的vs主...

2176
来自专栏PPV课数据科学社区

【译】从文本挖掘和机器学习中洞悉数据

版权申明 作者:Murat Yazici 原文链接:http://www.ibmbigdatahub.com/b ... rning 翻译:星星 ...

2699
来自专栏专知

【下载】最新TensorFlow深度学习教程指引《Learning TensorFlow,构建深度学习系统指引》

【导读】受大脑的启发,用大量数据训练的深神经网络可以以前所未有的精度解决复杂的任务。这本实用的书提供了一个端到端的TensorFlow实践指导,帮助你构建和计算...

3527
来自专栏杨熹的专栏

怎样做情感分析

本文结构: 什么是情感分析? 怎么分析,技术上如何实现? ---- cs224d Day 7: 项目2-命名实体识别 2016课程地址 项目描述地址 ----...

3435
来自专栏专知

从换脸到换姿势,AI 在图像处理的道路上越走越魔幻

【导读】加州大学伯克利分校的研究人员,近日在著名预印本网站 arXive 上,发布了最新的图像迁移成果:人体姿势和舞蹈动作迁移。旨在把专业舞蹈演员的动作迁移到不...

1215
来自专栏CDA数据分析师

导论丨图说深度学习丨神经网络和 TensorFlow (附视频中字)

CDA字幕组 编译整理 本文为 CDA 数据分析师原创作品,转载需授权 Youtube数据科学领域的热门博主sentdex,经常会分享关于Python和机器学习...

2298
来自专栏人工智能

基于深度学习的语音增强-极简源代码

最近忙里偷闲,想把博士期间的基于深度学习的语音增强的代码整理下。想当初需要在C++,perl和matlab之间来回切换,同时需要准备pfile这个上世纪产物,十...

5616
来自专栏WOLFRAM

Mathematica 11 在偏微分方程中的应用

2273
来自专栏PPV课数据科学社区

写给大家看的机器学习书(第二篇)

作者:徐晗曦 来源:https://zhuanlan.zhihu.com/p/25439997 在《写给大家看的机器学习书》的第一篇,我们了解了机器学习的基本...

3257

扫码关注云+社区