FaceNet源碼解讀2:史上最全的FaceNet源碼使用方法和講解(二)

史上最全的FaceNet源碼使用方法和講解(二)

這是對:史上最全的FaceNet源碼使用方法和講解(一)(附預訓練模型下載)的一個補充。

一、對模型進行測試:

用到的函數:validate_on_lfw.py
在pycharm中配置的參數如下:

數據集所在路徑 模型所在路徑 

示例:

20170512-110547 1.png 2.png

這將執行以下四個操作:
a)加載模型。
b)加載和解析文本文件與圖像對。
c)計算所有圖像(以及它們的水平翻轉版本)在測試集中的向量。
d)計算精度,驗證率(@ FAR = -10e-3),曲線下面積(AUC)和等誤差率(EER)等性能指標。

典型的輸出如下:

Model directory: /home/david/models/20180402-114759/
Metagraph file: model-20180402-114759.meta
Checkpoint file: model-20180402-114759.ckpt-275
Runnning forward pass on LFW images
........................
Accuracy: 0.99650+-0.00252
Validation rate: 0.98367+-0.00948 @ FAR=0.00100
Area Under Curve (AUC): 1.000
Equal Error Rate (EER): 0.004

二、對預訓練模型重新進行訓練

有時候,我們需要用自己的數據集對預訓練好的模型進行重新訓練,或者之前訓練了一個模型之後,覺得訓練輪數不夠,又不想從頭開始訓練,這樣,在訓練之前就要把之前訓練的模型重新加載進去,方式如下:
######第一步:添加預訓練模型的參數:
在中train_tripletloss.py找到這樣一個語句:
這裏寫圖片描述
改成這樣:

 parser.add_argument('--pretrained_model', type=str,
        help='Load a pretrained model before training starts.',default='模型所在路徑')
        
第二步:解決程序中的一個小bug

如果只是完成了第一步,運行程序會報錯。經過調試,是因爲程序有一個小的bug需要修復:
找到這一行程序:
這裏寫圖片描述
可以看出,這一處函數的作用是:如果預訓練模型這個參數非空,那麼用tensorflow的saver.restore()函數重新加載模型參數,但是此處會報錯,

那麼我們模仿compare.py函數中的加載模型方法,將這個函數改爲:

facenet.load_model(args.pretrained_model)

然後運行程序,發現程序已經可以正常執行了。

如果不放心,可以取一個已經訓練好的模型,加載之後訓練一輪,會發現初始的損失函數非常小,同時,訓練一輪之後模型的準確率已經和加載的預訓練模型準確率差不多了,說明模型加載成功。

三、用自己的數據集結合SVM訓練一個人臉識別系統

可能希望自動對您的私人照片集進行分類。或者您有一個安全攝像頭,您想要自動識別您的家庭成員。那麼您可能希望在自己的數據集上訓練分類器。在這種情況下,classifier.py程序也可以用於此。

1)構建自己的數據集。 在該示例中,每個類的5個第一圖像用於訓練,接下來的5個圖像用於測試。
比如說,你有9個需要分類的人(這裏暫時用F1-F9表示),其中你有每個人各20張照片

使用的類是:

F1
F2
F3
F4
F5
F6
F7
F8
F9

訓練集的目錄組織方式:

my_dataset/test
├── F1
│ ├── F1_0.png
│ ├── F1_1.png
│ ├── F1_2.png
│ ├── F1_3.png
│ ├── F1_3.png
…… ……
│ └── F1_19.png
├── F2
│ ├── F2_0.png
│ ├── F2_1.png
│ ├── F2_2.png
│ ├── F2_3.png
│ ├── F2_3.png
│ …… ……
│ └── F2_19.png
├── F3
│ ├── F3_0.png
│ ├── F3_1.png
…… …… ……


測試集的目錄組織方式類似。

2)訓練。 用到的代碼:calssifier.py。這一步是在你已經訓練好了一個FaceNet模型(或者使用網上提供的模型),需要用這個模型計算出的自己照片的特徵向量來訓練一個SVM分類器的場景,這個程序的基本原理是:通過用圖像算出來的向量數據來訓練一個SVM分類器,從而對人的身份進行一個判斷,同時在.pkl格式的文件中存儲每一個分類。這也是作者對於FaceNet程序應用的一個探索。
這個函數有兩個模式,一個模式用來訓練,另一個模式用來測試。具體功能如下:

  • 模式= TRAIN:

    • 使用訓練好的模型計算圖片的向量,用來訓練SVM分類器
    • 將訓練好的分類模型保存爲python pickle文件
  • 模式= CLASSIFY:

    • 加載SVM分類器模型
    • 使用來自數據集測試部分的向量來測試分類器

