作者:Adam Geitgey 譯者:巡洋艦科技——趙95 校對:離線Offline——林沁 轉(zhuǎn)載請聯(lián)系譯者。 你有沒有發(fā)現(xiàn) Facebook 研發(fā)出了一種能夠在你的照片中識別出你朋友的神奇neng li? 之前,你需要手動點(diǎn)擊你朋友的照片,輸入他們的名字,然后加上標(biāo)簽?,F(xiàn)在,只要你一上傳照片,F(xiàn)acebook 就會神奇地標(biāo)注出你的每一個朋友: ![]() 這種技術(shù)被稱為人臉識別。你的朋友被標(biāo)記了幾次之后,F(xiàn)acebook 的算法就能夠識別你朋友的臉。 這是一項(xiàng)非常驚人的黑科技——Facebook 的人臉識別準(zhǔn)確率達(dá)到了 98%,幾乎與人類做得一樣好! 讓我們來了解一下現(xiàn)代人臉識別是如何工作的! 但是,識別你的朋友這太容易了。 我們可以最大化擴(kuò)展這項(xiàng)技術(shù),來解決一個更具挑戰(zhàn)性的問題——區(qū)分威爾·法瑞爾(Will Ferrell,著名演員)和查德·史密斯(Chad Smith,著名搖滾音樂家)! ![]() 如何用機(jī)器學(xué)習(xí)解決復(fù)雜問題?到目前為止,在前三章,我們用機(jī)器學(xué)習(xí)來解決了一些一步就能完成的問題——估計(jì)房子的價格、基于現(xiàn)有數(shù)據(jù)生成新數(shù)據(jù)[1]、判別圖像當(dāng)中是否包含某個物品。 所有這些問題都可以通過下列步驟解決:選擇一個機(jī)器學(xué)習(xí)算法,輸入數(shù)據(jù),然后獲得結(jié)果。 但是,人臉識別是由一系列的幾個相關(guān)問題組成的: 1. 首先,找到一張圖片中的所有人臉。 2. 第二,對于每一張臉來說,無論光線明暗或面朝別處,它依舊能夠識別出是同一個人的臉。 3. 第三,能夠在每一張臉上找出可用于與他人區(qū)分的獨(dú)特之處,比如說眼睛有多大,臉有多長等等。 4. 最后,將這張臉的特點(diǎn)與已知的所有人臉進(jìn)行比較,以確定這個人的姓名。 作為人類,你的大腦總是在一瞬間自動做出了這些判斷。實(shí)際上,人類在識別人臉這方面做得太好了,以至于他們會在日常物品中同樣去「找臉」: 我們需要構(gòu)建一個流水線(pipeline)來識別人臉,它可以把上一個步驟的結(jié)果發(fā)送給下一個步驟。換句話說,我們會將好幾個機(jī)器學(xué)習(xí)算法連接到一起: ![]() 人臉識別——分步講解讓我們一步一步地解決這個問題。 對于每個步驟,我們將學(xué)習(xí)一個不同的機(jī)器學(xué)習(xí)算法。 我并不會完全解釋每一個的算法,否則這篇文章就變成了一本教科書。但你會學(xué)到每個步驟的精髓,以及如何在 Python 中使用 OpenFace 和 dlib 來構(gòu)建一個你自己的面部識別系統(tǒng)。 第一步:找出所有的面孔我們流水線的第一步是人臉檢測。顯然,在我們區(qū)分人臉之前,我們必須要照片中找到他們才行! 如果你在過去 10 年里使用過相機(jī),你可能已經(jīng)見過正在運(yùn)行中的人臉檢測功能: 2000 年初的時候, 當(dāng)保羅·比奧拉(Paul Viola)和邁克爾·瓊斯(Michael Jones) 發(fā)明了一種能夠快速在廉價相機(jī)上運(yùn)行的人臉檢測方法之后[2],人臉檢測在成為了主流。然而現(xiàn)在,更可靠的解決方案出現(xiàn)了。 我們將使用 2005 年發(fā)明的一種稱為方向梯度直方圖(Histogram of Oriented Gradients)的方法,簡稱 HOG。 要在一張圖片中找到臉,我們首先將圖像轉(zhuǎn)換為黑白,因?yàn)槲覀儾⒉恍枰伾珨?shù)據(jù)來找到臉: ![]() 如果你對圖片中的每一個像素重復(fù)這個過程,最終每個像素會被一個箭頭取代。這些箭頭被稱為梯度(gradients),它們能顯示出圖像上從明亮到黑暗的流動過程: 但是保存每個像素的梯度太過細(xì)節(jié)化了,我們最終很有可能「一葉障目不見泰山」。如果能從更高的角度上觀察基本的明暗流動,我們就可以看出圖像的基本規(guī)律,這會比之前更好。 為了做到這一點(diǎn),我們將圖像分割成一些 16×16 像素的小方塊。在每個小方塊中,我們將計(jì)算出每個主方向上有多少個梯度(有多少指向上,指向右上,指向右等)。然后我們將用指向性最強(qiáng)那個方向的箭頭來代替原來的那個小方塊。 最終的結(jié)果是,我們把原始圖像轉(zhuǎn)換成了一個非常簡單的表達(dá)形式,這種表達(dá)形式可以用一種簡單的方式來捕獲面部的基本結(jié)構(gòu): ![]() 為了在這個 HOG 圖像中找到臉部,我們要所需要做的,就是找到我們的圖像中,與已知的一些 HOG 圖案中,看起來最相似的部分。這些 HOG 圖案都是從其他面部訓(xùn)練數(shù)據(jù)中提取出來的: 如果你想用 Python 和 dlib 親手試試看,這些代碼顯示了如何生成和查看 HOG 圖像。 第二步:臉部的不同姿勢哇,我們把圖片中的臉部分離出來了。 但現(xiàn)在,我們要處理的問題就是,對于電腦來說,面朝不同方向的同一張臉,是不同的東西: ![]() 人類可以很輕松地識別出到兩個圖片都是威爾·法瑞爾,但電腦會認(rèn)為這兩張圖片是兩個完全不同的人。 為了解決這一點(diǎn),我們將試圖扭曲每個圖片,使得眼睛和嘴唇總是在圖像中的樣本位置(sample place)。 這將使我們在接下來的步驟中,更容易比較臉部之間的不同。 為此,我們將使用一種稱為面部特征點(diǎn)估計(jì)(face landmark estimation)的算法。 很多方法都可以做到這一點(diǎn),但這次我們會使用由 瓦希德·卡奇米(Vahid Kazemi)和約瑟菲娜·沙利文(Josephine Sullivan)在 2014 年發(fā)明的方法。 這一算法的基本思路是找到 68 個人臉上普遍存在的特定點(diǎn)(稱為特征點(diǎn), landmarks)——包括下巴的頂部、每只眼睛的外部輪廓、每條眉毛的內(nèi)部輪廓等。接下來我們訓(xùn)練一個機(jī)器學(xué)習(xí)算法,讓它能夠在任何臉部找到這 68 個特定的點(diǎn): ![]() 我們將在每一張臉上定位的 68 個特征點(diǎn)。這張圖片的作者是在OpenFace工作的卡內(nèi)基梅隆大學(xué) Ph.D. 布蘭東·阿莫斯(Brandon Amos)。 這是在測試圖片上定位 68 個特征點(diǎn)的結(jié)果: ![]() 現(xiàn)在,我們知道了眼睛和嘴巴在哪兒,我們將圖像進(jìn)行旋轉(zhuǎn)、縮放和錯切,使得眼睛和嘴巴盡可能靠近中心。我們不會做任何花哨的三維扭曲,因?yàn)檫@會讓圖像失真。我們只會使用那些能夠保持圖片相對平行的基本圖像變換,例如旋轉(zhuǎn)和縮放(稱為仿射變換): 如果你想用 Python 和 dlib 親手試試看這一步的話,這里有一些代碼幫你尋找臉部特征點(diǎn)并用這些特征點(diǎn)完成圖像變形。 第三步:給臉部編碼現(xiàn)在我們要面臨最核心的問題了——如何區(qū)分不同的人臉。這才是這件事的有趣之處! 最簡單的人臉識別方法,就是直接把我們在第二步中發(fā)現(xiàn)的未知人臉,與我們已經(jīng)標(biāo)注了的人臉圖片作比較。當(dāng)我們發(fā)現(xiàn)未知的面孔與一個以前標(biāo)注過的面孔看起來及其相似的時候,它肯定是同一個人。似乎這主意看起來不錯,對吧? 實(shí)際上這種方法有一個巨大的問題。像 Facebook 這種擁有數(shù)十億用戶和數(shù)萬億張照片的網(wǎng)站,是不可能去循環(huán)比較每張先前標(biāo)記的臉的,這浪費(fèi)的時間太長了。他們需要在毫秒內(nèi)識別人臉,而不是幾個小時。 我們需要的方法是一種從每張人臉上提取一些基本的測量數(shù)值。然后,我們可以用同樣的方式測量未知的面孔,并找到最接近測量數(shù)值的那張已知的臉。例如,我們可以測量每個耳朵的大小、眼睛之間的間距、鼻子的長度等。如果你曾經(jīng)看過像《犯罪現(xiàn)場調(diào)查》這樣的電視劇,你就知道我在說什么了。 https://cdn-images-1.medium.com/max/800/1*_GNyjR3JlPoS9grtIVmKFQ.gif 就像電視劇一樣!非常真實(shí)!#科學(xué) 測量人臉的最可靠的方法好的,那么我們應(yīng)該測量面部的哪些數(shù)值,來建立我們的已知臉部數(shù)據(jù)庫呢?耳朵的大?。勘亲拥拈L度?眼睛的顏色?還有什么? 事實(shí)證明,對于我們?nèi)祟悂碚f一些顯而易見的測量值(比如眼睛顏色),對計(jì)算機(jī)來說沒什么意義。研究人員發(fā)現(xiàn),最準(zhǔn)確的方法是讓計(jì)算機(jī)自己找出它要收集的測量值。深度學(xué)習(xí)比人類更懂面部哪些部分的測量值比較重要。 所以,解決方案是訓(xùn)練一個深度卷積神經(jīng)網(wǎng)絡(luò)(就像我們在第三章做的那樣)。但是,并不是讓它去識別圖片中的物體,這一次我們的訓(xùn)練是要讓它為臉部生成 128 個測量值。 每次訓(xùn)練要觀察三個不同的臉部圖像: 1. 加載一張已知的人的面部訓(xùn)練圖像 2. 加載同一個人的另一張照片 3. 加載另外一個人的照片 然后,算法查看它自己為這三個圖片生成的測量值。再然后,稍微調(diào)整神經(jīng)網(wǎng)絡(luò),以確保第一張和第二張生成的測量值接近,而第二張和第三張生成的測量值略有不同。 ![]() 在為幾千個人的數(shù)百萬圖像重復(fù)該步驟數(shù)百萬次之后,神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)了如何可靠地為每個人生成 128 個測量值。對于同一個人的任何十張不同的照片,它都應(yīng)該給出大致相同的測量值。 機(jī)器學(xué)習(xí)專業(yè)人士把每張臉的 128 個測量值稱為一個嵌入(embedding)。將復(fù)雜的原始數(shù)據(jù)(如圖片)縮減為可由計(jì)算機(jī)生成的一個數(shù)列的方法,在機(jī)器學(xué)習(xí)(特別是語言翻譯)中出現(xiàn)了很多次。我們正在使用的這種臉部提取方法是由 Google 的研究人員在 2015 年發(fā)明的,但也有許多類似方法存在。 給我們的臉部圖像編碼這個通過訓(xùn)練卷積神經(jīng)網(wǎng)絡(luò)來輸出臉部嵌入的過程,需要大量的數(shù)據(jù)和強(qiáng)大的計(jì)算能力。即使使用昂貴的 Nvidia Telsa 顯卡,你也需要大約 24 小時的連續(xù)訓(xùn)練,才能獲得良好的準(zhǔn)確性。 但一旦網(wǎng)絡(luò)訓(xùn)練完成,即使它從來沒有見過這些面孔,它也可以生成這張面孔的測量值!所以這種訓(xùn)練只需一次即可。幸運(yùn)的是,OpenFace 上面的大神已經(jīng)做完了這些,并且他們發(fā)布了幾個訓(xùn)練過可以直接使用的網(wǎng)絡(luò)。謝謝布蘭東·阿莫斯和他的團(tuán)隊(duì)! 所以我們需要做的,就是通過他們預(yù)訓(xùn)練的網(wǎng)絡(luò)來處理我們的臉部圖像,以獲得 128 個測量值。這是我們測試圖像的一些測量值: 如果你想自己嘗試這個步驟,OpenFace 提供了一個 lua 腳本,它可以生成一個文件夾中所有圖像的嵌入,并將它們寫入 csv 文件。點(diǎn)此查看如何運(yùn)行。 第四步:從編碼中找出人的名字最后這一步實(shí)際上是整個過程中最簡單的一步。我們要做的就是找到數(shù)據(jù)庫中,與我們的測試圖像的測量值最接近的那個人。 你可以通過任何基本的機(jī)器學(xué)習(xí)分類算法來達(dá)成這一目標(biāo)。我們并不需要太花哨的深度學(xué)習(xí)技巧。我們將使用一個簡單的線性 SVM 分類器,但實(shí)際上還有很多其他的分類算法可以使用。 我們需要做的是訓(xùn)練一個分類器,它可以從一個新的測試圖像中獲取測量結(jié)果,并找出最匹配的那個人。分類器運(yùn)行一次只需要幾毫秒,分類器的結(jié)果就是人的名字! 所以讓我們試一下我們的系統(tǒng)。首先,我使用威爾·法瑞爾、查德·史密斯和吉米·法倫(Jimmy Falon)三人每人 20 張照片的嵌入來訓(xùn)練分類器: ![]() 接下來,我在這個分類器上運(yùn)行了威爾·法瑞爾和查德·史密斯在吉米·法倫的節(jié)目上互相模仿的那個視頻的每一幀: https://cdn-images-1.medium.com/max/800/1*_GNyjR3JlPoS9grtIVmKFQ.gif 結(jié)果成功了!不同角度的臉部,甚至是側(cè)臉,它都能捕捉到! 你自己做一遍讓我們回顧一下我們的步驟: 1. 使用 HOG 算法給圖片編碼,以創(chuàng)建圖片的簡化版本。使用這個簡化的圖像,找到其中看起來最像通用 HOG 面部編碼的部分。 2. 通過找到臉上的主要特征點(diǎn),找出臉部的姿勢。一旦我們找到這些特征點(diǎn),就利用它們把圖像扭曲,使眼睛和嘴巴居中。 3. 把上一步得到的面部圖像放入神經(jīng)網(wǎng)絡(luò)中,神經(jīng)網(wǎng)絡(luò)知道如何找到 128 個特征測量值。保存這 128 個測量值。 4. 看看我們過去已經(jīng)測量過的所有臉部,找出哪個人的測量值和我們要測量的面部最接近。這就是你要找的人! 現(xiàn)在你知道這一切都是如何運(yùn)行的了,這里是如何使用 OpenFace 在你自己的電腦上運(yùn)行整個人臉識別系統(tǒng)的說明: 開始之前確保你已經(jīng)安裝了 python、OpenFace 和 dlib。你也可以在這里手動安裝,或者使用一個已經(jīng)設(shè)定好的 docker image:
運(yùn)行完后,這個./generated-embeddings/子文件夾會包含一個帶有每張圖像嵌入的 csv 文件。
這將生成一個名為 ./generated-embeddings/classifier.pkl的新文件,其中包含了你用來識別新面孔的 SVM 模型。
你應(yīng)該會得到像這樣的一個預(yù)測:
至此,你已經(jīng)完成了一個預(yù)測了。你也可以修改./demos/classifier.py 這個 python 腳本,來讓它匹配其他人的臉。
1. 譯者注:根據(jù)已有的超級馬里奧的關(guān)卡生成新的關(guān)卡 2. 譯者注:這種算法也可以用來訓(xùn)練檢測其他的物品,但是最經(jīng)常還是被用于人臉的檢測,其英文名稱為 Viola–Jones object detection framework |
|