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

简介:

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

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

1c2e99c2a37e49b28a7764a261eca806129fa141

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

我们开始吧!

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

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

目录

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

什么是Image Captioning问题?

设想你看到了这张图:

c266ad549b66855fbc2642bd36606f7a99abffd9

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

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网络。下图总结了前面提到的方法:

1fda53aceaab690616843f2ffe7b7692f586cb47

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

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

3f91eca1446556c79209ab771b3558320d01790b

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

89f626118290cb081f7a8eb26c03e73f354f9c5a

具体实现案例

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

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

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

1adcf08610274ed85f78e6f0b57adb0e24d73b3a

要运行本例中的代码,你需要安装必备软件,确保有一个可以工作的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'

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

5968d0bfa8861e6ec88436450f8ee7a99256f844

<start> a group of giraffes standing in a grassy area . <end>

<start>一群长颈鹿站在草地上<end>

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

下一步工作

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

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

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

结语

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

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


原文发布时间为:2018-04-25

本文作者:FAIZAN SHAIKH

本文来自云栖社区合作伙伴“数据派THU”,了解相关信息可以关注“数据派THU”。

相关文章
|
25天前
|
机器学习/深度学习 算法 PyTorch
【PyTorch实战演练】自调整学习率实例应用(附代码)
【PyTorch实战演练】自调整学习率实例应用(附代码)
37 0
|
8月前
|
机器学习/深度学习 缓存 监控
Pytorch学习笔记(7):优化器、学习率及调整策略、动量
Pytorch学习笔记(7):优化器、学习率及调整策略、动量
319 0
Pytorch学习笔记(7):优化器、学习率及调整策略、动量
|
25天前
|
机器学习/深度学习 PyTorch 算法框架/工具
通过实例学习Pytorch加载权重.load_state_dict()与保存权重.save()
通过实例学习Pytorch加载权重.load_state_dict()与保存权重.save()
13 0
|
1月前
|
机器学习/深度学习 算法 PyTorch
PyTorch使用Tricks:学习率衰减 !!
PyTorch使用Tricks:学习率衰减 !!
37 0
|
1月前
|
机器学习/深度学习 算法 PyTorch
从零开始学习线性回归:理论、实践与PyTorch实现
从零开始学习线性回归:理论、实践与PyTorch实现
从零开始学习线性回归:理论、实践与PyTorch实现
|
3月前
|
机器学习/深度学习 PyTorch 语音技术
Pytorch迁移学习使用Resnet50进行模型训练预测猫狗二分类
深度学习在图像分类、目标检测、语音识别等领域取得了重大突破,但是随着网络层数的增加,梯度消失和梯度爆炸问题逐渐凸显。随着层数的增加,梯度信息在反向传播过程中逐渐变小,导致网络难以收敛。同时,梯度爆炸问题也会导致网络的参数更新过大,无法正常收敛。 为了解决这些问题,ResNet提出了一个创新的思路:引入残差块(Residual Block)。残差块的设计允许网络学习残差映射,从而减轻了梯度消失问题,使得网络更容易训练。
|
3月前
|
机器学习/深度学习 存储 PyTorch
使用pytorch构建图卷积网络预测化学分子性质
在本文中,我们将通过化学的视角探索图卷积网络,我们将尝试将网络的特征与自然科学中的传统模型进行比较,并思考为什么它的工作效果要比传统的方法好。
36 0
|
8月前
|
机器学习/深度学习 并行计算 PyTorch
迁移学习的 PyTorch 实现
迁移学习的 PyTorch 实现
|
4月前
|
机器学习/深度学习 PyTorch 调度
迁移学习的 PyTorch 实现
迁移学习的 PyTorch 实现
|
4月前
|
机器学习/深度学习 搜索推荐 数据可视化
PyTorch搭建基于图神经网络(GCN)的天气推荐系统(附源码和数据集)
PyTorch搭建基于图神经网络(GCN)的天气推荐系统(附源码和数据集)
89 0

热门文章

最新文章