教你用PyTorch實現「看圖說話」(附代碼、學習資源)

2021-01-14 數據派THU

作者:FAIZAN SHAIKH

翻譯:和中華

校對:白靜

本文共2200字,建議閱讀10分鐘

本文用淺顯易懂的方式解釋了什麼是「看圖說話」(Image Captioning),藉助github上的PyTorch代碼帶領大家自己做一個模型,並附帶了很多相關的學習資源。


介紹


深度學習目前是一個非常活躍的領域---每天都會有許多應用出現。進一步學習DeepLearning最好的方法就是親自動手。儘可能多的接觸項目並且嘗試自己去做。這將會幫助你更深刻地掌握各個主題,成為一名更好的DeepLearning實踐者。


這篇文章將和大家一起看一個有趣的多模態主題,我們將結合圖像和文本處理技術來構建一個有用的深度學習應用,即看圖說話(ImageCaptioning)。看圖說話是指從一個圖像中基於其中的對象和動作生成文本描述的過程。例如:



這種過程在現實生活中有很多潛在的應用場景。一個明顯的應用比如保存圖片的描述字幕,以便該圖片隨後可以根據這個描述輕鬆地被檢索出來。


我們開始吧!


注意: 本文假定你了解深度學習的基礎知識,以前曾使用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問題?

解決任務的方法

應用演練

下一步工作


什麼是ImageCaptioning問題?


設想你看到了這張圖:



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


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 .(一個穿黑色襯衣的男人和一個穿橘色連衣裙的小女孩分享美食)


快速看一眼就足以讓你理解和描述圖片中發生的事情。從一個人造系統中自動生成這種文字描述就是ImageCaptioning的任務。


該任務很明確,即產生的輸出是用一句話來描述這幅圖片中的內容---存在的對象,屬性,正在發生的動作以及對象之間的互動等。但是與其他圖像處理問題一樣,在人造系統中再現這種行為也是一項艱巨的任務。因此需要使用像DeepLearning這樣先進複雜的技術來解決該任務。


在繼續下文之前,我想特別感謝AndrejKartpathy等學者,他們富有洞察力的課程CS231n幫助我理解了這個主題。


解決任務的方法


可以把imagecaptioning任務在邏輯上分為兩個模塊——一個是基於圖像的模型,從圖像中提取特徵和細微的差別,另一個是基於語言的模型,將第一個模型給出的特徵和對象翻譯成自然的語句。


對於基於圖像的模型而言(即編碼器)我們通常依靠CNN網絡。對於基於語言的模型而言(即解碼器),我們依賴RNN網絡。下圖總結了前面提到的方法:



通常,一個預先訓練好的CNN網絡從輸入圖像中提取特徵。特徵向量被線性轉換成與RNN/LSTM網絡的輸入具有相同的維度。這個網絡被訓練作為我們特徵向量的語言模型。


為了訓練LSTM模型,我們預先定義了標籤和目標文本。比如,如果字幕是Aman and a girl sit on the ground and eat .(一個男人和一個女孩坐在地上吃東西),則我們的標籤和目標文本如下:




這樣做是為了讓模型理解我們標記序列的開始和結束。



具體實現案例


讓我們看一個Pytorch中imagecaptioning的簡單實現。我們將以一幅圖作為輸入,然後使用深度學習模型來預測它的描述。


例子的代碼可以在GitHub上找到。代碼的原始作者是YunjeyChoi 向他傑出的pytorch例子致敬。


在本例中,一個預先訓練好的ResNet-152被用作編碼器,而解碼器是一個LSTM網絡。



要運行本例中的代碼,你需要安裝必備軟體,確保有一個可以工作的python環境,最好使用anaconda。然後運行以下命令來安裝其他所需要的庫。


gitclone https://github.com/pdollar/coco.git


cdcoco/PythonAPI/

make

pythonsetup.py build

pythonsetup.py install


cd../../


gitclone https://github.com/yunjey/pytorch-tutorial.git

cdpytorch-tutorial/tutorials/03-advanced/image_captioning/


pipinstall -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

pythonbuild_vocab.py  



#resize all the images to bring them to shape 224x224

