項目前期準備(2)——基於Pytorch的人臉識別神經網絡系統研究

前言

時間易逝!轉眼間又大三了,最近都在忙於項目、比賽和學習,很少去管理一下自己的博客了,請大家諒解一下。這次呢,我準備把以前學習的人臉識別算法心得寫出一篇記錄來。
在這裏插入圖片描述

正文

首先呢,我想給大家推薦兩種人臉識別神經網絡結構——Siamese network、FaceNet。
對於什麼是Siamese network,這裏點擊查看Siamese network;而對於什麼是FaceNet,則可以點擊這裏。不過,在這裏我希望大家能夠學會多看論文,畢竟是搞算法研究的,學會怎麼樣看論文很重要。
在這裏插入圖片描述
看到這裏,我想有人問,爲什麼不用傳統的神經網絡結構呢,既簡單又方便。答案是:訓練時確實是既簡單又方便,但應用起來又準確又不方便。
假設你的模型訓練時分類是5個人,但突然間你的組長叫你要識別分類六個人,而你的模型又訓練好了。怎麼辦?
在這裏插入圖片描述
還能怎麼辦,重新訓練唄。
你知道嗎,我們搞算法的最難的就是缺乏數據了。假設我這裏有10個人,但每個人只有10張圖片,先不考慮訓練時的數據增強,總的數據只有100個。這時候怎麼辦,搭建一個小的神經網絡模型,又學習不到什麼,搭建一個深點的神經網絡又可能會過擬合。怎麼辦,沒法了,來個PCA降維法,對人臉數據進行降維操作,最後使用歐式距離分類。但是結果肯定不好。因此呢,上面兩種是較爲好的選擇,在這裏我就不多言描述上面這兩種人臉識別算法的思路了。
在這裏插入圖片描述
選擇好了以後,剩下來的就是數據方面了,我想這是很頭痛的事情。不過在這裏的話我覺得還是從簡單的數據開始吧。我相信大家都去網上找了數據集,遺憾的是大都數都需要註冊郵箱才能獲取數據吧。不用的有些數據又太垃圾了,還得自己去人臉檢測,剪裁出適宜的人臉來。這裏呢我推薦幾個黑白圖像數據集給大家先練練手。
數據集一這個數據挺好的,目前我用過的最好的亞洲人臉數據(這個本來我有網盤的鏈接的,不過被我好像刪了,大家想要的話,可以找我解決辦法);
數據集二,這是我在一些官網上下載的數據OCR,大家可以先拿去玩玩。不過我還在網上發現了一個畢竟有趣的數據生成網站數據庫三如果有興趣的話可以去學習一下這種技術GAN。關於GAN的或許你也可以學習一下我的另一篇博客
既然有了數據了,那麼接下來幹嘛尼!答案是:數據預處理啊。有些數據是本身比較髒的,需要我們去“清洗”。首先是對圖像進行濾波去噪——中值濾波、細節濾波等。然後呢,因爲我們的圖像是灰白圖像,可能會存在關照強度不一樣的影響,那麼就需要進行非線性轉換了。爲了能夠讓訓練比較困難、以及數據大小過小的問題,我們需要對數據進行剪裁、翻轉,emm,如果是Pytorch框架的對應的是transform不懂的話點擊這裏,接着就去餵養給神經網絡了。最後效果肯定比一般的神經網絡好得多。
這裏呢,給個搭建Siamese Network例子

class SiameseNetwork(nn.Module):
     def __init__(self):
         super(SiameseNetwork, self).__init__()
         self.cnn1 = nn.Sequential(
             nn.ReflectionPad2d(1),
             nn.Conv2d(1, 4, kernel_size=3),
             nn.ReLU(inplace=True),
             nn.BatchNorm2d(4),
             nn.Dropout2d(p=.2),
             
             nn.ReflectionPad2d(1),
             nn.Conv2d(4, 8, kernel_size=3),
             nn.ReLU(inplace=True),
             nn.BatchNorm2d(8),
             nn.Dropout2d(p=.2),
 
             nn.ReflectionPad2d(1),
             nn.Conv2d(8, 8, kernel_size=3),
             nn.ReLU(inplace=True),
             nn.BatchNorm2d(8),
             nn.Dropout2d(p=.2),
         )

         self.cnn2 = nn.Sequential(
             nn.Conv2d(8, 16, kernel_size=5),
             nn.ReLU(inplace=True),
             nn.BatchNorm2d(16),
             nn.Dropout2d(p=.2),
             
             nn.Conv2d(16, 32, kernel_size=3),
             nn.ReLU(inplace=True),
             nn.BatchNorm2d(32),
             nn.Dropout2d(p=.2),
 
             nn.Conv2d(32, 32, kernel_size=1),
             nn.ReLU(inplace=True),
             nn.BatchNorm2d(32),
             nn.Dropout2d(p=.2),
         ) 

         self.fc1 = nn.Sequential(
             nn.Linear(32*94*94, 1500),
             nn.ReLU(inplace=True),
 
             nn.Linear(1500, 500),
             nn.ReLU(inplace=True),
 
             nn.Linear(500, 128)
         )
 
     def forward_once(self, x):
         output = self.cnn1(x)
         output = self.cnn2(2)
         output = output.view(output.size()[0], -1)
         output = self.fc1(output)
         return output
 
     def forward(self, input1, input2):
         output1 = self.forward_once(input1)
         output2 = self.forward_once(input2)
         return output1, output2

損失函數設計:

class ContrastiveLoss(torch.nn.Module):

     def __init__(self, margin=2.0):
         super(ContrastiveLoss, self).__init__()
         self.margin = margin
 
     def forward(self, output1, output2, label):
         euclidean_distance = F.pairwise_distance(output1, output2)
         loss_contrastive = torch.mean((1-label) * torch.pow(euclidean_distance, 2)  
                                       (label) * torch.pow(torch.clamp(self.margin - euclidean_distance, min=0.0), 2))
 
         return loss_contrastive

其實呢,這個損失函數設計得也不太好,訓練時容易過優,還有就是一定要對數據進行預處理,和將類內數據差異化增大,類間數據差距減小,這樣訓練出來的模型能相比沒有的情況下識別準確度能提升百分之五。
加載數據的話,實在不會的話,可以留言。
下面給出我訓練後的神經網絡模型的結果:
在這裏插入圖片描述
上面這張圖片代表的是相同人臉歐氏距離誤差大小,不同人臉對比爲下圖所示:
在這裏插入圖片描述
理論上圖像數據噪音少,對比度準確率還是挺高的,這裏我把判斷是否爲同一人臉的歐氏距離閾值設定爲0.9,大於它則不是,小於或等於它則是
emm,說了有點簡陋,我想大家很難根據我的思路實現吧,主要是本人最近正準備寫一篇關於人臉複雜條件下的識別算法研究的論文,所以就不詳細地寫了。不過呢,我再推薦一下一個代碼實現的鏈接,算是對大家的幫助了
FaceNet

先說到這裏了,以後我還會講解一下怎麼樣設計人臉識別網絡和改進損失函數。記得留個👍哦
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章