看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

大数据文摘發表於2018-06-07

走進Aribnb位於舊金山總部的辦公樓,你會看到一個個裝修各異的會議室。這些會議室正是Airbnb形形色色民宿的縮影。

Airbnb為數百萬的民宿提供了一個平臺,也因此囊獲了一大批民俗房間細節照片和使用者資料。

坐擁百萬級別的使用者資料,Airbnb的資料團隊可謂將資料的價值發揮地淋漓盡致。傳統的推薦系統、廣告系統自是不用說,深度學習的應用更是讓Airbnb的資料有了前所未有的價值。

今天,文摘菌就要分享一篇來自Airbnb資料團隊的課題小報告。讓我們一起來看看,Airbnb的資料科學家們(Shijing Yao, Qiang Zhu, Phillippe Siclait)是怎麼將他們的圖片資料玩出花樣的。

看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

Airbnb在舊金山總部的會議室

資料真的是新石油麼?

如果把這個問題拋給Airbnb的資料團隊,那他們一定會給出一個堅定的答覆:一點兒沒錯!

Airbnb為數百萬的民宿提供了一個平臺。全世界的旅行者都在這個平臺上為他們的旅行尋找到最滿意的家。而對於這些房屋除了地段和價格外,房屋本身的照片是最能影響使用者決策的因素之一了。

然而直到目前,我們對這些照片瞭解的甚少,Airbnb形態各異的民宿也增加了我們分析這些照片的難度。

當旅行者在瀏覽一張房屋的照片時,我們暫時無法為使用者提供最能準確反映民宿情況的圖片,也無法為房東提升照片的吸引力提供指導和建議。

看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

客廳、廚房、臥室、浴室圖片示例

得益於如今計算機視覺深度學習的優勢,我們終於可以規模化地解決這一問題了。

我們今天的目標是圖片分類。這樣,一方面我們能將具有相似風格的房源聚集到一起,方便使用者瀏覽。另一方面,分類也可以幫助驗證房間數量和房屋資訊的準確性。在不久的未來,我們將對這些圖片進行更深的研究,預計還能發掘出許多潛在的資訊。文章的最後我們會展示一些例項。

圖片分類

正確的圖片分類對最佳化提升使用者體驗是極具意義的。從客戶端來講,分類便於對一系列照片的重新排序,確保最先看到的都是最感興趣的內容;從房東的角度來講,分類為審查照片的清單提供了便利,幫助房東確保自身能滿足市場的高標準。而精準的照片分類是這些核心功能得以實現的基石。

我們最先進行分類的物件房屋型別包含了臥室、浴室、客廳、廚房、游泳池和園景,我們後期還會根據產品團隊的需要,新增房間其他的元素。

房間型別分類問題類似於ImageNet上的圖片分類,期望輸出的是具有使用者個性化的結果。這就使得諸如VGG,ResNet這樣的現成又先進的深度神經網路模型(DNN)是沒辦法直接使用的。

當然,網上有許多很棒的帖子,告訴人們如何使用這些模型來解決這類問題。其中,最基本的兩步是:1.修改DNN模型的最頂層以保證輸出結果符合要求;2.重新訓練DNN網路以確保達到想要的預期。

透過幾次實驗,我們選取了ResNet50網路作為驅動,由於它在模型效能和計算時間上具有良好的平衡性。同時,為了確保與用例的相容性,我們加入了兩個額外的全連線層和一個Softmax啟用函式

相關連結:

https://arxiv.org/abs/1512.03385

重新訓練ResNet50模型

看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

修改後的RESNET50的體系結構基礎模型圖

ResNet50模型的重訓練有三種方法:

  1. 保持基礎ResNet模型,僅以最小的資料量重新訓練新新增的兩層。也稱作微調。

  2. 同1一樣的微調,但資料量更大。

  3. 重新訓練整個ResNet50模型。

絕大多數的線上教程會使用第一種方法,計算省時且結果可觀。我們也確實透過第一種方法得出了合理的最初結果,然而為了滿足分類結果質量的高標準,我們需要更顯著地提高模型效能——保證95%+的高精度和80%+的召回率。

為了兼顧精確率和高召回率,我們意識到必然要用到海量的資料對DNN模型進行重訓練,然而這裡存在兩個挑戰:1.即使擁有大量來自使用者上傳的照片資料,我們卻無法對其打上精確的標籤;2.重新訓練ResNet50的DNN模型任務量非常重要—需要2500萬訓練引數,對GPU要求極高。下面,我們就來詳細介紹我們是如何應對這兩個挑戰的。

圖片標題管理

許多公司會依託第三方供應商來獲取高質量的圖片標籤。然而在數以百萬計的照片需要標籤的情況下,這顯然不是最具價效比的解決方案。

為了權衡成本和效能,我們採取一種混合的方案,一方面,委託第三方對少量打標籤,通常是成千上萬張照片。以這些具有標籤的資料作為模型的評估標準,採用隨機抽樣法來建立這一標準,以確保標準資料的平衡性;另一方面,利用房東上傳的照片標題資料作為房屋型別資訊的代表,並從中提取標籤。

