忘掉PS吧!歡迎進入修圖的神經網絡時代


左邊是原圖,右邊是修圖。是否是以爲美女與右邊圖片的背景搭在一塊兒,更有動感和帥氣。但是不會修圖啊,腫麼辦?
git


今天讓咱們來看一個有意思的AI應用,讓不會PS的你,也能立馬擁有吊炸天的修圖超能力,沒準還能分分鐘修完上萬張圖,秒殺全部PS修圖大神。


如下是機器學習大神
Gidi Shperber講
述,他是到底一步步把這個模型給搞出來的詳細過程。你要不要本身也來訓練一個呢?


翻譯 | AI科技大本營(rgznai100)github

參與 | shawn算法

                                                   引言

在機器學習領域摸爬滾打的這幾年中,我一直想開發一個實用的機器學習產品。
spring

幾個月前,我學完了 Fast.AI深度學習課程(http://www.fast.ai/%22),期待已久的機會終於閃如今我眼前:深度學習技術近幾年日新月異,許多以前沒法實現的事情如今也有了實現的可能。新的工具開發成功後,應用的實現變得比以往更加容易。在學習Fast.AI課程期間,我遇到了經驗豐富的網站開發者Alon Burg(https://medium.com/@burgalon/35648f9dc5fb)。我倆一拍即合,決定一塊兒追求這一目標。所以,咱們一塊兒設定了如下小目標:編程

  1. 提升咱們在深度學習上的能力瀏覽器

  2. 提高咱們的AI產品應用能力服務器

  3. 開發一個有市場需求的使用產品網絡

  4. (讓咱們和咱們的用戶)享受到樂趣架構

  5. 分享咱們的經驗dom

鑑於以上目標,咱們開發的產品須要知足如下要求:

  1. 別人還沒開發出來(或者別人開發的不夠好)

  2. 計劃和實現起來不是很難——咱們計劃在2-3個月內完成,每週工做一天。

  3. 用戶界面簡單有趣——咱們想開發一個既有演示做用又有實用價值的產品。

  4. 要求的訓練數據能輕易得到——機器學習從業人員都知道,數據有時候要比算法貴不少。

  5. 使用先進的機器學習算法(谷歌、亞馬遜等公司仍未在其雲平臺上提供的),但不要太過先進(這樣咱們就還能在網上找到一些實例)

  6. 有實現「生產就緒」的潛力。

咱們早期的想法是從一些醫療項目下手,由於這個領域深得人心,咱們(仍然)感受深度學習在醫療領域有不少容易實現的應用。可是,咱們意識到咱們會在數據採集和法律及法規方面遇到一些問題,解決起來不會很容易。

這樣背景移除產品就成了咱們的第二選擇。

若是使用某種「標識」和邊緣識別工具,手動完成或半手動完成背景移除任務就至關容易(示例地址-https://clippingmagic.com/) 。可是,全自動背景移除卻極具挑戰。據咱們所知,有人作過嘗試,可是如今尚未哪一個產品可以得出使人滿意的結果。

咱們要移除什麼樣的背景?這是個很重要的問題,由於模型在目標、角度等元素上針對性越強,背景分離質量就越好。在剛開始時,咱們的野心很大:目標是開發出一個能夠自動識別前景(foreground)和背景的通用背景移除模型。可是在訓練了第一個模型後,咱們發現最好仍是將工做集中在某一系列的圖像上。所以,咱們決定專攻自拍和人類肖像。


                                                                     (類)人類肖像背景移除

自拍圖像有一個既明顯又明確地前景(一個或多個「主角」),這樣咱們就能很好地將對象(臉部和上身)和背景分離開來。此類圖像每每角度單一,顯示的對象也相同(人)。

有了這些假設,咱們開始進行研究、實現以及長達數小時的訓練,以期作出一個簡單易用的背景移除產品。

雖然咱們的主要工做是訓練模型,可是咱們不能低估正確實現的重要性。好的背景分離模型仍然不像分類模型那樣結構緊湊(例如SqueezeNet-https://arxiv.org/abs/1602.07360%22),咱們積極研究了產品在服務器和瀏覽器上的應用。

若是您想了解更多關於產品實現的內容,歡迎查看咱們在server side (https://medium.com/@burgalon/35648f9dc5fb)和 client side(https://medium.com/@burgalon/2e5a29589ad8)上發表的文章。

若是您想了解該模型及其訓練過程,請繼續閱讀。

                                                    語義分割

在研究與本任務相似的深度學習和計算機視覺任務時,咱們很快發現最好的策略是語義分割。

就咱們的目的而言,其餘策略(如經過深度檢測實現分割)好像不夠成熟,例如經過深度檢測實現背景分離(https://arxiv.org/pdf/1507.06821.pdf)。

除了分類和目標檢測,衆所周知的計算機視覺任務還有語義分割。從像素分類的角度來看,語義分割其實是一個分類任務。不一樣於圖像分類或圖像檢測,語義分割模型在必定程度上可以「理解」圖像,它不僅能檢測出「圖像中有一隻貓」,並且還能在像素級別上指出這隻貓的品種以及它在圖像中的位置。

語義分割模型的工做原理是什麼?爲了獲得答案,咱們研究了該領域的一些早期成果。

咱們最先的想法是採用早期的分類網絡,如VGG和Alexnet。回溯到2014年,VGG是當時最早進的圖像分類模型,並且VGG結構簡單易懂,時至今日仍十分有用。當觀察VGG較淺的層時,能夠看到要進行分類的對象周圍彙集有激活單元,並且層越深上面的激活單元就越強。因爲重複的pooling操做,VGG得出的結果在本質上比較粗糙。理解了這些,咱們假設分類訓練在通過一些調整後也能夠用於搜尋/分割對象。

分類算法出現後,語義分割的早期成果也應運而生。這篇文章給出了一些使用VGG得出的粗糙的語義分割結果。

這篇文章

http://warmspringwinds.github.io/tensorflow/tf-slim/2016/11/22/upsampling-and-image-segmentation-with-tensorflow-and-tf-slim/

                                                       

輸入圖像

靠後層的結果:

                                            公共汽車圖像分割,亮紫色(29)表明校車類別

在雙線性升採樣後:

這些結果是這樣得來的:將全鏈接層轉化爲(或維持)它的原始形狀,維持其空間特徵不變,得出一個全卷積神經網絡(FCN)。在上面的例子中,咱們將一個768*1024的圖像輸入到VGG中,結果獲得了一個24*32*1000的卷積層。24*32的圖像是池化後的圖像(1/32大小),1000是圖像網絡類別數,據此咱們能夠推導出上文中的語義分割。

爲了讓模型能順利地進行預測,研究人員使用了一個簡單的雙線性升採樣層(bilienar upsampling layer)。

在這篇FCN論文(https://arxiv.org/abs/1411.4038)中,研究人員改進了上述方法。爲了解釋得更詳細,他們將一些層鏈接在一塊兒,根據升採樣率的不一樣將它們分別命名爲FCN-3二、FCN-16 和FCN-8。


在層之間加一些skip connection,可使預測模型對原始圖像中更細微的細節進行編碼。通過進一步訓練,得出的結果會更好。

試驗證實,這種方法的效果並不像想象的那樣糟糕;並且利用深度學習完成語義分割任務的確有實現的可能。


圖4. 經過整合不一樣步長的跨層信息來改善全卷積網絡,改進分割細節。前三張圖展現的分別是步長爲3二、16和8像素的網絡的輸出。

論文中得出的FCN 結果

FCN的提出揭示了語義分割的概念,爲了解決這個任務研究人員嘗試了不少不一樣的架構。從一些新的模型能夠看出,他們的主要思路仍然相似:使用已知的架構,進行升採樣,採用skip connection。

您能夠經過閱讀 文章一、 文章2 和文章3來了解該領域的一些進展。您會發現,大多數架構採用的仍然是編碼器—解碼器架構。

咱們的項目

在作了一些研究工做後,咱們最終肯定了三個模型:FCN、Unet(https://arxiv.org/pdf/1505.04597.pdf%22)和Tiramisu (https://arxiv.org/abs/1611.09326%22)。這三個模型都是很是深的編碼器—解碼器架構,並且都能找獲得。咱們還有一些關於mask-RCNN的想法,可是這種模型的實現彷佛不在咱們項目涵蓋的範圍內。

因爲FCN的結果不如咱們預期的那樣好(甚至不及格),所以暫不考慮這種模型。另外兩種模型的結果則相對不錯:tiramisu 在CamVid (http://mi.eng.cam.ac.uk/research/projects/VideoRec/CamVid/%22)數據集上表現良好;Unet的主要優勢在於結構緊湊、速度快。在實現方面,Unet實現起來很簡單(咱們使用的是keras),Tiramisu 也可以成功實現。開始進行項目前,咱們在Jeremy Howard的深度學習課程(https://www.usfca.edu/data-institute/certificates/deep-learning-part-two)的最後一課中使用過一個很好的Tiramisu應用。

獲取了兩個模型(一個Unet和一個Tiramisu)後,咱們用一些數據集對它們進行了訓練。值得指出的是,第一次試驗咱們用的是Tiramisu模型,結果對咱們而言很理想,由於它能夠捕捉圖像中的尖銳邊緣。而Unet模型處理得彷佛不夠精細,得出的圖像有點糊。

                                                                                       Unet 得出的結果有點糊

                                                  數據

在肯定了該使用哪一種模型這個大方向後,咱們開始尋找合適的數據集。語義分割數據不像分類數據或者檢測數據那樣常見。並且,手動標記並不可行。語義分割最多見的數據集是COCO(http://mscoco.org/)數據集(大約包含8萬張圖像,90種類別)、VOC pascal(http://host.robots.ox.ac.uk/pascal/VOC/%22)數據集(大約包含11000萬張圖像,20種類別)以及相對較新的ADE20K(http://groups.csail.mit.edu/vision/datasets/ADE20K/%22)數據集。

咱們選擇使用COCO數據集訓練模型,由於它包含更多「人」像,這正是咱們感興趣的一類圖像。

針對任務,咱們思考了是隻使用相關性很強的圖像,仍是使用涵蓋範圍較廣的數據集。一方面,涵蓋範圍較廣的數據集每每包含更多的圖像和類別,使用這種數據集的話,模型能夠處理更多的場景和問題。另外一方面,模型一整夜的訓練圖像數超過15萬張。若是咱們用整個COCO數據集訓練模型,同一張圖像模型最後(平均)會學習兩次,所以稍微修剪一下數據集會有所幫助。另外,這樣作的話咱們還能夠獲得一個目標性更強的模型。

還有一個問題有必要指出——Tiramisu模型本來是用CamVid數據集訓練的,這個數據集雖然存在一些弊端,可是最大的問題是它的圖像千篇一概:全部圖像都是在車內拍攝的路景圖。很顯然,學習這樣的數據集(即便圖像中有人)對咱們的任務沒有任何幫助。所以,咱們只用該數據集完成了一個簡短的試驗。

                                                       CamVid數據集中的圖像

COCO數據集支持很是簡單的API,這使得咱們能夠知道目標在每張圖像中的具體位置(根據預先設定的90個類別)。

在進行了一些試驗後,咱們決定對數據集進行稀釋:首先咱們過濾了只顯示有一人的圖像,這樣就只留下了4萬張。而後,咱們剔除了全部顯示有多我的的圖像,留下只顯示一人或兩人的圖像,此類圖像就是咱們的產品應該識別的對象。最後,咱們只留下了20%-70%的內容都被標記爲「人」的圖像,剔除了那些顯示有某種奇怪的巨物或者背景中有一個很小的人像的圖像(惋惜沒有剔除掉全部此類圖像)。最後,該數據集留下了11000張圖像,咱們感受在這個階段這麼多就足夠了。


                                                            左圖:符合要求的圖像 ___ 中圖:人物過多___ 右圖: 對象過小

                                               Tiramisu模型

如上文所述,咱們曾在Jeremy Howard的課程中使用過Tiramisu模型。它的全名是「100層Tiramisu」,聽起來像是一個很大的模型,可是它實際上很簡潔,只有900萬個參數。相比之下,VGG16的參數則多達1.3億多。

Tiramisu模型基於DensNet,後者是近期提出的一種全部層都是全鏈接層的圖像分類模型。並且同Unet同樣,Tiramisu也在升採樣層上添加了一些skip connection。

這種架構與FCN論文中闡述的想法相契合:使用分類架構,升採樣,添加skip connection以改善模型。

                                                                

                                                        Tiramisu 架構概覽

咱們能夠將DenseNet(https://arxiv.org/pdf/1608.06993.pdf%22)模型看做爲Resnet模型的天然進化版,它記憶的是整個模型的全部層,而不是隻在到達下一層以前「記憶」全部層。這些鏈接稱爲「highway connection」。這種鏈接會致使過濾器數量增長——定義爲「增加率」(growth rate)。Tiramisu的增加率爲16,所以咱們在每層上都添加16個新的過濾器,直到抵達過濾器總數爲1072個的層。您可能會說模型是100層tiramisu模型,那不就是1600層嗎。但事實並非這樣,由於升採樣層會損失一些過濾器。


                                                                                  

                                                                                  Densenet模型簡圖——模型前面層的過濾器堆疊在一塊兒

                                                        訓練

咱們按照原論文中闡述的訓練安排訓練咱們的模型:標準交叉熵損失函數,學習率爲1e-3並且衰減很小的RMSProp優化器。咱們按比例這11000張圖像分爲訓練圖像(70%)、驗證圖像(20%)和測試圖像(10%)。下文中的全部圖像都來自於咱們的測試數據集。

爲了使咱們的訓練安排與原論文保持一致,咱們將epoch大小設爲500張圖像。這樣的話,用於訓練模型的數據就更多(本文中所用的CamVid數據集包含的圖像數少於1000張),咱們能夠經過改進結果週期性地改進模型。

另外,咱們只使用了2個類別的訓練圖像:背景和人像,原論文使用了12個類別。起先咱們用的是COCO的一些類別,可是卻發現這對訓練沒有多大幫助。

                                                                  數據問題

某些數據集缺陷影響告終果:

  • 動物——咱們的模型有時會語義分割動物,這必然會致使IOU值較小。在同一主類別中加入動物或將動物做爲另外一主類別,可能會完全消除咱們的結果。

  • 身體部位——因爲使用編程的方法對數據集進行過濾,咱們沒法判斷「人」類別真的指的是人,仍是指人身體部位,如手部或腳部。這些圖像雖然都不在咱們處理的範圍內,可是仍然會出如今數據集中。

                                                                   

                                                                         動物、身體部位、手持物體

  • 手持物體——數據集中的許多圖像都有運動有關,好比棒球棒、網球拍和滑雪板。咱們的模型在分割這些圖像時會被迷惑。咱們認爲,將動物做爲主類別的一部分或者另外一單獨類別會對模型的表現有幫助。

                                                                       
                                                                                帶物體的運動圖像
  • 粗糙的ground truth——COCO數據集並未進行逐像素的標記,可是是用多邊形標註的。有時效果很好,但有時ground truth卻很粗糙,這會阻礙模型學習細節。

                                                                                                                          原圖像和(很是)粗糙的ground truth

                                                         結果

咱們的結果雖然使人滿意,但仍是不夠完美:咱們用測試數據集測試模型所獲得的IOU值爲84.6,而當前最優秀的模型的IoU值爲85。這個數字很難統計,由於只要遇到不一樣的數據集和類別,它就會波動。有些類別自己較爲容易分割,例如房屋、道路等,模型處理這些類別時的IOU值能夠達到90。較難處理的類別則包括數和人類,模型在處理這些類別時的IOU值在60上行波動。爲了限定困難程度,咱們使模型只關注一個類別以及必定類型的圖像。

咱們仍然感受咱們的產品並未實現預期的「生產就緒」,可是咱們認爲這時候停下來討論試驗結果會更好,由於約50%的圖像會得出好的結果。

如下是一些較好的實例,以便您瞭解咱們App的性能:



                                             原圖像、Ground truth、咱們的結果(來自於測試數據集)

                                                 調試和記錄

調試是訓練神經網絡的一個很重要的環節。當剛開始進行工做時,很容易就會想直接獲取數據和神經網絡,開始訓練,而後看看會得出什麼樣的結果。可是咱們發現,追蹤每步操做極其重要,這樣作的話咱們就能夠對每一步的結果進行檢查。

如下是一些常見的挑戰以及咱們的應對方法:

  • 早期問題——可能沒法訓練模型。多是由於一些內在問題或者某種預處理錯誤,如忘記正則化某部分數據。總之,對結果進行簡單的可視化可能會有助於找出問題。這是一篇關於此論題的文章(https://blog.slavv.com/37-reasons-why-your-neural-network-is-not-working-4020854bd607)。

  • 調試網絡自己——在肯定無嚴重問題後,開始用預先定義的損失和metric進行訓練。在分割任務中,主要的評價指標是檢測評價函數(intersect over union,IoU)。在進行了幾個階段的工做後,咱們纔開始將IoU做爲模型的主要評價指標(而不是交叉熵損失)。另外一個有用的操做是給出模型在每個epoch的預測。這是一篇關於調試機器的優質文章(https://hackernoon.com/how-to-debug-neural-networks-manual-dc2a200f10f2)。注意IoU雖然不是Keras中標準的metric函數的或損失函數,可是在網上很容易就能夠找到,例如此網站(https://github.com/udacity/self-driving-car/blob/master/vehicle-detection/u-net/README.md)。咱們還將這個gist(https://gist.github.com/shgidi/7c3fcf69b1eb3eaf4bac1112d10967ca)用於每個epoch的損失和某些預測的plotting中。

  • 機器學習變體控制——當訓練模型時,你會遇到不少參數,有些參數很難追蹤。我必須認可咱們還沒找到完美的解決方法,咱們的方法是頻繁寫入配置(以及利用Keras的callback自動保存表現最佳的模型,見下文)。

  • 調試工具——在完成以上步驟後,咱們能夠檢查每一步的結果,可是不能無間斷地檢查。所以,最重要的步驟是整合上文中的步驟,生成一個Jupyter notebook,這樣咱們就能夠用它來無間斷地加載每一個模型和每張圖像,並快速檢查結果。這樣咱們就能輕易地觀察到模型之間的差別、缺陷和其餘問題。

如下是一些經過調整參數和增長訓練而對模型實現的一些改進:


                                        


保存目前爲止的最佳驗證IoU:(Keras提供了一個很是好的工具——callbacks-https://keras.io/callbacks/%22 ,用於簡化工做)

callbacks = [keras.callbacks.ModelCheckpoint(hist_model, verbose=1,save_best_only =True, monitor= ’val_IOU_calc_loss’), plot_losses]

除了對可能的代碼錯誤進行的常規調試,咱們發現模型錯誤是「能夠預測的」,好比「切割」不屬於廣義身體範疇的身體部位、大分割圖像上的「缺口」、沒必要要的身體部位持續延伸、光線很差、質量差以及等等細節錯誤。有些錯誤在從不一樣數據集中提取特定圖像時獲得了處理,可是有些問題仍然未獲得解決。爲了改進下一版產品的結果,咱們將專門針對模型「難處理」的圖像使用數據加強 (Data Augmentation)法。

上文探討了這個問題以及數據集問題,如今咱們來看看咱們的模型遇到的一些問題:

  • 衣服——顏色很是深或很是淺的衣服有時會被誤看成爲北京。

  • 「缺口」——除了好的結果,得出的一些圖像中存在缺口。

                                                                                               衣服和缺口

  • 光線問題——光線不足和陰暗在圖像中很常見,可是COCO數據集中的圖像卻沒有這個問題。所以,處理可以解決一些標準的困難,咱們的模型如今還不能處理一些較難處理的圖像。可是,咱們能夠經過增長數據量以及數據加強法(data augmentation)來改進模型。另外,請避免在夜間使用咱們的App。

                                                                                   光線不足問題

                                       進一步改進模型的方法

進一步訓練

在用訓練數據完成了約300 epoch的訓練後,咱們得出了生產結果。在此階段結束後,模型開始過分擬合。咱們在發佈產品前不久才得出了這些結果,所以咱們還沒機會應用基本的數據加強操做。

在將圖像尺寸調整爲224X224後,咱們對模型進行了訓練。使用更多的數據和更大的圖像(COCO數據集圖像的原始尺寸爲600X1000)訓練模型預計也能夠改進結果。

CRF和其餘加強

在有些階段中,咱們看到得出的圖像在邊緣有少量噪點。可使用CRF模型解決這個問題。在這篇博文中(http://warmspringwinds.github.io/tensorflow/tf-slim/2016/12/18/image-segmentation-with-tensorflow-using-cnns-and-conditional-random-fields/),做者給出了CRF。可是,CRF對咱們的工做幫助不大,也許是由於一般只有在結果較爲粗糙時它纔能有所幫助。

Matting

即便是咱們如今得出的結果,其分割效果也不完美。咱們永遠也不能完美地分割頭髮、細緻的衣服、樹枝和其餘精細的物體,就是由於ground truth分割圖像不涵蓋這些細節。分割此類細緻分割圖像的任務稱爲matting,這是一種不一樣的挑戰。這是一個優秀matting方案的實例(https://news.developer.nvidia.com/ai-software-automatically-removes-the-background-from-images/),發表在今年上半年內的NVIDIA會刊上。


                                  Matting 示例——輸入圖像也包含trimap

Matting任務不一樣於其餘圖像處理任務,由於它的輸入不只包含一張圖像,還有一個trimap——圖像邊緣的輪廓線,這使matting任務成了一個「半監督」問題。

咱們將分割圖像做爲trimap,進行了一些matting試驗,可是得出的結果並很差。

還有一個問題時缺少訓練所需的合適數據集。

                                                     總結

正如文章開頭說的那樣,咱們的目標是開發一個有意義的深度學習產品。Alon在其文章中指出,機器學習的應用正變得愈來愈簡單及快速。可是,模型訓練倒是一個棘手的問題——訓練(尤爲是夜間訓練)時須要仔細地進行計劃、調試和記錄結果。

要想平衡研究和創新、訓練與改進之間的關係也不容易。由於使用的是深度學習方法,咱們總感受最好的模型或者最適合咱們的模型近在咫尺,也許谷歌再發布一項的研究或一篇論文,咱們就能找到實現的方法。可是實際上,咱們模型的改進其實是從原始模型中一點一點地「擠出來」的。就像我上文所說的,咱們仍然感受進步的空間還很大。

最後,咱們在工做期間得到了不少樂趣,幾個月以前這項工做在咱們看來像是科幻小說同樣。咱們很樂意討論和回答任何問題,但願能在咱們的網站上看到您:

greenScreen.AI。感謝 Alon Burg.


(看到這裏,營長想說,幸虧沒學PS,之後俺只需輕輕一點,分分鐘修完上萬張圖片。耶耶耶!雖然這傢伙的模型還不成熟,沒事,營長等。)


做者:Gidi Shperber 機器學習發燒友


原文地址

https://medium.com/towards-data-science/background-removal-with-deep-learning-c4f2104b3157?nsukey=HjVxf540wVOL13ThjgEVgqK6yTM0j%2BlZf%2B56cPoPdFCFk%2F6NrblQg0ftuvs82azzYzUhxR4SKluuDZW6Hpk5849qrjCLB8VJg0ULIGW9dHP0nuecErk37IqJ%2Ff3A%2Bip8DzhS1EkpoXYPded2mOJbdA%3D%3D

相關文章
相關標籤/搜索