pythonresize.py


現在,運行下面的命令來訓練模型:


pythontrain.py --num_epochs 10 --learning_rate 0.01


來看一下被封裝好的代碼中是如何定義模型的,可以在model.py文件中找到:


importtorch

importtorch.nn as nn

importtorchvision.models as models

fromtorch.nn.utils.rnn import pack_padded_sequence

fromtorch.autograd import Variable


classEncoderCNN(nn.Module):

   def__init__(self, embed_size):

       """Loadthe 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()

       

   definit_weights(self):

       """Initializethe weights."""

       self.linear.weight.data.normal_(0.0,0.02)

       self.linear.bias.data.fill_(0)

       

   defforward(self, images):

       """Extractthe image feature vectors."""

       features= self.resnet(images)

       features= Variable(features.data)

       features= features.view(features.size(0), -1)

       features= self.bn(self.linear(features))

       returnfeatures

   

classDecoderRNN(nn.Module):

   def__init__(self, embed_size, hidden_size, vocab_size, num_layers):

       """Setthe 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()

   

   definit_weights(self):

       """Initializeweights."""

       self.embed.weight.data.uniform_(-0.1,0.1)

       self.linear.weight.data.uniform_(-0.1,0.1)

       self.linear.bias.data.fill_(0)

       

   defforward(self, features, captions, lengths):

       """Decodeimage 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])

       returnoutputs

   

   defsample(self, features, states=None):

       """Samplescaptions for given image features (Greedy search)."""

       sampled_ids= []

       inputs= features.unsqueeze(1)

       fori in range(20):                                    # maximum samplinglength

           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)

       returnsampled_ids.squeeze()


現在測試我們的模型:


pythonsample.py --image='png/example.png'


對於樣例圖片,我們的模型給出了這樣的輸出:



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

<start>一群長頸鹿站在草地上<end>


以上就是如何建立一個用於imagecaptioning的深度學習模型。


下一步工作


以上模型只是冰山一角。關於這個主題已經有很多的研究。目前在imagecaptioning領域最先進的模型是微軟的CaptionBot。可以在他們的官網上看一個系統的demo.


我列舉一些可以用來構建更好的imagecaptioning模型的想法:


加入更多數據 當然這也是深度學習模型通常的趨勢。提供的數據越多,模型效果越好。可以在這裡找到其他的數據集: 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)」。


結語


這篇文章中,我介紹了imagecaptioning,這是一個多模態任務,它由解密圖片和用自然語句描述圖片兩部分組成。然後我解釋了解決該任務用到的方法並給出了一個應用演練。對於好奇心強的讀者,我還列舉了幾條可以改進模型性能的方法。


希望這篇文章可以激勵你去發現更多可以用深度學習解決的任務,從而在工業中出現越來越多的突破和創新。如果有任何建議/反饋,歡迎在下面的評論中留言!


原文標題: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 ID:DatapiTHU),並在文章結尾放置數據派醒目二維碼。有原創標識文章,請發送【文章名稱-待授權公眾號名稱及ID】至聯繫郵箱,申請白名單授權並按要求編輯。

發布後請將連結反饋至聯繫郵箱(見下方)。未經許可的轉載以及改編者,我們將依法追究其法律責任。

相關焦點

  • 雲計算學習:用PyTorch實現一個簡單的分類器
    所以我總結了一下自己當初學習的路線,準備繼續深入鞏固自己的 pytorch 基礎;另一方面,也想從頭整理一個教程,從沒有接觸過 pytorch 開始,到完成一些最新論文裡面的工作。以自己的學習筆記整理為主線,大家可以針對參考。第一篇筆記,我們先完成一個簡單的分類器。
  • 用Java實現目標檢測|PyTorch
    魚羊 編輯整理量子位 報導 | 公眾號 QbitAI編者按:作為一個Java開發者,你是否曾為在PyTorch上部署模型而苦惱?這篇來自AWS軟體工程師的投稿,結合實例,詳細介紹了DJL這個為Java開發者設計的深度學習庫:5分鐘,你就能在PyTorch上,用Java實現目標檢測。
  • 用Java實現目標檢測 | PyTorch
    這篇來自AWS軟體工程師的投稿,結合實例,詳細介紹了DJL這個為Java開發者設計的深度學習庫:5分鐘,你就能在PyTorch上,用Java實現目標檢測。5分鐘,用Java實現目標檢測文 / 知乎用戶@LankingPyTorch在深度學習領域中的應用日趨廣泛,得益於它獨到的設計。
  • 華為雲應用編排,手把手教您完成pytorch代碼部署
    背景介紹PyTorch是由Facebook人工智慧研究院於 2017 年 1 月在github上開源的深度學習框架,一經開源就迅速吸引了人們的眼球。其歷史可以追溯至 2002 年使用Lua語言的Torch框架,並由其幕後團隊一手打造。
  • 手把手教你用PyTorch實現圖像分類器(第一部分)
    翻譯 | 醬番梨、Succi         校對 | 醬番梨        審核 | 醬番梨       整理 | 立魚王原文連結:https://medium.com/udacity/implementing-an-image-classifier-with-pytorch-part
  • PyTorch最佳實踐,教你寫出一手風格優美的代碼
    選自github 本文轉自機器之心(nearhuman2014) PyTorch是最優秀的深度學習框架之一,它簡單優雅,非常適合入門。本文將介紹PyTorch的最佳實踐和代碼風格都是怎樣的。
  • 一行代碼安裝,TPU也能運行PyTorch,修改少量代碼即可快速移植
    曉查 發自 凹非寺量子位 報導 | 公眾號 QbitAI對於PyTorch開發者來說,Google Colab上的TPU資源不能用,恐怕是最遺憾的事情了。Google的雲計算資源眼看著不能用,轉TensorFlow又是不可能的。過去一直有PyTorch用戶試圖在Colab上薅羊毛,但是都沒有太成功的。
  • 獨家 | 教你使用torchlayers 來構建PyTorch 模型(附連結)
    附連結:https://github.com/szymonmaszke/torchlayers與Keras中的操作類似,上述的操作不需要用戶幹預(除了調用一次torchlayers.build)。Keras的模型構建提供了一些有用的功能,並填補了一個明顯的空白。
  • 重磅| Torch7團隊開源PyTorch:Python優先的深度學習框架
    據官網介紹,PyTorch 是一個 Python 優先的深度學習框架,能夠在強大的 GPU 加速基礎上實現張量和動態神經網絡。你可以像使用 numpy / scipy / scikit-learn 那樣輕鬆地使用 PyTorch。你可以用你喜歡的庫和包(如 Cython 和 Numba)在 Python 中編寫新的神經網絡層。我們的目標是儘量讓你不用重新發明輪子。命令式體驗PyTorch 的設計思路是線性、直觀且易於使用。當你需要執行一行代碼時,它會忠實執行。PyTorch 沒有異步的世界觀。
  • Keras vs PyTorch:誰是第一深度學習框架?
    兩大框架的連結:  Keras:https://github.com/keras-team/keras (https://keras.io/)  PyTorch:https://github.com/pytorch/pytorch  你想學習深度學習嗎?
  • 還不會使用PyTorch框架進行深度學習的小夥伴,看過來
    如果你想要跟蹤這個類的所有操作,請將「.requires_grad」設置為 True。如果要計算所有的梯度,請調用「.backward()」。這個張量的梯度將在「.grad」屬性中積累。如果你想要從計算歷史中分離出一個張量,請調用「.detach()」函數。這也可以防止將來對張量的計算被跟蹤。另一種防止歷史跟蹤的方法是用「torch.no_grad()」方法封裝代碼。
  • 一行代碼即可調用18款主流模型!PyTorch Hub輕鬆解決論文可復現性
    很多論文選擇隨文附上代碼和訓練模型,在一定程度上對使用者起到了幫助作用,但成效並不明顯。復現過程中,仍有大量工作需要論文讀者自己摸索。PyTorch Hub是什麼?近日,Facebook新推出了一個深度學習工具包:PyTorch Hub,這是一個簡單的API和工作流,提供基本的構建模塊從而可以改善機器學習研究的可重現性。
  • 分離硬體和代碼、穩定 API,PyTorch Lightning 1.0.0 版本正式發布
    William Falcon 表示自己非常期待有一天,當用戶查看 GitHub 上的複雜項目時,深度學習代碼不再那麼令人望而生畏。特斯拉 AI 負責人 Andrej Karpathy 也評論稱:「這看起來很棒,也很有前途。PyTorch Lightning 倡導對深度學習代碼進行重構,將『工程(硬體)』與『科學(代碼)』分割開,然後將前者委託給框架。」
  • PyTorch實現TPU版本CNN模型
    隨著深度學習模型在各種應用中的成功實施,現在是時候獲得不僅準確而且速度更快的結果。為了得到更準確的結果,數據的大小是非常重要的,但是當這個大小影響到機器學習模型的訓練時間時,這一直是一個值得關注的問題。為了克服訓練時間的問題,我們使用TPU運行時環境來加速訓練。為此,PyTorch一直在通過提供最先進的硬體加速器來支持機器學習的實現。
  • TensorFlow與PyTorch之爭,哪個框架最適合深度學習
    那麼究竟哪種框架最適宜自己手邊的深度學習項目呢?本文作者從這兩種框架各自的功能效果、優缺點以及安裝、版本更新等諸多方面給出了自己的建議。如果你在讀這篇文章,那麼你可能已經開始了自己的深度學習之旅。如果你對這一領域還不是很熟悉,那麼簡單來說,深度學習使用了「人工神經網絡」,這是一種類似大腦的特殊架構,這個領域的發展目標是開發出能解決真實世界問題的類人計算機。
  • 一篇文章教你用11行Python代碼實現神經網絡
    聲明:本文是根據英文教程 (用 11 行 Python 代碼實現的神經網絡)學習總結而來,關於更詳細的神經網絡的介紹可以參考我的另一篇博客:。A Neural Network in 11 lines of Python從感知機到人工神經網絡如果你讀懂了下面的文章,你會對神經網絡有更深刻的認識,有任何問題,請多指教。
  • 60分鐘入門深度學習工具PyTorch
    autograd包為張量上的所有操作提供了自動求導.它是一個運行時定義的框架,這意味著反向傳播是根據你的代碼如何運行來定義,並且每次迭代可以不同.要防止跟蹤歷史記錄(和使用內存),您還可以使用torch.no_grad包裝代碼塊:在評估模型時,這可能特別有用,因為模型可能具有requires_grad = True的可訓練參數,但我們不需要梯度。還有一個類對於autograd實現非常重要 - Function。
  • 代碼詳解:用Pytorch訓練快速神經網絡的9個技巧
    估計你還在用32位精度或*GASP(一般活動仿真語言)*訓練,甚至可能只在單GPU上訓練。如果市面上有99個加速指南,但你可能只看過1個?(沒錯,就是這樣)。但這份終極指南,會一步步教你清除模型中所有的(GP模型)。不要讓你的神經網絡變成這樣。(圖片來源:Monsters U)這份指南的介紹從簡單到複雜,一直介紹到你可以完成的大多數PITA修改,以充分利用你的網絡。
  • Keras vs PyTorch,哪一個更適合做深度學習?
    工具應該和你的思考方式和代碼樣式同步。因此要想找到適合自己的工具,首先你要多嘗試不同的工具。我們同時用 Keras 和 PyTorch 訓練一個簡單的模型。如果你是深度學習初學者,對有些概念無法完全理解,不要擔心。從現在開始,專注於這兩個框架的代碼樣式,儘量去想像哪個最適合你,使用哪個工具你最舒服,也最容易適應。
  • 使用PyTorch進行主動遷移學習:讓模型預測自身的錯誤
    本文詳細說明主動遷移學習, 它是主動學習和遷移學習技術的結合,本文將實現書籍  Human-in-the-Loop Machine Learning 中的所有用到 PyTorch 的方法。,包括本文中介紹的新算法:github 網址:https://github.com/rmunro/pytorch_active_learning理想情況下,你應該在接觸本文中更高級的方法之前,親自嘗試實現更簡單的主動學習策略。