孿生網絡如何識別面部相似度?這有篇PyTorch教程

2021-01-11 TechWeb

原文來源:hackernoon

作者:Harshvardhan Gupta

「機器人圈」編譯:嗯~阿童木呀

這是兩篇文章的第二篇,為了更系統地了解與掌握該教程,在閱讀本文之前,建議最好通讀機器人圈的前一篇文章。

在前一篇文章中,我們討論了小樣本數據旨在解決的主要問題類別,以及孿生網絡之所以能夠成為解決這個問題優良選擇的原因。首先,我們來重溫一個特殊的損失函數,它能夠在數據對中計算兩個的圖像相似度。我們現在將在PyTorch中實施我們之前所討論的全部內容。

你可以在本文末尾查看完整的代碼連結

架構

我們將使用的是標準卷積神經網絡(CNN)架構,在每個卷積層之後使用批量歸一化,然後dropout。

代碼片段:孿生網絡架構:

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.fc1 = nn.Sequential(

nn.Linear(8*100*100, 500),

nn.ReLU(inplace=True),

nn.Linear(500, 500),

nn.ReLU(inplace=True),

nn.Linear(500, 5)

)

def forward_once(self, x):

output = self.cnn1(x)

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

其實這個網絡並沒有什麼特別之處,它可以接收一個100px * 100px的輸入,並且在卷積層之後具有3個完全連接的層。

在上篇文章中,我展示了一對網絡是如何處理數據對中的每個圖像的。但在這篇文章中,只有一個網絡。因為兩個網絡的權重是相同的,所以我們使用一個模型並連續地給它提供兩個圖像。之後,我們使用兩個圖像來計算損失值,然後再返回傳播。這樣可以節省大量的內存,絕對不會影響其他指標(如精確度)。

對比損失

我們將對比損失定義為

等式1.0

我們將Dw(也就歐氏距離)定義為:

等式1.1

Gw是我們網絡的一個圖像的輸出。

PyTorch中的對比損失看起來是這樣的:

代碼片段:默認邊際價值為2的對比損失:

class ContrastiveLoss(torch.nn.Module):

"""

Contrastive loss function.

Based on: http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf

"""

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

數據集

在上一篇文章中,我想使用MNIST,但有些讀者建議我使用我在同篇文章中所討論的面部相似性樣本。因此,我決定從MNIST / OmniGlot切換到AT&T面部數據集。

數據集包含40名測試對象的不同角度的圖像。我從訓練中挑選出3名測試對象的圖像,以測試我們的模型。

不同類的樣本圖像

一名測試對象的所有樣本圖像

數據加載

我們的架構需要一個輸入對,以及標籤(類似/不相似)。因此,我創建了自己的自定義數據加載器來完成這項工作。它使用圖像文件夾從文件夾中讀取圖像。這意味著你可以將其用於任何你所希望的數據集中。

代碼段:該數據集生成一對圖像和相似性標籤。如果圖像來自同一個類,標籤將為0,否則為1:

class SiameseNetworkDataset(Dataset):

def __init__(self,imageFolderDataset,transform=None,should_invert=True):

self.imageFolderDataset = imageFolderDataset

self.transform = transform

self.should_invert = should_invert

def __getitem__(self,index):

img0_tuple = random.choice(self.imageFolderDataset.imgs)

#we need to make sure approx 50% of images are in the same class

should_get_same_class = random.randint(0,1)

if should_get_same_class:

while True:

#keep looping till the same class image is found

img1_tuple = random.choice(self.imageFolderDataset.imgs)

if img0_tuple[1]==img1_tuple[1]:

break

else:

img1_tuple = random.choice(self.imageFolderDataset.imgs)

img0 = Image.open(img0_tuple[0])

img1 = Image.open(img1_tuple[0])

img0 = img0.convert("L")

img1 = img1.convert("L")

if self.should_invert:

img0 = PIL.ImageOps.invert(img0)

img1 = PIL.ImageOps.invert(img1)

if self.transform is not None:

img0 = self.transform(img0)

img1 = self.transform(img1)

return img0, img1 , torch.from_numpy(np.array([int(img1_tuple[1]!=img0_tuple[1])],dtype=np.float32))

