個人識別のために顔認識を行う場合、FineTuningを行う方法と、FeatureExtractorを使う方法があります。

前者は、予め決まっている人物を識別したい場合に使用し、VGG16等をベースにFineTuningを行っておき、学習後の学習済みモデルを使用して人物を特定します。後者は再学習は不要な方法であり、事前に膨大な顔画像で学習させておいた学習済みモデルを使用して、その中間層のデータを取得することで、顔の特徴を示す特徴ベクトルを取得し、認識したい人物のベクトルと、カメラから取得した人物のベクトルとの距離を計算することで個人を識別します。

CNNをFeatureExtractorとして使う場合の学習済みモデルとしては、VGG Faceがあります。これは、2015年に公開されており、ネットワーク構造はVGG16です。しかし、VGG Faceは商用利用不可となっています。

そこでTensorFlowで動く商用利用可のモデルとして2017年に公開されたのが、FaceNetです。ネットワーク構造はInception ResNetとなっています。

2018年にはVGG Face2が公開されました。VGG Faceから精度が向上し、商用利用可のライセンスとなっています。ネットワーク構造はResNetとSENetの2バージョンがあります。

VGG Face2のデータセットはクリーニングされており精度が高いため、FaceNetの方でもVGG Face2のデータセットで再学習が行われ、精度が改善しています。

KerasでVGG FaceおよびVGG Face2を使うには、keras-vggfaceを使用することができます。VGG16、ResNet、SENetに対応しています。

test.pyをコメントアウトして実行すると、以下のようにデータセットの中から最も近い人を表示します。

('\n', 'RESNET50')
('\n', array([[1.2077236e-07, 6.9855632e-06, 9.1819614e-01, ..., 1.4105116e-07,
        9.3622623e-07, 9.7075758e-07]], dtype=float32))
('\n', 'Predicted:', [[[' A._J._Buckley', 0.91819614], [' Billy_Butler', 0.007661988], [' Chris_Hardwick', 0.007469104], [' A._J._Pierzynski', 0.0045922087], [' Michael_Voltaggio', 0.0044681374]]])
.('\n', 'VGG16')
('\n', array([[9.7901160e-01, 4.9870639e-08, 7.0865167e-07, ..., 5.4379225e-08,
        7.6642658e-07, 3.7070203e-07]], dtype=float32))
('\n', 'Predicted:', [[['A.J._Buckley', 0.9790116], ['David_Denman', 0.0014457349], ['Carmine_Giovinazzo', 0.0008676527], ['Robert_Buckley', 0.0007245681], ['Eddie_Cahill', 0.00041833066]]])

特徴ベクトルを取得するには、include_top=FalseにしてFC層を除外した上で推論します。VGG Face(VGG16)の場合は4096次元、VGG Face2(ResNet)の場合は2048次元になります。

model = VGGFace(include_top=False, input_shape=(224, 224, 3), pooling='avg',model='vgg16')
print model.predict(x)[0]