這種方案對我們來說是非常有意義的,明顯降低了標籤所需的高昂成本。我們僅僅需要一套明智的方法來確保從圖片標題中提煉的房屋型別標籤準確可靠。

從影像標題中提取房間型別的標籤似乎是一種可行的方法:如果某張圖片的標籤中包含有某種明確的房屋型別關鍵詞,那麼圖片就該加以相應房屋型別的標籤。然而現實情況往往更加複雜:這種方法的結果是令人失望的。太多的情況下,圖片標籤與圖片實際內容相差甚遠,如下一些例子:

看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

錯誤的標籤提煉示例

為了篩除這些錯誤的情況,我們又額外增加了一條規則。經過幾輪篩選和檢查,標籤質量有了明顯的提升。以下就是一個例項,展示了我們是如何將標籤中含有“廚房”關鍵字的資料進行篩選,以獲得真正描述“廚房”的圖片。

程式碼段:

AND LOWER(caption) like '%kitchen%' AND LENGTH(caption) <= 22 AND LOWER(caption) NOT LIKE '%bed%' AND LOWER(caption) NOT LIKE '%bath%' AND LOWER(caption) NOT LIKE '%pool%' AND LOWER(caption) NOT LIKE '%living%' AND LOWER(caption) NOT LIKE '%view%' AND LOWER(caption) NOT LIKE '%door%' AND LOWER(caption) NOT LIKE '%table%' AND LOWER(caption) NOT LIKE '%deck%' AND LOWER(caption) NOT LIKE '%cabinet%' AND LOWER(caption) NOT LIKE '%entrance%'

由於這些額外的過濾器,我們丟失了許多圖片資料。但是這沒有明顯的不良影響:即便採用瞭如此激進的篩選方法,我們仍然為每個房屋型別獲取了成百上千張照片,累計達幾百萬張。

而且,透過與標準平衡資料集的對比,我們發現標籤的質量顯著提升了。這裡我們假設資料分佈沒有隨著過濾而改變。究竟是不是這樣,那就要看模型在測試資料集上的表現了。

未來,我們希望利用NLP技術對圖片標題進行動態聚類,取代目前基於規則的啟發式演算法。然而就目前而言,還是會繼續採用啟發式演算法。

建模、評估、求解

看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

左:8核並行訓練的GPU效能,右:分散式SGD:從Quoc v.Le中引用的圖表

要想用幾百萬張影像重新訓練像ResNet50那樣的DNN模型需要大量的計算資源。我們在帶有英偉達8核K80GPU的AWS P2.8xlarge例項上進行訓練,在每個訓練步驟中,我們向8個GPU傳送一批樣本(batch),每一批樣本共128張影像。

我們使用Tensorflow作為後端進行並行訓練,在並行後進行編譯,否則訓練無法進行。為了進一步加快訓練速度,我們從keras.applications.resnet50.ResNet50中載入已經訓練好的影像網路權重,用這些權重對模型權重進行初始化。

經過3個訓練時期(epoch),歷時約6個小時後,模型達到了最好效果,之後模型便開始過擬合驗證集的效果也不再提升了。

值得注意的是,我們對房間做分類時採用的是多個二分類模型,而不是採用一個包括所有房間型別的多分類模型。這麼做並不理想,但由於我們的模型主要還是離線(offline)的,多次呼叫模型造成的額外延遲對我們的影響很小。以後我們很快就會轉為訓練多分類模型。

我們用精確率(precision)和召回率(recall)對模型進行評估,並用F1分數(F1-score)和準確率(accuracy)等指標對模型進行監控。

這裡再重新回顧一下這幾個指標的定義:簡而言之,精確率描述了預測為正的樣本中有多少為真正的正樣本,召回率描述了樣本中的正例有多少被正確預測了,精確率和召回率通常是互相制約的。

在我們這個例子中,我們對精確率設定了一個比較高的標準(95%),因為當我們說這張照片屬於某種房間型別時,我們應該對這個說法有很高的信心。

看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

混淆矩陣與精確率、召回率、F1分數、準確率的定義

混淆矩陣是計算這些矩陣的關鍵。我們模型的原始輸出是對每個影像給出一個範圍在0到1內的機率分數,要計算出一組預測值的混淆矩陣,首先要設定一個閾值,將預測分數轉換為0或1,然後透過從0到1調整閾值取值,生成精確率-召回率(PR)曲線。原則上,PR曲線的AUC(曲線下面積)越接近1,模型越精確。

人為標記的標籤作為真實標籤。有趣的是,我們發現不同房間型別的模型準確率不大一樣。房間型別為臥室和浴室時的模型是最準確的模型,而房間型別為其他時的模型則不太準確。簡潔起見,我們只展示房間型別為臥室和客廳時的P-R曲線,其中虛線的交叉點表示給定某個閾值時的模型效果,圖中還展示了此時各個指標的摘要。

看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

房間型別為臥室時的PR曲線

看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

房間型別為客廳時的PR曲線

