分別來自 《DeepFace: Closing the gap to human-level performance in face verification》(2014) [1]與 《FaceNet: A Unified Embedding for Face Recognition and Clustering》(2015) [2]這兩篇 paper 提出的方法,而外利用OpenCV來擷取 Webcam 影像並使用其提供的 Haar Cascade 分類器進行人臉檢測(Face Detection)
在Face Recognition(人臉辨識)的問題上,通常會再進一步分成兩個種類 :
- Face Verification (人臉驗證) :
- 給予輸入 image, name/ID
- 輸出是否為此人
- 視為 1:1 matching problem
e.g. 手機的人臉解鎖
- Face Recognition (人臉辨識) :
- 擁有 K 個人物的Database
- 給予 Input image
- 輸出 ID, if (image 為 K 個人物中的其中一個)
- 無法辨識此人, if (image 不為K個人物中任何一個)
- 視為 1:K matching problem
e.g. 使用的人臉辨識的員工通行閘門
概念
在人臉辨識 (Face Recognition) 的應用中經常要做到只靠一張照片就能辨認一個人,但深度學習(Deep Learning)的演算法在只有一筆訓練資料的情況下效果會很差,所以在人臉辨識中必須解決 One Shot Learning(單樣本學習) 的問題
One Shot Learning (單樣本學習)
假定某公司內的Database共有4位人員的照片各一張,當有其中一位人員經過系統前的鏡頭並被捕捉到臉孔後,儘管Database只有一張此人的照片,系統依然能辨認出此臉孔為公司裡的員工,相反的,若不為公司內人員則無法辨識此人
Similarity Function (相似度函數)
為了達到One Shot Learning (單樣本學習)這樣的目標,我們希望讓NN(Neural Network)去學習一個 函數 d
d(img1, img2):給予兩張照片,輸出這兩張照片的相異程度
- 如果兩張照片是同一個人,則輸出一個較小的數字
- 如果兩張照片是不同人,則輸出一個較大的數字
此外,需定義一個 Hyperparameter(超參數)「τ」 - 如果d(img1,img2)≤τ→ 相同
- 如果d(img1,img2)>τ→ 不同
如此一來就解決了Face Verification (人臉驗證) 1:1 matching的問題
Siamese network (孿生網路)
使用 《DeepFace: Closing the gap to human-level performance in face verification》(2014) [1]提出的Siamese network架構來達成上述Similarity Function的效果,其實就是使用兩個常見的ConvNet的網路架構,這個兩個網路擁有相同的參數與權重,一樣經由Convolution(卷積)、Pooling(池化)、Fully connected layers(全連接層)最後得到一個帶有128個數字的特徵向量(feature vector),而這個過程稱為encoding(編碼)
- 將兩張圖片(這裡稱x(1)與x(2))放入這兩個ConvNet後得出編碼後的兩個特徵向量(feature vector)
- 為了算出兩張圖片相似度,方式為將這兩個經由編碼所獲得的128維特徵向量f(x1)、f(x2)相減並取2範數(2-Norm)的平方,這樣我們就透過Siamese network學習出我們所想要的Similarity Function(相似度函數)
Note:2範數(2-Norm)又稱為為歐基里德範數(Euclidean norm),是以歐式距離的方式作為基礎,計算出向量的長度或大小
- 總結來說,在Siamese network的架構我們希望能學出一種encoding(編碼)方式,更準確來說是希望學習出參數使得我們能達成以下的目標
在上述的目標中,改變 ConvNet 每一層的參數就會得到不同的編碼,所以我們可以利用反向傳播(Backpropagation)來更改這些參數以達到上列的目標
Triplet Loss (三元組損失)
在NN(Neural Network)的訓練中,都需要一個損失函數(Loss function)作為最小化(minimize)目標,而在Face recognition的應用中為了能夠學習參數來得到良好的編碼(encoding), 《FaceNet: A Unified Embedding for Face Recognition and Clustering》(2015) [2]這篇論文提出一種有效的損失函數稱為 Triplet Loss (三元組損失)
- 在 Triplet Loss 中會有 Anchor 、 Positive 、 Negative 這三種照片
- Positive 為與 Anchor 同個人 的照片
- Negative 則為 不同人 的照片
- 我們需要比較 Anchor 分別與 Positive 和 Negative 一組的兩對的照片
- 目標是希望 Anchor 與 Positive 的距離(編碼) 較近 ,與 Negative 的距離(編碼) 較遠
也就是說,我們希望神經網路的參數所造成的編碼能夠使 Anchor 與 Positive的距離 小於等於 Anchor 與 Negative 的距離這樣的性質
在上圖中,Anchor、Positive、Negative分別簡寫為A、P、N
- 如果 f 變成 零函數 會將每個向量的輸出都變成零,就是所謂的 trivial solutions ,則0 – 0 ≤ 0 這樣就很容易滿足這個不等式,會讓NN學不到我們的目標
- 為了不讓 NN 將編碼學習成零函數,我們希望兩對的照片的差距不只小於等於零,還要 比零還小一些 ,因而外引進一個超參數(Hyperparameter) α ,這個 α 稱為 邊距 (margin),我們讓 ≤ 這個符號左邊的式子小於負α,習慣上會將 α 移到式子左邊
- 而 margin(邊距) 用意即是拉開 d(A,P) 與 d(A,N) 這兩對的差距,就是把這兩對推開, 盡量的遠離彼此
e.g. 假設 margin = 0.2 ,表示若 d(A,P)=0.5 則 d(A,N) 至少0.7才符合上述的不等式,若 d(A,N) 為0.6就不符合,因為兩組的差距不夠大 - Triplet Loss 的實現如下
``
def triplet_loss(y_true, y_pred, alpha = 0.3):
anchor, positive, negative = y_pred[0], y_pred[1], y_pred[2]
# Step 1: 計算anchor和positive的編碼(距離)
pos_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, positive)), axis=-1)
# Step 2: 計算anchor和negative的編碼(距離)
neg_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, negative)), axis=-1)
# Step 3: 將先前計算出的距離相減並加上邊距alpha
basic_loss = tf.add(tf.subtract(pos_dist, neg_dist), alpha)
# Step 4: 將上述計算出的損失與零取最大值,再將所有樣本加總起來
loss = tf.reduce_sum(tf.maximum(basic_loss, 0.0))
return loss ``
def triplet_loss(y_true, y_pred, alpha = 0.3): anchor, positive, negative = y_pred[0], y_pred[1], y_pred[2] # Step 1: 計算anchor和positive的編碼(距離) pos_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, positive)), axis=-1) # Step 2: 計算anchor和negative的編碼(距離) neg_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, negative)), axis=-1) # Step 3: 將先前計算出的距離相減並加上邊距alpha basic_loss = tf.add(tf.subtract(pos_dist, neg_dist), alpha) # Step 4: 將上述計算出的損失與零取最大值,再將所有樣本加總起來 loss = tf.reduce_sum(tf.maximum(basic_loss, 0.0)) return loss
Loss Function (損失函數)
Triplet Loss 定義在3張一組的圖片A、P、N上,則損失函數則可以定義成:
這個 max 函數的用意在於,若括號的左邊項 ≤ 0則損失就為零,若左邊項 > 0則損失變成大於零;而我們是希望損失越小越好,所以只要左邊項 ≤ 0不管負多少,就能把損失推向零
Cost function (成本函數)
將訓練資料裡一組三張圖片的損失加總起來作為整體 NN 的總成本(Total cost),並利用 Gradient descent (梯度下降法)來去訓練 NN 最小化成本
Note: 假定有10000張訓練圖片,分別來自1000個不同的人(每人約10張圖片)才能構成我們的資料集,若每個人只有一張照片這樣就無法順利挑出Anchor 與 Positive,但是當 NN 訓練完成後就可以將系統用在 One-shot Learning 的問題,對於你想辨識的人,你可能只有他的一張照片也能順利辨識出此人。
選擇三胞胎A,P,N
- 在訓練資料中,Triplets(三元組)樣本的選擇會是一個問題,因為在上述學習目標 d(A,P) + α ≤ d(A,N) 中,若只按照要求隨機的選擇同一個人的照片A與P 和不同人照片A與N,則這個不等式很容易就被滿足,因為隨機挑兩個人的照片有很大的機率使得A與N差異遠大於A與P,這會使得NN無法學習有效的參數
- 因此,要建立訓練集的話必須挑選那種很難訓練的A,P和N,因為目標是讓所有Triplets(三元組)滿足d(A,P) + α ≤ d(A,N) 這個不等式,而很難訓練的Triplets(三元組)的意思就是你所挑選的A,P和N會讓 d(A,P)≈ d(A,N) ,如此一來NN在學習的時候就必須花更大的力氣嘗試讓d(A,N)往上推或讓d(A,P)往下掉 ,推開彼此以達到相隔α的邊距,這樣的效果會讓你的學習演算法更效率;反之,若隨便選會導致很多的Triplets(三元組)都解起來很簡單,Gradient descent(梯度下降法)就不會再做任何事,因為你的NN早已把問題都做對了,在這部分在 《FaceNet: A Unified Embedding for Face Recognition and Clustering》(2015) [2]這篇論文有更詳細的說明
Face detection (人臉偵測)
在人臉偵測的部分使用 OpenCV 的 Haar Cascade 分類器,選擇的為人臉分類器 haarcascade_frontalface_default.xml
用法
- 在Windows上
例如:使用Tensorflow作為後端 > python facenet.py
結果
- 利用 OpenCV 的 Haar Cascade 分類器進行人臉偵測(Face detection)
- 偵測出人臉後使用預訓練的 FaceNet 來進行 encoding 並計算距離,辨識從 Webcam 讀取的影像是否為資料庫中的人物
– 若距離小於0.7則回傳資料庫內對應的人名與印出字串並發出語音”Welcome (someone), have a nice day!”
– 若不是則繼續偵測人臉並計算當下影像的編碼與距離
參考
- [1] “DeepFace:在面部驗證中縮小與人類績效的差距”
- [2] “FaceNet:用於人臉識別和聚類的統一嵌入”
- [3] 使用網絡攝像頭在 Python 中進行人臉檢測
- [4] OpenFace pretrainde模型
- [5] 官方FaceNet github存儲庫
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
解构产品经理:互联网产品策划入门宝典
电子工业出版社 / 2018-1 / 65
《解构产品经理:互联网产品策划入门宝典》以作者丰富的职业背景及著名互联网公司的工作经验为基础,从基本概念、方法论和工具的解构入手,配合大量正面或负面的案例,完整、详细、生动地讲述了一个互联网产品经理入门所需的基础知识。同时,在此基础上,将这些知识拓展出互联网产品策划的领域,融入日常工作生活中,以求职、沟通等场景为例,引导读者将知识升华为思维方式。 《解构产品经理:互联网产品策划入门宝典》适合......一起来看看 《解构产品经理:互联网产品策划入门宝典》 这本书的介绍吧!
HTML 压缩/解压工具
在线压缩/解压 HTML 代码
随机密码生成器
多种字符组合密码