執行本代碼需要添加的參數以及各參數的含義:

  • mode: 設定“TRAIN”和“CLASSIFY”兩種模式。
  • data_dir: 圖片數據所在文件夾
  • model: 訓練好的模型
  • classifier_filename:類似於標籤,如果mode參數是TRAIN,那麼需要指定一個輸出的文件位置(以.pkl結尾,例如**/**.pkl),如果mode參數是CLASSIFY,那麼就需要指定參數的路徑(.pkl文件)。

配置參數示例:

TRAIN 圖片數據所在文件夾 模型文件夾 標籤文件.pkl 

運行結果:

Number of classes: 9
Number of images: 180
Loading feature extraction model
Model directory: 20180606
Metagraph file: model-20180606-232113.meta
Checkpoint file: model-20180606-232113.ckpt-120120
Calculating features for images
Training classifier
Saved classifier model to file "E:/facenet/pick/classifier.pkl"

測試:

CLASSIFY 圖片數據所在文件夾 模型文件夾 標籤文件保存地址.pkl 

運行結果:

Number of classes: 9
Number of images: 20
Loading feature extraction model
Model directory: 20180606
Metagraph file: model-20180606-232113.meta
Checkpoint file: model-20180606-232113.ckpt-120120
Calculating features for images
Testing classifier
Loaded classifier model from file "E:/facenet/pick/classifier.pkl"
   0  F1: 0.471
   1  F1: 0.672
   2  F1: 0.685
   3  F1: 0.700
   4  F3: 0.633
   5  F1: 0.556
   6  F1: 0.555
   7  F1: 0.696
   8  F2: 0.827
   9  F2: 0.775
      ……  ……

如果不需要在每次執行的過程中都配置這幾個參數,可以對程序進行微調,找到原程序中的這幾行代碼:
這裏寫圖片描述
改動如下(即將初始值配置在程序中,避免每次執行程序時都要輸入對應的參數。如果參數有改動,只需要更改程序對應部位即可。):

parser.add_argument('--mode', type=str, choices=['TRAIN', 'CLASSIFY'],
        help='Indicates if a new classifier should be trained or a classification ' + 
        'model should be used for classification', default='CLASSIFY')#這裏更改模式
parser.add_argument('--data_dir', type=str,
        help='Path to the data directory containing aligned LFW face patches.',default='TF1_classify')#添加自己的數據文件夾
parser.add_argument('--model', type=str,
        help='Could be either a directory containing the meta_file and ckpt_file or a model protobuf (.pb) file',default='20180606')#預訓練模型
parser.add_argument('--classifier_filename',
        help='Classifier model file name as a pickle (.pkl) file. ' + 
        'For training this is the output and for classification this is an input.',default='pick/classifier.pkl')#.pkl文件存儲的位置

附錄:程序中的一些小改進:

一)用GPU訓練模型。

原程序默認使用CPU訓練,但是這樣訓練的速度太慢,如果你電腦恰好有一塊不錯的GPU,或者實驗室裏有GPU服務器,那麼配置好GPU環境之後(包括cuda,TensorFlow-gpu等),可以在程序中添加代碼如下:

import OS
os.environ["CUDA_VISIBLE_DEVICES"] = '0'#如果有多塊顯卡,可以指定第幾塊顯卡,0即爲第一塊顯卡。

這樣,程序在執行過程中就優先調用GPU訓練模型了。

二)微調損失函數

在《In Defense of the Triplet Loss for Person Re-Identification》這篇論文中提到:損失函數中去掉平方後效果還會更好一些,如下圖:
這裏寫圖片描述

如果有需要的話,可以改成開方的形式,在facenet.py下的triplet_loss函數中,找到如下兩句代碼:
這裏寫圖片描述
改成:

pos_dist = tf.sqrt(tf.reduce_sum(tf.square(tf.subtract(anchor, positive)), 1))  # tf.square:平方。tf.subtract::減法
neg_dist = tf.sqrt(tf.reduce_sum(tf.square(tf.subtract(anchor, negative)), 1))

即加上一個開方運算。(目前正在測試效果,以後補充……)

個人知乎主頁地址:知乎個人主頁。歡迎關注。

附:

找到一個非常好的人臉識別領域的彙總博客,把鏈接貼在這裏:格靈深瞳:人臉識別最新進展以及工業級大規模人臉識別實踐探討 | 公開課筆記

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