這裡有兩個重要的發現:

  • 房間型別為臥室時模型的整體表現遠勝於房間型別為客廳時的模型表現。對此有兩種可能的解釋:1.臥室比客廳更容易分類,因為臥室的佈置相對標準,而客廳的佈置則相對更加多樣化。2.從臥室照片中提取的標籤比從客廳照片中提取的標籤質量更高,因為客廳照片有時還包括飯廳或廚房。

  • 無論是哪種房間型別,完全重新訓練的模型(紅色曲線)要比部分重新訓練的模型(藍色曲線)具有更好的表現,而且房間型別為客廳時,這兩個模型之間的差距比房間型別為臥室時的更大。這表明重新培訓一個完整的ResNet50模型對於不同的房間型別有不同的影響。

在我們訓練的6個模型中,精確率一般在95%以上,召回率一般在50%以上,人們可以透過設定不同的閾值對這兩個指標進行權衡。這個模型旨在為Airbnb內部的多個產品團隊提供多種不同的產品。

使用者將我們的結果與一些有名的第三方影像識別API進行了比較。根據他們反映,我們這個對房子內部結構進行分類的模型,總體上優於第三方的模型,這說明當我們做某個自己感興趣的任務時,透過使用自己的資料,我們也有機會超越業界最先進的模型。

最後,我們想展示一些具體例子來說明這個模型的強大功能。

看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

左邊兩張照片被正確地預測為臥室,右邊兩張照片被正確地預測為“不是臥室”

看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

左邊兩張照片被正確地預測為浴室,右邊兩張照片被正確地預測為“不是浴室”

看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

左邊兩張照片被正確地預測為泳池,右邊水族館和海濱的兩張照片被正確地預測為“不是泳池”

除了分類以外,我們還做了些別的

在做這個專案時,我們也嘗試了一些除了對房間型別進行分類以外的有趣想法。在這裡我們想展示兩個例子,讓人們瞭解到這些問題有多令人振奮。

非監督的場景分類

在我們剛開始嘗試使用預先訓練好的ResNet50模型對房間型別進行分類時,我們生成了影像的嵌入向量(維度為2048x1的向量)。為了解釋這些向量意味著什麼,我們使用PCA技術將這些長向量投影到2D平面上。

令我們驚訝的是,投影后的資料被自然地聚為兩類。縱觀這兩個分類,我們發現左邊的分類幾乎都是室內的場景,右邊的分類則幾乎都是戶外場景。這意味著無需再進行任何訓練,只需在影像嵌入向量的第一個主成分上設定一條切割線,就可以確定室內和室外場景。這一發現為無監督的遷移學習(嵌入)等有趣的領域開啟了大門。

看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

室內和室外的照片被自動聚類為第一和第二主成分

目標檢測

我們嘗試努力的另一個領域是目標檢測。預先訓練好的Faster R-CNN已經在開放的影像資料集上達到了驚人的效果。

在下面的例子中你會看到,該模型能夠檢測到門、窗、餐桌及其位置。 透過使用Tensorflow Object Detection API,我們對房主上傳的照片做了一些快速評估。使用現成的結果已經可以檢測到很多家居設施。

未來,我們計劃使用Airbnb定製的便利標籤重新訓練Faster R-CNN模型。由於開源資料中缺少一些這樣的標籤,我們可能會自己建立標籤。透過用這些演算法檢測到的設施,我們可以房主上傳的圖片質量,並幫助客人更方便地找到具有特定環境需求的房屋,這將把Airbnb的照片智慧前沿推向更高水平。

看照片挑民宿:Airbnb如何重新訓練ResNet50,實現房間圖片分類最佳化

門、窗、餐桌被成功檢測

結論

以下是一些重要結論,可能會對各位深度學習實踐者有用:

首先,深度學習不過是一種特殊的有監督學習,我們不能高估高質量標籤對資料的重要性。由於深度學習通常需要大量的訓練資料才能達到出色的表現,因此尋找一種有效的標記方法顯得至關重要。幸運的是,我們發現了一種經濟的、可擴充套件的且可靠的組合方法。

其次,從零開始訓練像ResNet50這樣的DNN模型可能會相當複雜。不妨試試以簡單快速的方式開始——使用小的資料集只對網路最上面的層進行訓練。如果您確實有大量可訓練資料集,從頭開始重新訓練DNN可能能讓模型能達到更好的表現。

第三,如果可以的話,進行並行訓練。在我們的例子中,我們透過使用8個GPU獲得了大約6倍(準線性)的加速。這使得建立複雜的DNN模型在計算上可行,而且也讓超引數和模型結構上的迭代變得更加容易。

原作者按

這項工作是與Krishna Puttaswamy、Xiaohan Zeng 和Alfredo Luque合作完成的,整個公司的員工幫忙推出了這個產品的功能。我們還要感謝Keras、Tensorflow、Open Images Data、ImageNet等開源庫的貢獻者和和ResNet的發明者,我們從這個友好的開源社群獲益匪淺。最後,我們要感謝Jeff Feng和Rebecca Rosenfelt在校對方面的熱情幫助。

相關文章