LoginSignup
92
93

More than 5 years have passed since last update.

TensorFlowを使って顔認識器を作る

Posted at

はじめに

s_スクリーンショット 2016-07-27 12.37.01.png

こんにちは、Hironsanです。

顔認識は画像中に映った人を検知し、人物の識別を行う技術です。顔認識の用途としては、監視カメラのシステムに組み込んでセキュリティ向上に役立てたり、ロボットに組み込んで家族の顔を認識させたりすることがあげられます。

今回はTensorFlowを使って畳み込みニューラルネットワークを構築し、既存のデータセットを使って顔認識器を作ってみます。

対象読者

  • 畳み込みニューラルネットワーク(CNN)を知っている
  • TensorFlowでどう書くかはわからない

CNNの理論については以下を見ればわかると思います。

準備

TensorFlowのインストール

TensorFlowのインストールは公式サイトが丁寧に解説しているのでそちらを参照してください。

データのダウンロード

まずはデータセットを用意します。今回は以下の顔画像データセットを使います。

このデータセットには40人分の画像が各10枚ずつ含まれています。各画像サイズは64x64でグレースケール画像です。
スクリーンショット 2016-07-25 22.30.04.png

画像の読み込み

データセットを用意したら、画像を読み込みます。
PyFaceRecognizer/example/input_data.py

import input_data
dataset = input_data.read_data_sets('data/olivettifaces.mat')

ここで、datasetは学習データ、検証データ、テストデータを含んでいます。また、読み込んだ段階で画像サイズを32x32に縮小しています。

畳み込みニューラルネットワークの構築

畳み込みニューラルネットワーク(CNN)を用いて顔認識を行います。全体像としては以下のようになっています。

スクリーンショット 2016-07-27 13.19.06.png

各層のconv, pool, fcはそれぞれ畳み込み層、プーリング層、全結合層を表しています。関数欄のReLは正規化線形関数を表しています。パラメータを表にすると以下のようになります。

層種・名称 パッチ ストライド 出力マップサイズ 関数
data - - 32 x 32 x 1 -
conv1 5 x 5 1 32 x 32 x 32 ReL
pool1 2 x 2 2 16 x 16 x 32 -
conv2 5 x 5 1 16 x 16 x 64 ReL
pool2 2 x 2 2 8 x 8 x 64 -
fc3 - - 1 x 1 x 1024 ReL
fc4 - - 1 x 1 x 40 softmax

コードで書いてあげると以下のようになります。ほぼそのままですね。
PyFaceRecognizer/example/run.py

def inference(input_placeholder, keep_prob):
    W_conv1 = weight_variable([5, 5, 1, 32])  # 最初の2つはパッチサイズ。残りは入力チャネルと出力チャネルの数
    b_conv1 = bias_variable([32])

    x_image = tf.reshape(input_placeholder, [-1, 32, 32, 1])  # 第2、第3の次元は画像の幅と高さ、最後の次元はカラー・チャネルの数

    h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)  # たたみ込み
    h_pool1 = max_pool_2x2(h_conv1)  # maxプーリング

    W_conv2 = weight_variable([5, 5, 32, 64])
    b_conv2 = bias_variable([64])

    h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
    h_pool2 = max_pool_2x2(h_conv2)

    W_fc1 = weight_variable([8 * 8 * 64, 1024])
    b_fc1 = bias_variable([1024])

    h_pool2_flat = tf.reshape(h_pool2, [-1, 8 * 8 * 64])
    h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

    h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

    W_fc2 = weight_variable([1024, 40])
    b_fc2 = bias_variable([40])

    y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)  # 出力そう

    return y_conv

モデルの訓練と評価

inferenceにモデルのコードを書きました。次はモデルを訓練するためのコードを書いていきます。それがlossとtrainingです。lossではクロスエントロピーを計算し、trainingではAdamオプティマイザを使用してパラメータの更新を行っていきます。コードにすると以下の通りです。

def loss(output, supervisor_labels_placeholder):
    cross_entropy = tf.reduce_mean(-tf.reduce_sum(supervisor_labels_placeholder * tf.log(output), reduction_indices=[1]))
    return cross_entropy


def training(loss):
    train_step = tf.train.AdamOptimizer(1e-4).minimize(loss)
    return train_step

以上で定義した、inference, loss, trainingを用いて顔認識を行います。訓練プロセスの100反復ごとにログを出力します。テストするときはドロップアウトさせないように、keep_peobを1.0にしています。

with tf.Session() as sess:
    output = inference(x, keep_prob)
    loss = loss(output, y_)
    training_op = training(loss)

    init = tf.initialize_all_variables()
    sess.run(init)

    for step in range(1000):
        batch = dataset.train.next_batch(40)
        sess.run(training_op, feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
        if step % 100 == 0:
            print(sess.run(loss, feed_dict={x: batch[0], y_: batch[1], keep_prob: 1.0}))

    correct_prediction = tf.equal(tf.argmax(output, 1), tf.argmax(y_, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    print('test accuracy %g' % accuracy.eval(feed_dict={x: dataset.test.images, y_: dataset.test.labels, keep_prob: 1.0}))

実行

実行結果は下のような感じです。クロスエントロピーが下がっている様子が確認できます。

9.8893
1.68918
0.602403
0.261183
0.0490791
0.0525591
0.0133087
0.0121071
0.00673524
0.00580989

ソースコード

以下のリポジトリからソースコードをダウンロードして動かすことができます。

おわりに

畳み込みニューラルネットワークを用いて既存の顔データセットに対して顔認識を行ってみました。
次はカメラからリアルタイムに取得した画像を使って、顔検知・顔認識をやってみたいと思います。

参考資料

92
93
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
92
93