def __len__(self):

return len(self.imageFolderDataset.imgs)

孿生網絡數據集生成一對圖像,以及它們的相似性標籤(如果為真,則為0,否則為1)。 為了防止不平衡,我將保證幾乎一半的圖像是同一個類的,而另一半則不是。

訓練孿生網絡

孿生網絡的訓練過程如下:

1.通過網絡傳遞圖像對的第一張圖像。

2.通過網絡傳遞圖像對的第二張圖像。

3.使用1和2中的輸出來計算損失。

4.返回傳播損失計算梯度

5.使用優化器更新權重。我們將用Adam來進行演示:

代碼片段:訓練孿生網絡:

net = SiameseNetwork().cuda()

criterion = ContrastiveLoss()

optimizer = optim.Adam(net.parameters(),lr = 0.0005 )

counter = []

loss_history = []

iteration_number= 0

for epoch in range(0,Config.train_number_epochs):

for i, data in enumerate(train_dataloader,0):

img0, img1 , label = data

img0, img1 , label = Variable(img0).cuda(), Variable(img1).cuda() , Variable(label).cuda()

output1,output2 = net(img0,img1)

optimizer.zero_grad()

loss_contrastive = criterion(output1,output2,label)

loss_contrastive.backward()

optimizer.step()

if i %10 == 0 :

print("Epoch number {} Current loss {}".format(epoch,loss_contrastive.data[0]))

iteration_number +=10

counter.append(iteration_number)

loss_history.append(loss_contrastive.data[0])

show_plot(counter,loss_history)

網絡使用Adam,以0.0005的學習率進行了100次的迭代訓練。隨著時間的變化,損失曲線如下所示:

隨時間變化的損失值曲線,x軸代表迭代次數

測試網絡

我們從訓練中抽取了3個測試對象,用於評估我們的模型性能。

為了計算相似度,我們只是計算Dw(公式1.1)。其中距離直接對應於圖像對之間的不相似度。Dw的高值表示較高的不相似度。

代碼片段:通過計算模型輸出之間的距離來評估模型:

folder_dataset_test = dset.ImageFolder(root=Config.testing_dir)

siamese_dataset = SiameseNetworkDataset(imageFolderDataset=folder_dataset_test,

transform=transforms.Compose([transforms.Scale((100,100)),

transforms.ToTensor()

])

,should_invert=False)

test_dataloader = DataLoader(siamese_dataset,num_workers=6,batch_size=1,shuffle=True)

dataiter = iter(test_dataloader)

x0,_,_ = next(dataiter)

for i in range(10):

_,x1,label2 = next(dataiter)

concatenated = torch.cat((x0,x1),0)

output1,output2 = net(Variable(x0).cuda(),Variable(x1).cuda())

euclidean_distance = F.pairwise_distance(output1, output2)

imshow(torchvision.utils.make_grid(concatenated),'Dissimilarity: {:.2f}'.format(euclidean_distance.cpu().data.numpy()[0][0]))

模型的一些輸出,較低的值表示相似度較高,較高的值表示相似度較低。

果然,實驗結果相當不錯。網絡能夠做到從圖像中分辨出同一個人,即使這些圖像是從不同角度拍攝的。與此同時,該網絡在辨別不同的圖像方面也做得非常好。

結論

我們討論並實施了用一個孿生網絡從面部圖像對中進行面部識別的實驗。當某個特定面部的訓練樣本很少(或只有一個)時,使用這個辦法是非常有效的。我們使用一個有辨別性的損失函數來訓練神經網絡。

點擊此處獲取該教程的完整代碼

