玩過圖像分類的開發者不少,許多人或許對圖像分割(image segmentation)也不陌生,但圖像注解(image caption)的難度,無疑比前兩者更進一步。
原因無他:利用神經網絡來生成貼合實際的圖像注釋,需要結合最新的計算機視覺和機器翻譯技術,缺一不可。對于為輸入圖像生成文字注解,訓練神經圖像注解模型能使其成功幾率最大化,并能生成新奇的圖像描述。舉個例子,下圖便是在 ms coco 資料集上訓練的神經圖像注解生成器,所輸出的潛在注解。
左圖注解:一個灰衣男子揮舞棒子,黑衣男子旁觀;右圖注解:一輛大巴車“坐”在一個人旁邊
本文是一篇中級教程,旨在教給大家如何在 flickr30k 資料集上訓練圖像注解生成模型,使用的是谷歌 show and tell 模型的變體。我們使用 tensorflow 架構來建立、訓練、測試模型,因為 tensorflow 相對容易使用,并且有不斷增長的龐大使用者社群。
近來深度學習在 cv(計算機視覺)和 nlp(自然語言處理)領域的成功,激發了 ai 研究人員在這兩者的交叉領域探索新的應用。而作為結果的注解生成模型,需要平衡對視覺線索和自然語言的了解。
這兩門傳統上泾渭分明、并不相關的領域之間所産生的交集,有潛力在業内産生廣泛的影響。該技術有一些直接應用場景,比如為 youtube 視訊生成簡介,又比如為無标簽圖像做注解,但其價值遠不止于此。類似于傳統的 cv 技術試圖讓現實世界變得讓計算機更容易接觸更容易了解,該技術有潛力讓現實世界變得對于我們來說更容易了解。它可以作為我們的導遊、日常生活的視覺輔助,比如意大利 ai 公司 eyra 的為視覺障礙患者開發的可穿戴裝置 horus (古埃及神話中的荷魯斯之眼)。
首先,你需要安裝 tensorflow。
你還需要下載下傳 flickr30k 資料集的圖像注解和 image embeddings。下載下傳連結也在 github 資源庫裡。
現在教程開始。
在高層級,這就是我們将要訓練的模型。每一幅圖像将會用深度 cnn 編碼成 4,096 維的矢量表示。一個語言生成 rnn 會随後對其按次序解碼,成為自然語言描述。
作為一個曆史悠久的 cv 任務,圖像分類背後有許多強大模型。圖像分類能把圖像中相關聯的形狀、物體的視覺資訊拼湊到一起,把圖像放入物體類别中。針對其他 cv 任務的機器學習模型,建立在圖像分類的基礎之上,比如物體識别和圖像分割。它們不僅能對提供的資訊進行識别,還能學習如何解讀 2d 空間,調和兩種了解,并決定圖像中物體資訊的位置分布。
對于注釋生成,這引發了兩個問題:
我們如何充分利用圖像分類模型的成功,從圖像提取重要資訊?
我們的模型,該如何調和對語言和圖像的了解?
我們可以利用已有的模型,推動圖像注解。遷移學習使得——在不同任務上訓練神經網絡而學習到的資料變形,能用于我們的資料。在我們的例子中,vgg-16 圖像分類模型導入 224x224 分辨率的圖像,生成對分類圖像非常有用的 4,096 維特征矢量。
我們可以把 vgg-16 模型的表示(即 image embedding)用于訓練其他模型上面。受篇幅限制,本文對 vgg-16 的架構不欲詳述,并預先計算好了 4,096 維特征,來加速訓練。
載入 vgg 圖像特征和圖像注解比較直接:
def get_data(annotation_path, feature_path): annotations = pd.read_table(annotation_path, sep='\t', header=none, names=['image', 'caption']) return np.load(feature_path,'r'), annotations['caption'].values
了解注解
有了圖像表示,我們需要模型來學習把它解碼為可了解的注解。由于文本的序列本質,我們需利用 rnn/lstm 中的循環。對于序列中的給定詞語,這些網絡被訓練,用以預測下一個詞語以及圖像表示。
lstm 單元允許模型在注解詞語序列中,更好地選擇使用哪條資訊、記憶什麼、又要忘記什麼。tensorflow 提供了一個 wrapper 函數,來對給定輸入、輸出次元生成 lstm 層。
為了把詞語轉換成适合 lstm 輸入的固定長度表示,我們使用了一個 embedding 層,它能學習把詞語映射到 256 維的特征(或 word-embedding)。word-embedding 幫助我們把詞語表示為矢量,相近的詞語矢量在語義上也是近似的。
在 vgg-16 圖像分類器裡,卷積層提取了 4,096 維表示,傳入最終的 softmax 層進行分類。由于 lstm 單元需要 256 維文本特征作為輸入,我們需要把圖像表示轉譯為針對目标注解的表示。為實作這一點,我們使用了另一個 embedding 層,學習把 4,096 維圖像特征映射到 256 維文本特征的空間。
整體上,這就是谷歌 show and tell 模型看起來的樣子:
上圖中, {s0, s1, ..., sn}代表了注解中我們想要預測的詞語, {wes0, wes1, ..., wesn-1} 是每個詞的 word embedding 矢量。lstm 的輸出 {p1, p2, ..., pn} 是模型生成的機率分布,針對句子中的下一個詞。該模型被訓練來最小化每個詞語對數機率(log probabilities )的負數總和。
訓練之後,我們有了一個模型。給定圖像和所有此前的詞語,它能給出下一步某個詞出現在注解中的機率。如何用它來生成新注解呢?
最簡單的辦法,是拿來一個輸入圖像,輸出下一個可能性最高的詞語,建立一個簡單的圖像注解。
這在許多情況下會奏,但“貪婪”地使用每一個機率最大的詞語,未必能獲得整體上機率最大的注解。
繞過這個難題的一個潛在方案,是采用一個名為"beam search"的方法。該算法會對長度 t 以内的 k 個最佳語句集反複考量,作為候選來生成 t + 1 大小的句子,隻保留結果中的 k 個最佳選擇。這允許開發者探索一個較大的優質注解空間,同時讓推理在計算上可追蹤。在下面的例子裡,算法保持了一個 k = 2 的候選句子清單,即每個垂直時間步到每個加粗詞語的路線。
對于學習把圖像映射到人類級别的文字注解,該神經圖像注解生成器提供了一個十分有用的架構。銅鼓偶在大量圖像—注解成對資料上訓練,該模型學會了通過視覺特征抓取相關語義資訊。
但對于靜态圖檔而言,嵌入我們的注解生成器,将會聚焦于圖像中對分類有用的特征,而不是對注解生成有用的特征。為提升每個特征裡涵蓋的與任務相關的資訊,我們可以訓練圖像嵌入模型(用來對特征進行編碼的 vgg-16 網絡)作為注解生成模型的一部分。這使得我們能為圖像編碼器調參,以更符合注解生成器的角色。
另外,如果我們仔細觀察生成的注解,會發現它們基本是日常、常見的情形。下圖便是例子:
幾乎可以肯定,這圖檔是“長頸鹿站在一棵樹旁邊”。但是,如果我們看看其他圖檔,會立刻發現無論對于哪一張生成的注解都是“長頸鹿站在一棵樹旁邊”。這是因為訓練集中的長頸鹿都出現在樹旁邊。
現有的前沿圖像注解模型會包含一個視覺注意力機制(visual attention mechanism),使得模型能發現圖像中感興趣的部分,因而能在生成注解時選擇性地聚焦。
====================================分割線================================
本文作者:三川