LoginSignup
1
1

More than 3 years have passed since last update.

学習モデルの作成、学習と推論

Posted at

はじめに

  • 数年前に TensorFlowMNIST CNN のチュートリアルをやり、放置していました。よくある話です。
  • 今回は、チュートリアルを改造して、顔画像の学習モデルを作成しました。
  • クラスも 10 画像サイズも 28x28 の同一です。精度は、80% 前後となりました。まぁ、遊びなので、満足しました。
  • ソース一式は ここ です。

モデル

  • モデル自体は、下記を参考にしました。
  • 参考: TensorFlow mnist_deep.py
  • num_classes img_rows img_cols は、設定ファイルの値を利用する様にしています。クラス数、画像サイズの変更に対応しました。
def model():
    """MNIST 参考モデル."""

    num_classes = len(CLASSES)
    img_rows, img_cols = IMG_ROWS, IMG_COLS

    x = tf.compat.v1.placeholder(tf.float32, [None, img_rows*img_cols])

    with tf.name_scope('reshape'):
        x_image = tf.reshape(x, [-1, img_rows, img_cols, 1])

    with tf.name_scope('conv1'):
        W_conv1 = weight_variable([5, 5, 1, 32])
        b_conv1 = bias_variable([32])
        h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)

    with tf.name_scope('pool1'):
        h_pool1 = max_pool_2x2(h_conv1)

    with tf.name_scope('conv2'):
        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)

    with tf.name_scope('pool2'):
        h_pool2 = max_pool_2x2(h_conv2)

    with tf.name_scope('fc1'):
        W_fc1 = weight_variable([int(h_pool2.shape[1]) * int(h_pool2.shape[2]) * 64, 1024])
        b_fc1 = bias_variable([1024])

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

    with tf.name_scope('dropout'):
        keep_prob = tf.compat.v1.placeholder(tf.float32)
        h_fc1_drop = tf.nn.dropout(h_fc1, rate=1-keep_prob)

    with tf.name_scope('fc2'):
        W_fc2 = weight_variable([1024, num_classes])
        b_fc2 = bias_variable([num_classes])

        y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2

    return x, y_conv, keep_pro
  • 下記も同様に、チュートリアルを利用しています。
def conv2d(x, W):
    """conv2d returns a 2d convolution layer with full stride."""
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')


def max_pool_2x2(x):
    """max_pool_2x2 downsamples a feature map by 2X."""
    return tf.nn.max_pool2d(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')


def weight_variable(shape):
    """weight_variable generates a weight variable of a given shape."""
    initial = tf.random.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)


def bias_variable(shape):
    """bias_variable generates a bias variable of a given shape."""
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

学習

学習モデル

  • 以前作成したデータセットを読み込める様にしています。
  • また、バッチサイズ、エポックも変更出来る様にしました。
def train(datasets, batch_size=128, epochs=12):
    """学習."""

    x, y_conv, keep_prob = model()

    y_ = tf.compat.v1.placeholder(tf.float32, [None, 10])

    with tf.name_scope('loss'):
        cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(labels=y_, logits=y_conv)
    cross_entropy = tf.reduce_mean(cross_entropy)

    with tf.name_scope('adam_optimizer'):
        train_step = tf.compat.v1.train.AdamOptimizer(1e-4).minimize(cross_entropy)

    with tf.name_scope('accuracy'):
        correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
        correct_prediction = tf.cast(correct_prediction, tf.float32)
    accuracy = tf.reduce_mean(correct_prediction)
  • ほぼ、チュートリアルと一緒ですが、モデルの保存を追加しました。
  • 保存場所は、設定ファイルから指定しています。
    saver = tf.compat.v1.train.Saver()
    os.makedirs(os.path.dirname(os.path.abspath(MODEL_FILE)), exist_ok=True)
  • チュートリアルから改造を実施し、エポック単位で、精度の表示やモデルの保存を行う様にしました。
    with tf.compat.v1.Session() as sess:
        sess.run(tf.compat.v1.global_variables_initializer())

        next_epoch = 1
        print('epoch, train accuracy, test accuracy')
        while datasets.train.epochs_completed < epochs:
            train_images, train_labels = datasets.train.next_batch(batch_size)
            sess.run(train_step, feed_dict={x: train_images, y_: train_labels, keep_prob: 0.5})

            if datasets.train.epochs_completed == next_epoch:

                train_accuracy = accuracy.eval(feed_dict={x: datasets.train.images, y_: datasets.train.labels, keep_prob: 1.0})
                test_accuracy = accuracy.eval(feed_dict={x: datasets.test.images, y_: datasets.test.labels, keep_prob: 1.0})
                print('{:d}, {:.4f}, {:.4f}'.format(datasets.train.epochs_completed, train_accuracy, test_accuracy))

                saver.save(sess, MODEL_FILE)

                next_epoch = datasets.train.epochs_completed + 1

学習の実行

  • --train オプションを指定する事で、学習を実行します。
  • バッチサイズは、128 エポックは、120 にしました。
$ python face_deep.py --train
epoch, train accuracy, test accuracy
1, 0.4580, 0.4090
2, 0.5593, 0.4880
省略
119, 1.0000, 0.8110
120, 1.0000, 0.792

image.png

推論

推論

  • 画像は、numpy になっている必要があります。
  • dtype で結果の型を変更できます。
def predict(images, dtype=None):
    """推論 結果は numpy, int, argmax を dtype で切り替え."""

    tf.compat.v1.reset_default_graph()

    x, y_conv, keep_prob = model()

    with tf.compat.v1.Session() as sess:
        sess.run(tf.compat.v1.global_variables_initializer())

        saver = tf.compat.v1.train.Saver()
        saver.restore(sess, MODEL_FILE)

        results = sess.run(tf.nn.softmax(y_conv), feed_dict={x: images, keep_prob: 1.0})
        results = np.array(results * 100, dtype=np.uint8)
        if dtype == 'int':
            results = [[int(y) for y in result] for result in results]
        if dtype == 'argmax':
            results = [np.argmax(y) for y in results]

    return results

推論の実行

  • 推論は、オプションなしで実行します。
  • あくまで、動作確認レベルとしています。別途、Webアプリケーションから利用する事を考えています。
  • 下記は、データセットのテスト画像の最初の10配列の推論結果です。最初の数百は、0 のラベルなので、大体あっている様です。
$ python face_deep.py
省略
[[100   0   0   0   0   0   0   0   0   0]
 [ 99   0   0   0   0   0   0   0   0   0]
 [ 99   0   0   0   0   0   0   0   0   0]
 [  0  99   0   0   0   0   0   0   0   0]
 [ 99   0   0   0   0   0   0   0   0   0]
 [ 97   0   0   0   0   0   0   0   0   1]
 [ 99   0   0   0   0   0   0   0   0   0]
 [  0  99   0   0   0   0   0   0   0   0]
 [ 99   0   0   0   0   0   0   0   0   0]
 [ 36  63   0   0   0   0   0   0   0   0]]

おわりに

  • TensorFlowMNIST CNN のチュートリアルを改造して、顔画像の学習と推論を実施しました。
  • あくまで、勉強レベルなので、学習と推論の動作が出来た事でも十分でした。
  • 次回は、Flask の Webアプリケーションから推論を実行してみます。
1
1
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
1
1