利用Microsoft COCO数据集和pytorch实现看图说话

对于没有GPU的同学,本文建议在Google Colab环境下进行代码编程。

本文用浅显易懂的方式解释了什么是“看图说话”(Image Captioning),借助Github上的PyTorch代码带领大家自己做一个模型。

介绍

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

这篇文章将和大家一起看一个有趣的多模态主题,我们将结合图像和文本处理技术来构建一个有用的深度学习应用,即看图说话(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网络。

git clone https://github.com/cocodataset/cocoapi

cd coco/PythonAPI/ make python setup.py build python setup.py install

cd …/…/

git clone https://github.com/yunjey/pytorch-tutorial
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)”。

参考文献
  • https://www.analyticsvidhya.com/blog/2018/04/solving-an-image-captioning-task-using-deep-learning/
  • https://zhuanlan.zhihu.com/p/36282198
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
你可以使用以下步骤在 PyTorch 中下载和使用 COCO 数据集: 1. 安装 COCO API: ```python !pip install pycocotools ``` 2. 下载 COCO 数据集: ```python !wget http://images.cocodataset.org/zips/train2017.zip !wget http://images.cocodataset.org/zips/val2017.zip !wget http://images.cocodataset.org/annotations/annotations_trainval2017.zip ``` 3. 解压数据集: ```python !unzip train2017.zip !unzip val2017.zip !unzip annotations_trainval2017.zip ``` 4. 使用 PyTorch 中的 `torchvision.datasets.CocoDetection` 加载数据集: ```python import torchvision.datasets as dset import torchvision.transforms as transforms train_transforms = transforms.Compose([ transforms.Resize((256, 256)), transforms.RandomCrop((224, 224)), transforms.RandomHorizontalFlip(), transforms.ToTensor() ]) val_transforms = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor() ]) train_dataset = dset.CocoDetection(root='./train2017', annFile='./annotations/instances_train2017.json', transform=train_transforms) val_dataset = dset.CocoDetection(root='./val2017', annFile='./annotations/instances_val2017.json', transform=val_transforms) ``` 其中,`root` 参数指定数据集的根目录,`annFile` 参数指定 COCO 数据集的注释文件路径,`transform` 参数指定数据增强和转换方式。 5. 使用 PyTorch 中的 `torch.utils.data.DataLoader` 加载数据集: ```python train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True) val_loader = torch.utils.data.DataLoader(val_dataset, batch_size=32, shuffle=False) ``` 其中,`batch_size` 参数指定每个批次的大小,`shuffle` 参数指定是否打乱数据集顺序。 现在,你就可以在 PyTorch 中使用 COCO 数据集进行训练和测试了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安替-AnTi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值