[ I am Jarvis ] :聊聊 FaceID 背后的深度學習視覺算法
在上周發布的iPhoneX中,最吸引我的,不是那蠢萌的兔耳朵,而是蘋果的FaceID。在蘋果用FaceID取代TouchID的背后,是強大的視覺算法支持,讓iPhoneX有能力識別各種欺騙和偽裝,從而敢于將FaceID作為最重要的安全校驗手段。
正如大家所知曉的,深度學習算法最近迅猛發展,推動著人工智能的發展。2012年AlexNet在ImageNet數據集上的成功,使沉寂已久的卷積神經網絡(Concolutional Neural Network, CNN)再次獲得人們的關注,VGG,ResNet等一系列模型的提出賦予了計算機接近人類的視覺能力。循環神經網絡(Recurrent Neural Network, RNN)在自然語言處理和語音識別等領域的應用,突破了傳統模型難以把握時序數據的瓶頸。深度學習作為一種基礎能力,推動著遷移學習、強化學習等一系列相關學科的發展,當然,這里面也包括了視覺相關的變革。
為此,我們將多個經典的深度學習算法和模型,融入到Jarvis算法庫中,并通過Tesla平臺給大家使用。目前Jarvis的深度學習類目,已經集成了9種不同算法,分布于如下3大類:
本文將會重點介紹計算機視覺領域的幾種經典算法,包括其原理、模型和適用場景。其他領域之后也會陸續有文章,請大家要持續關注喲~
計算機視覺概要
計算機視覺是一門研究如何使機器“看懂”世界的科學。計算機視覺采用圖像處理、模式識別和人工智能技術相結合的手段,著重于對一幅或多幅圖像進行分析,從而獲得需要的信息。因此計算機視覺也可以看做是研究如何使人工系統從圖像或多維數據中“感知”的科學。具體來說,計算機視覺包含物體的檢測和識別、物體跟蹤、圖像恢復(移除噪聲等)和場景重建等。
從2012年Alexnet摘下視覺領域競賽ILSVRC的桂冠以來,Deep Learning便一發不可收拾,ILSVRC每年都不斷被深度學習刷榜。下圖中的這些模型,代表了深度視覺領域發展的里程碑。隨著模型變得越來越深,Top-5的錯誤率也越來越低,在Resnet上的結果已經達到了3.5%附近,而在同樣的ImageNet數據集上,人眼的辨識錯誤率大概在5.1%,也就是說深度學習模型的識別能力已經超過了人類。
(http://ai.51cto.com/art/201704/538154.htm)
經典算法和模型
Alexnet、VGG等網絡不僅在ImageNet上取得了很好的成績,而且還可以被用于其他場景。為了方便用戶能靈活快速地訓練這些模型,我們在Jarvis中,集成了這些算法。用戶可以在Tesla上直接拖出對應算法節點,無需再編寫復雜的網絡定義和模型訓練代碼,就可以對相應的圖片進行訓練,得到一個基本可用的模型。當然了,如果要效果好的話,還是要自己耐心慢慢調試的哈~
1. AlexNet
AlexNet的網絡結構如下圖所示,可以看到AlexNex在大體結構上仍遵循了傳統CNN的原則,由卷積、下采樣和全連接層逐一構成。圖中詭異的“上下分層”的畫法其實是指GPU的并行。
AlexNet在ImageNet上能取得較好的成績,除了利用較深和較寬的網絡結構來增強學習能力外,在數據處理和訓練技巧上還有以下幾點值得借鑒:
- Data Augmentation
Data Augmentation(數據增強)是一種在基礎數據上進行一系列操作,從而得到更多數據,來增強數據集的多樣性的手段,可以在一定程度上減少過擬合。AlexNet在ImageNet上訓練時用到的數據增強方式有以下幾種:
水平翻轉
隨機裁剪
顏色/光照變化等
- Dropout
Dropout是指在深度學習網絡的訓練過程中,對于神經網絡單元,按照一定的概率將其暫時從網絡中丟棄。對于隨機梯度下降來說,由于是隨機丟棄,因此可以看做每一個mini-batch都在訓練不同的網絡。它是防止網絡過擬合,增強模型泛化性的一個有效方法。
下圖左邊是常見的層連接,每一次dropout都相當于從原始的網絡中找到一個更“瘦”的結構,像右圖那樣。在訓練階段,我們設定一個dropout因子p,范圍為0-1,表示在前向計算階段需要隨機斷開的連接的比例,并且在反向傳播時只更新沒有斷開的權重值。在測試階段則需要使用全部的連接,但這些權重都需要乘上1-p。
需要注意的是,每一次的斷開和更新都是以p的概率隨機實現的,因此每次迭代時的斷開都不一樣。對于一個有n個節點的神經網絡,假設dropout因子p=0.5,那么在前向的次數足夠多的情況下,在整個訓練過程中會得到2^n種連接組合,也就相當于訓練了2^n個模型,***得到的是2^n個模型的組合。
(http://blog.csdn.net/stdcoutzyx/article/details/49022443)
ReLU激活函數
ReLu激活函數與傳統的Tanh或Logistic函數相比有以下幾個優點:
- 前向計算和反向求偏導的過程都非常簡單,沒有復雜的指數或除法之類的操作
- 不像tanh和logistic那樣有”flat spot”,因此不容易發生梯度彌散的問題
- 關閉了左邊,可以使很多隱層輸出為0,因此使網絡變得稀疏,有一定的正則化作用,可以緩解過擬合
Relu函數的缺點也體現在被關閉的左邊部分,如果某些節點的輸出落在函數左邊,那么其將“永無翻身之日”。為了解決該問題后來又出現了pRelu等改進的激活函數,即給函數左邊也賦予一定的梯度,在保證非線性的同時不至于讓某些節點“死掉”。
(http://gforge.se/2015/06/benchmarking-relu-and-prelu/)
- 局部響應歸一化(Local Response Normalization,LRN)
神經生物學上有一個概念叫做“側抑制(lateral inhibitio)”,指被激活的神經元對相鄰神經元有一定的抑制作用。
LRN就是借鑒側抑制的思想來對局部神經元的活動創建競爭機制,使響應比較大的值相對更大,從而提高模型的泛化能力。LRN有兩種歸一化模式:通道內和通道間,具體可以參考該篇文章。在論文的ImageNet的實驗中,LRN可以降低1.2%的top-5錯誤率,但從我們在其他數據集上的實驗來看,LRN提升訓練效果并不是那么顯著,因此可以看到LRN的操作并不是適用于所有場景的,還是要多實驗才能出結果。
- 交疊的pooling
顧名思義,就是指在做pooling的時候也會存在overlap的部分。一般來說pooling是將輸入的結果進行分塊處理,通過提取該塊的***值(max pooling)或平均值(average pooling)來實現下采樣的過程,這里的塊間是相互不交疊的。在AlexNet中卻會有overlap的部分。和LRN一樣,這個trick不一定適用于所有場景。
綜合以上幾個技巧,整體來看,AlexNet還是非常經典的一個算法。所以我們將AlexNet集成到Jarvis的深度學習算法的視覺類目下。在實現上,我們根據AlexNet原本的構建和訓練方式、參考Alex發表的《One weird trick for parallelizing convolutional neural networksc》這篇文章,做了如下幾個事情,包括:
- 移除了LRN層,并將參數的初始化改成xavier方式。
- 激活函數使用Relu函數
- 正則化選擇L2正則化
- 在fc6和fc7兩個全連接層使用系數為0.5的dropout操作
- 自動Resize:在數據的輸入上,給定的輸入圖像是224x224x3的大小,如果讀取到的圖像大于該尺寸,則會將其隨機crop到224x224x3,如果讀取到的圖像小于該尺寸,則會將其resize到224x224x3。
另外,我們對輸入圖像也提供了一些data augmentation的操作,包括水平翻轉、顏色、光照變化等,文章后部分會有相關參數的描述。
2. VGG16
VGG16繼承了alexnet的框架,但其通過加深卷積層數的方法獲得了比AlexNet更高的圖像識別率,是一種比AlexNet更深的網絡結構,如下圖所示,更詳細的網絡結構參數可以參考該論文。
(https://www.cs.toronto.edu/~frossard/post/vgg16/ )
與AlexNet相比,VGG16明顯的不同之處在于:
- 連續的convolution塊和較小的filter size
通過網絡結構圖可以看到,vgg16中含有多個連續的convolution操作(圖中黑色框部分),而這些卷積層的卷積核大小都為3x3,相比AlexNet的7x7小很多??梢岳斫獬蒝GG通過降低filter的大小,同時增加卷積層數來達到同樣的效果。
This can be seen as imposing a regularisation on the 7 × 7 conv. filters, forcing them to have a decomposition through the 3 × 3 filters
較小的卷積核在一定程度上減少了需要訓練的權重個數,假設輸入和輸出的channel數都為C,在7x7大小的卷積核下,該層的權重個數為7x7xCxC=49xCxC,而此時VGG中連續的3個卷積層的權重個數為3x3x3xCxC=27xCxC。權重個數的減少有利于網絡的訓練和泛化。
- 通道數(channels)增多
對比AlexNet和VGG可以發現AlexNet的channel數明顯小于VGG。如此一來,網絡可以對輸入提取更豐富的特征。VGG之所以能夠達到更高的準確率,與通道數的增多有較大關系。
VGG16也被集成到Jarvis的深度學習算法的視覺模塊下。除了網絡結構的定義不同外,其他都與Alexnet相似,包括全連接層的dropout設置,Relu激活函數和L2的正則化。
- 3. VGG19
VGG19和上面小節所述的VGG16其實出自同一篇論文,是一種方法的兩種不同配置。VGG19的網絡結構與VGG16非常相似,差別在于VGG19在第3、4、5個“卷積塊”里分別加多了一個卷積層,因此比VGG16多了3個weight layer。這里就不再贅述。
除了上述的AlexNet和VGG系列的網絡結構外,Jarvis還會逐步集成Googlenet,Resnet等,歡迎大家持續關注。
自定義網絡
經典算法雖好,但是總會有一定的局限性的。為了提供更好的靈活度,Jarvis上還集成了基于卷積神經網絡的分類和回歸算法,其***優點是可以對網絡結構進行靈活的自定義,從而滿足不同場景下的需求。
在TensorFlow中定義一個卷積+激活層通常需要如下幾行代碼:
- with tf.name_scope('conv2') as scope:
- kernel = tf.Variable(tf.truncated_normal([5, 5, 96, 256], dtype=tf.float32,stddev=1e-1), name='weights')
- biases = tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32),trainable=True, name='biases')
- conv2 = tf.nn.conv2d(pool1, kernel, [1, 1, 1, 1], padding='SAME')
- conv2 = tf.nn.relu(tf.nn.bias_add(conv2, biases))
這還只是一個卷積層的構造,如果我們要構建的網絡由十幾或者幾十層組成,則估計要敲好幾百行代碼了,而且重點是你就算復制黏貼相同性質的層也不一定找得準眼花繚亂的參數啊。
好在tensorflow也支持一些接口的高級抽象如slim、keras和tensorlayer等,這樣一個卷積層就可以一句話寫完,比如在slim可以如此定義一個卷積層操作:
net = layers.conv2d(inputs, 64, [11, 11], 4, padding='VALID', scope='conv1')
盡管這些高級接口使網絡的定義簡便了不少,但如果在訓練過程中要多次調整網絡結構,這樣hardcode的形式則仍然很不方便。
鑒于以上,我們在tesla上實現CNN時,將網絡結構單獨抽出來作為一個可修改的參數傳入到算法中。該網絡參數其實是一個json文件,文件中的每一行表示一個層,***幾行表示數據輸入的一些信息。
一個CifarNet的網絡結構如下圖所示:
(https://inclass.kaggle.com/c/computer-vision-cs543-ece549)
將該CifarNet轉成我們自定義的json文件后示例如下:
- {
- "layer1" : { "operation": "conv", "maps": 64, "kernel_height": 5, "kernel_width": 5, "stride_height": 1,"stride_width": 1, "padding": "SAME", "activation_func": "relu"},
- "layer2" : { "operation": "max_pool", "kernel_height": 3,"kernel_width":3,"stride_height": 2,"stride_width":2, "padding": "SAME"},
- "layer3" : { "operation": "conv", "maps": 64, "kernel_height": 5,"kernel_width":5, "stride_height": 1,"stride_width":1, "padding": "SAME", "activation_func": "relu"},
- "layer4" : { "operation": "max_pool", "kernel_height": 3,"kernel_width":3, "stride_height": 2,"stride_width":2, "padding": "SAME"},
- "layer5" : { "operation": "fc", "maps": 384, "dropout_rate": 1.0, "activation_func": "relu"},
- "layer6" : { "operation": "fc", "maps": 192, "dropout_rate": 1.0, "activation_func": "relu"},
- "layer7" : { "operation": "fc", "maps": 100},
- "initial_image_height": 32, "initial_image_width": 32,
- "input_image_height": 32, "input_image_width": 32,
- "normalize": 1,"crop": 1,"whitening": 1,"contrast": 1,"flip_left_right": 1,"brightness": 1
- }
還有更懶的親們甚至可以直接復制這份模板,然后按自己的網絡定義更改一下里面的參數就可以了。在tesla界面運行時,如果需要修改網絡結構,可以直接在界面右邊的參數配置編輯該json文件,不需要再修改并上傳代碼啦~~
基于上述的自定義網絡結構的特點,我們配置了CNN的分類和回歸兩種算法。
1. CNN Classification
基于卷積神經網絡CNN的分類算法。支持如上所述的網絡結構自定義,可以適應不同場景下的圖像分類任務。
2. CNN Regression
基于卷積神經網絡CNN的回歸算法,與CNN classification類似,區別在于訓練時用的是歐氏距離損失函數,可以接受float類型的標簽。注意在配置網絡結構時***一層的feature map個數為1,而不是分類中的類別數。
Jarvis視覺算法的使用
目前,Jarvis主要通過Tesla平臺透出,其訓練和使用都非常簡單,總體來說可以分為三個步驟:數據準備、模型訓練和模型使用
1. 數據準備
在開始訓練前,我們需要準備好訓練集和測試集數據。對于目前計算機視覺目錄下的算法,輸入都為圖像數據,并且都需要轉換成tfrecord的格式。
打開Tesla的工作界面,在輸入->數據源下拖出數據集節點,點擊該節點,完整填寫界面右邊的參數配置選項,便完成了一個數據節點的配置。轉換節點可以加在數據節點之后。為了方便用戶使用,我們會提供一個image->tfrecord的轉換工具,放在輸入->數據轉換目錄下。
2. 模型訓練
在tesla工作流界面從左邊的深度學習算法下拖出想要訓練的算法節點。點擊該節點,右側會出現參數配置選項,包含算法IO參數,算法參數和資源配置參數。
- 資源參數
指定模型訓練時所需的GPU和CPU資源。
- 算法IO參數
用于指定數據集、模型存儲和Tensorboard保存的ceph路徑,這里我們只需要指定數據集所在路徑,而模型存儲和Tensorboard路徑由Tesla默認指定。
如果算法節點上有對應的數據集節點,則該數據集節點的數據路徑會自動匹配到算法的數據輸入路徑,不想拖數據集節點的用戶也可以手動填寫算法的數據輸入路徑。
- 算法參數
用于指定訓練過程中所需的參數。深度學習各算法的參數有一部分是相通的,如批處理大小、學習率和迭代次數等。但不同的算法也可能有自己特殊的參數。在下面的介紹中,我們將會在各算法的詳細介紹鏈接里找到對應的參數解釋。
對于CNN Classification/Regression算法來說,由于支持網絡結構的自定義,因此參數與上表會稍有不同。以工作流右側的參數配置項目為準。
配置完各參數后,右鍵點擊該算法節點,選擇起點運行即可開始訓練模型。在訓練過程中可通過tensorflow控制臺查看log信息和tensorboard可視化,便于把握訓練走向。
3. 模型收藏和使用
模型使用指用訓練好的模型做預測工作。除了在剛訓練完成時對模型做預測外,Tesla還貼心地提供了模型收藏功能,可以留待以后再做預測。
模型收藏:在模型操作下選擇收藏模型可以將模型收藏到tesla界面左邊的個人模型目錄下,下一次需要使用的時候可以直接拖出模型節點,填寫相應的配置參數,右鍵選擇起點運行即可。
結語
本篇文章介紹了計算機視覺領域比較經典的幾種深度學習算法,同時展示了如何在tesla平臺上快速靈活地訓練和使用深度學習模型。在算法Demo下有各個算法的樣例工程供大家參考。
***,再一次提一下蘋果的FaceID。FaceID的成功啟用無疑是計算機視覺領域在人類生活應用中的一大進步,其低于指紋解鎖的破解率與背后的機器學習尤其是深度學習算法密不可分。當然,FaceID背后的人臉識別技術肯定比本文中簡單介紹的幾種算法復雜的多,這里我們就不深入探討了,因為就算你問我我也不知道呀,呵呵~~ 不過,蘋果在去年的CVPR上發表了一篇SimGAN的文章《Learning from Simulated and Unsupervised Images through Adversarial Training》,有興趣的可以看一下。另外,蘋果在去年的NIPS上宣布會開始公開他們的研究成果,相信這一決定會給學術界和工業界帶來很多驚喜,大家可以期待一下。
***+1,本文由andymhuang和royalli指導完成,這里表示感謝。如果在使用算法時遇到相關問題,歡迎咨詢我(joyjxu)或者royalli,也墻裂歡迎各種批評指正意見!
原文鏈接:https://www.qcloud.com/community/article/648055
作者:許杰
【本文是51CTO專欄作者“騰訊云技術社區”的原創稿件,轉載請通過51CTO聯系原作者獲取授權】