相關焦點

  • 福利,PyTorch中文版官方教程來了
    近日,一款完整的 PyTorch 中文版官方教程出爐,讀者朋友可以更好的學習了解 PyTorch 的相關細節了。教程作者來自 pytorchchina.com。教程網站:http://pytorch123.com教程裡有什麼教程根據 PyTorch 官方版本目錄,完整地還原了所有的內容。包括簡單的環境搭建、快速入門相關 API、高級操作、圖像處理實戰、文本處理實戰、GAN 和強化學習等,基本涵蓋了目前所有深度學習相關的知識點。
  • 微軟面部識別系統Windows Hello與FaceID相似
    FaceID的底層技術就是面部識別,它並不是新技術。微軟面部識別系統Windows Hello與FaceID相似,事實上,Windows Hello已經推出多年,表現一直不錯。 人們對FaceID有很多的擔憂,比如隱私憂慮,還有一些人擔心FaceID不快不可靠。我認為這些擔憂可能被誇大了。 早在2015年微軟就推出了相似的技術,效果很好。
  • Pytorch 中文文檔和中文教程
    筆者獲得了ApacheCN社區的同意,放出該社區的翻譯文檔和官方教程,歡迎大家多去GitHub頁面 fork,star!簡單介紹GitHub項目管理:https://github.com/apachecn/pytorch-doc-zh
  • PyTorch 深度學習官方入門中文教程 pdf 下載|PyTorchChina
    它主要由Facebookd的人工智慧小組開發,不僅能夠 實現強大的GPU加速,同時還支持動態神經網絡,這一點是現在很多主流框架如TensorFlow都不支持的。 PyTorch提供了兩個高級功能: 1.具有強大的GPU加速的張量計算(如Numpy) 2.包含自動求導系統的深度神經網絡 除了Facebook之外,Twitter、GMU和Salesforce等機構都採用了PyTorch。
  • 雲計算學習:用PyTorch實現一個簡單的分類器
    所以我總結了一下自己當初學習的路線,準備繼續深入鞏固自己的 pytorch 基礎;另一方面,也想從頭整理一個教程,從沒有接觸過 pytorch 開始,到完成一些最新論文裡面的工作。以自己的學習筆記整理為主線,大家可以針對參考。第一篇筆記,我們先完成一個簡單的分類器。
  • 《PyTorch中文手冊》來了
    PyTorch 有許多優勢,如採用 Python 語言、動態圖機制、網絡構建靈活以及擁有強大的社群等。由於其靈活、動態的編程環境和用戶友好的界面,PyTorch 是快速實驗的理想選擇。這是一本開源的書籍,目標是幫助那些希望和使用 PyTorch 進行深度學習開發和研究的朋友快速入門,其中包含的 Pytorch 教程全部通過測試保證可以成功運行。
  • 面部識別的神經機制
    人類早就演化出了識別並記憶不同面孔的能力。我們能在擁擠的餐廳或熱鬧的大街上一眼認出朋友的面孔。只需一瞥就知道一個人興奮還是憤怒,高興還是難過。腦成像研究發現,大腦顳葉(位於太陽穴下方)有一些藍莓大小的區域專門負責面部識別。神經科學家稱這些區域為「面部識別塊」(face patches)。
  • 還不會使用PyTorch框架進行深度學習的小夥伴,看過來
    學習本教程之前,你需要很熟悉 Scikit-learn,Pandas,NumPy 和 SciPy。這些程序包是使用本教程的重要先決條件。教程大綱何為深度學習?Pytorch 簡介相較於其它 Python 深度學習庫,Pytorch 有何優勢?
  • 抖音測兩個人相似度怎麼拍 測相似度特效拍攝教程
    抖音測兩個人相似度怎麼拍?最近抖音有個很火的挑戰相似度活動,很多玩家都在測兩個人的相似度,不過這是需要預先設置的,下面就一起來了解下抖音測相似度特效拍攝教程吧。
  • 要禁止使用面部識別?
    正當面部識別在中國如火如荼的進行,並且大行其道,發展勢不可遏,當第一步面部識別手機在中國出現,直到掃臉支付在中國的支付界大行其道,我們可以感受到面部識別給我們帶來的好處。但是,這樣方便的方式卻將要在歐洲面臨可能長達5年的禁止。
  • 大家心心念念的PyTorch Windows官方支持來了
    GitHub 發布地址:https://github.com/pytorch/pytorch/releasesPyTorch 官網:http://pytorch.org/在沒有官方支持前,Windows 上安裝 PyTorch 需要藉助其它開發者發布的第三方 conda 包,而現在我們可以直接在 PyTorch 首頁上獲取使用 conda 或 pip 安裝的命令行,或跟隨教程使用源文件安裝。
  • 新版PyTorch 1.2 已發布:功能更多、兼容更全、操作更快!
    highlight=transformer#torch.nn.Transformer),該模塊基於「Attention is All You Need(https://arxiv.org/abs/1706.03762)」這篇論文。nn.Transformer 模塊完全依賴注意力機制來構建輸入和輸出之間的全局依賴關係;該模塊的各個組件經過精心設計,可以獨立使用。
  • 如何使用Python進行面部識別?
    該算法生成了一個幾何圖形,該幾何圖形將識別與我們所分析的相似點。因此在本例中,它將嘗試尋找人臉圖案,即眼睛、鼻子和嘴巴。這種分析方法最大的問題是產生幻想性視錯覺。圖源:unsplash你看到的是人眼還是幾扇窗戶?在希臘詞源學中,幻想性視錯覺是一種人類的特徵。
  • 盤點人臉識別中的黑科技——人工神經網絡
    他們發現大腦中編碼人臉的方式和成功地執行人工智慧系統(稱為深度神經網絡)的驚人相似性。當我們看一張面孔時,視覺皮層中的神經元群被激活並發射它們的信號。事實上,某些神經元對面部有選擇性的反應,而不是對其他物體的反應。但是單個神經元的激活是如何共同產生面部感知和識別的呢?
  • 手把手教你用PyTorch實現圖像分類器(第一部分)
    當我接近完成的時候,我決定與大家分享一些在未來對他人有益的建議和見解。通過3篇短文,介紹如何實現圖像分類器的概念基礎——這是一種能夠理解圖像內容的算法。本文的目標不是提供手把手的指導,而是幫助理解整個過程。如果你正在考慮學習機器學習或人工智慧,你將不得不做類似的項目,並理解本系列文章中介紹的概念。
  • 語音識別開源工具PyTorch-Kaldi:兼顧Kaldi效率與PyTorch靈活性
    語音識別的最終結果就是在聲學模型得分和語言模型得分上進行搜索得到的。具體的內容這裡不做展開。在語音識別技術的發展史上,深度學習絕對是極具影響力的。可以說,沒有對深度學習的引入,就不會有今天如此先進的語音識別引擎。
  • PyTorch可視化理解卷積神經網絡
    如今,機器已經能夠在理解、識別圖像中的特徵和對象等領域實現99%級別的準確率。生活中,我們每天都會運用到這一點,比如,智慧型手機拍照的時候能夠識別臉部、在類似於谷歌搜圖中搜索特定照片、從條形碼掃描文本或掃描書籍等。造就機器能夠獲得在這些視覺方面取得優異性能可能是源於一種特定類型的神經網絡——卷積神經網絡(CNN)。
  • 如何用PyTorch訓練圖像分類器
    -99465a1e9bf5如果你剛剛開始使用PyTorch並想學習如何進行基本的圖像分類,那麼你可以參考本教程。它將介紹如何組織訓練數據,使用預訓練神經網絡訓練模型,然後預測其他圖像。為此,我將使用由Google地圖中的地圖圖塊組成的數據集,並根據它們包含的地形特徵對它們進行分類。我會在另一篇文章中介紹如何使用它(簡而言之:為了識別無人機起飛或降落的安全區域)。但是現在,我只想使用一些訓練數據來對這些地圖圖塊進行分類。下面的代碼片段來自Jupyter Notebook。
  • PyTorch官方教程書限時免費!500頁內容帶你上手最流行框架
    機器之心報導參與:魔王去年 11 月,PyTorch 官方發布權威 PyTorch 教程書籍《Deep Learning with PyTorch》,但遺憾的是當時這本書只有前五章內容免費這本書為使用 PyTorch 構建和訓練神經網絡提供了詳細且易於上手的教程,使用的程式語言為 Python。
  • 應用層下的人臉識別(三):人臉比對
    人臉1:N人臉1:N又稱靜態大庫檢索:即以人臉圖片、人臉相似度作為檢索條件,在人臉庫中搜索與其相似(相似度大於設定閾值)的圖片——類似於百度以圖搜圖。檢索過程實際就是:進行N次人臉比對,並留下比分大於閾值的結果。