ニートがプログラミングするブログ(はてな出張所)

ニートがプログラミングするブログです。今は主にコンピュータビジョンに関することをやっています。

ディープラーニングを使わない顔認識2

今回は前に書いた方法を改良したので、その方法を書いておこうと思います。
その前に以前のはてブのコメントで処理負荷を知りたいという意見があったので書いておきます。
使用したデータはsugyanさんのアイドルデータセットです。
(何度も使ってすみません。。。)
このデータセットは40人のアイドルの画像がそれぞれ180枚あります。
ここでは150枚をトレーニングに使う画像、30枚をテスト用の画像としました。
またトレーニングでは反転画像も使用したので枚数は上記の2倍です。
このデータセットでは既に、顔検出と位置あわせが済んでいるのでその部分はスキップしました。
pythonで作った簡易版ですが、特徴量を取り出すのに約10分、40クラス分のlogistic regressionのトレーニングに約20分、テストに約120秒です。
テスト画像は30x40=1200枚なので、40クラス問題ならば1枚あたりの処理時間は約0.1秒ということになります。
精度に関しては、簡易版とは言っていますが、OpenCV付属の顔認識機能よりは良いです。
OpenCVではEigenface、Fisherface、LBPHの3種類があります。
これに上記のデータセットを流し込んだだけですが、精度はそれぞれ40%、61%、41%でした。
一方で私の方法は94%なのでsugyanさんの96%には劣りますが、それなりの精度は出ていると思います。
(ちなみにC++で作ったオリジナル版では97%が出ています。)

で、本題ですが実はそれほど改良したわけではありません。
改良した部分は標準化の部分とlogistic regressionの重みの部分です。
標準化では各次元の値を平均0分散1となるようにします。
そのときに、たまたま大きな(あるいは小さな)値を取ったために結果に影響してしまう、という状況を避けたいというのが動機です。
そこで標準化の結果1以上(あるいは-1以下)になったら、強制的に1(あるいは-1)にセットしなおします。

logistic regression、というかニューラルネットワークでは重み上限という方法があります。
この方法は重みの二乗和をある値以下に制限するというものです。
以前はこの方法を使っていましたが、上記の方法と同様に、各重みの値が0.1以上(あるいは-0.1以下)になったら、強制的に0.1(あるいは-0.1)にセットしなおすことにしました。
とりあえず、こんな方法で精度が1%程度上がりました。

 


それからせっかくなのでpythonで作った簡易版のソースコードを公開しました。
使い方を以下に書いておきます。
1.パッケージのインストール
以下のパッケージを使うのでpipコマンドでインストールします。
dlib
skimage
PIL
numpy
scipy

2.スクリプトとデータのダウンロード
githubのページからスクリプトをダウンロードします。
dlibの顔の特徴点検出機能を使うので、http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2をダウンロードして解凍して、スクリプトと同じとこに置きます。

3.データの用意
スクリプトと同じ場所に"data"フォルダを作ります。
"data"フォルダの下に、"test"フォルダと"train"フォルダを作ります。
それぞれのフォルダの下に、各人のフォルダを作ってデータを格納します。
具体的には以下のような構造になります。

.
├── align.py
├── data
│   ├── test
│   │   ├── person1
│   │   │   ├── p1_01.jpg
│   │   │   └── p1_02.jpg
│   │   ├── person2
│   │   │   ├── p2_01.jpg
│   │   │   └── p2_02.jpg
│   │   ├── person3
│   │   │   ├── p3_01.jpg
│   │   │   └── p3_02.jpg
│   │   └── person4
│   │       ├── p4_01.jpg
│   │       └── p4_02.jpg
│   └── train
│       ├── person1
│       │   ├── p1_01.jpg
│       │   └── p1_02.jpg
│       ├── person2
│       │   ├── p2_01.jpg
│       │   └── p2_02.jpg
│       ├── person3
│       │   ├── p3_01.jpg
│       │   └── p3_02.jpg
│       └── person4
│           ├── p4_01.jpg
│           └── p4_02.jpg
├── hog.py
├── lr.py
├── shape_predictor_68_face_landmarks.dat
└── train_and_test.py

 

4.実行
あとは"python train_and_test.py"コマンドを実行すればそのうち終わります。
また、デフォルトでは顔の検出をしますが、必要ない場合はtrain_and_test.py内で"FACE_DETECTION_FLAG = False"としてください。
同様に、デフォルトは顔の位置あわせをしますが、必要ない場合はtrain_and_test.py内で"ALIGN_FLAG = False"としてください。

最後に宣伝ですが、AV女優の画像検サービスをやっているのでよろしくお願いします。