質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.48%

バッチの正規化を使用したモデルに1枚のデータで識別を行いたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,303

score 7

 前提・実現したいこと

pythonとtensorflowによりResNetを用いて、男女の顔の識別を行う機械学習モデルを作っています。実際に学習済みのモデルに1枚の顔写真を入力すると、上手く判別することができませんでした。原因は活性化関数に入れる前に行われているバッチの正規化(Batch Normalization)であるのではないかと考えています。バッチの正規化を使用したモデルに1枚のデータで識別を行う事ができるようにしたいです。

 発生している問題・エラーメッセージ

バッチの正規化を含んで学習を行ったモデルに対してバッチではなく、
1つのデータをインプットとしていれるにはどのような工夫を行えばいいのでしょうか。

 該当のソースコード

# ============================import============================
import tensorflow as tf
import os
# GPUの無効化
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
import sys
os.chdir("path")
sys.path.append('path')
import data_set

# ============================init============================
IMAGE_SIZE = 56
LAYER_NUM = 3
LABEL_NUM = 6
CHANNEL = 3
IMAGE_PIXELS = IMAGE_SIZE*IMAGE_SIZE*CHANNEL
LEARNING_RATE = 1e-3
MOMENTUM_RATE =  0.9
LOOP_NUM = 1000
VALIDATION_SIZE = 300
TEST_SIZE = 120
alpha = 1e-3
batch_size = 1
CKPT_PATH = "path"

x = tf.placeholder(tf.float32, [None, IMAGE_PIXELS])
y_ = tf.placeholder(tf.float32, [None, LABEL_NUM])
x_image = tf.reshape(x, [-1, IMAGE_SIZE, IMAGE_SIZE, CHANNEL])
keep_prob = tf.placeholder("float")

# leaky-Relu
def leaky_relu(x, alpha):
    plus = tf.nn.relu(x)
    minus = tf.nn.relu(-x)
    plus = tf.cast(plus, tf.float32)
    minus = tf.cast(minus, tf.float32)
    y = plus - minus*alpha
    return y

# w:init
def weight_variable(shape, name=None):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial, name=name)

def fc_layer(inpt, shape):
    fc_w = weight_variable(shape)
    fc_b = tf.Variable(tf.zeros([shape[1]]))
    fc_h = tf.matmul(inpt, fc_w) + fc_b

    return fc_h

# conv(relu):init
def conv_layer(inpt, filter_shape, stride):
    out_channels = filter_shape[3]
    filter_ = weight_variable(filter_shape)
    conv = tf.nn.conv2d(inpt, filter=filter_, strides=[1, stride, stride, 1], padding="SAME")
    beta = tf.Variable(tf.zeros([out_channels]), name="beta")
    gamma = weight_variable([out_channels], name="gamma")
    mean, var = tf.nn.moments(conv, axes=[0,1,2])

    batch_norm = tf.nn.batch_norm_with_global_normalization(conv, mean, var, beta, gamma, 0.001,
                                                            scale_after_normalization=True)
    out = leaky_relu(batch_norm, 1e-3)

    return out

def residual_block(inpt, output_depth, down_sample, projection=False):
    input_depth = inpt.get_shape().as_list()[3]
    if down_sample:
        filter_ = [1,2,2,1]
        inpt = tf.nn.max_pool(inpt, ksize=filter_, strides=filter_, padding='SAME')

    conv1 = conv_layer(inpt, [3, 3, input_depth, output_depth], 1)
    conv2 = conv_layer(conv1, [3, 3, output_depth, output_depth], 1)

    if input_depth != output_depth:
        if projection:
            # Option B: Projection shortcut
            input_layer = conv_layer(inpt, [1, 1, input_depth, output_depth], 2)
        else:
            # Option A: Zero-padding
            input_layer = tf.pad(inpt, [[0,0], [0,0], [0,0], [0, output_depth - input_depth]])
    else:
        input_layer = inpt

    res = conv2 + input_layer
    return res

n_dict = {20:1, 32:2, 44:3, 56:4}

# ============resnet====================
n = 32
inpt = x_image

if n < 20 or (n - 20) % 12 != 0:
    print("ResNet depth invalid.")
    sys.exit()

num_conv = (n - 20) // 12 + 1
layers = []

with tf.variable_scope('conv1'):
    conv1 = conv_layer(inpt, [3, 3, 3, 16], 1)
    layers.append(conv1)

for i in range (num_conv):
    with tf.variable_scope('conv2_%d' % (i+1)):
        conv2_x = residual_block(layers[-1], 16, False)
        conv2 = residual_block(conv2_x, 16, False)
        layers.append(conv2_x)
        layers.append(conv2)


for i in range (num_conv):
    down_sample = True if i == 0 else False
    with tf.variable_scope('conv3_%d' % (i+1)):
        conv3_x = residual_block(layers[-1], 32, down_sample)
        conv3 = residual_block(conv3_x, 32, False)
        layers.append(conv3_x)
        layers.append(conv3)


for i in range (num_conv):
    down_sample = True if i == 0 else False
    with tf.variable_scope('conv4_%d' % (i+1)):
        conv4_x = residual_block(layers[-1], 64, down_sample)
        conv4 = residual_block(conv4_x, 64, False)
        layers.append(conv4_x)
        layers.append(conv4)

with tf.variable_scope('fc'):
    global_pool = tf.reduce_mean(layers[-1], [1, 2])
    assert global_pool.get_shape().as_list()[1:] == [64]

    out = fc_layer(global_pool, [64, LABEL_NUM])
    layers.append(out)

    y_fc = layers[-1]
    y_conv = tf.nn.softmax(y_fc)

 試したこと

1枚のみの入力の際は全学習データの平均値と分散値をそれぞれmean,varとして使用しようとしたのですが、畳み込み層の1層目~4層目まであるため、それぞれに固定値を設定するのは非合理的だと考え、やめました。
現在は学習とテストを分けずに行っていますが、この課題の糸口がみえたら分けようと思っております。

 補足情報(FW/ツールのバージョンなど)

このサイトのコードを参考に作成しました。
http://www.iandprogram.net/entry/2016/06/06/180806

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

https://stackoverflow.com/questions/44807038/single-prediction-when-using-batch-normalization
からの
https://r2rt.com/implementing-batch-normalization-in-tensorflow.html

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/23 00:51

    適切な回答ありがとうございます。
    以下のように改善したところ、is_training = Falseとするとうまくいかないのですが間違っているからでしょうか?

    # conv(relu):init
    def conv_layer(inpt, filter_shape, stride):
    # out_channels = filter_shape[3]
    filter_ = weight_variable(filter_shape)
    conv = tf.nn.conv2d(inpt, filter=filter_, strides=[1, stride, stride, 1], padding="SAME")
    batch_norm = batch_norm_wrapper(conv, filter_shape, is_training=True)
    # beta = tf.Variable(tf.zeros([out_channels]), name="beta")
    # gamma = weight_variable([out_channels], name="gamma")
    # mean, var = tf.nn.moments(conv, axes=[0,1,2])
    # batch_norm = tf.nn.batch_norm_with_global_normalization(conv, mean, var, beta, gamma, 0.001,
    # scale_after_normalization=True)
    out = leaky_relu(batch_norm, 1e-3)

    return out


    def residual_block(inpt, output_depth, down_sample, projection=False):
    input_depth = inpt.get_shape().as_list()[3]
    if down_sample:
    filter_ = [1,2,2,1]
    inpt = tf.nn.max_pool(inpt, ksize=filter_, strides=filter_, padding='SAME')

    conv1 = conv_layer(inpt, [3, 3, input_depth, output_depth], 1)
    conv2 = conv_layer(conv1, [3, 3, output_depth, output_depth], 1)

    if input_depth != output_depth:
    if projection:
    # Option B: Projection shortcut
    input_layer = conv_layer(inpt, [1, 1, input_depth, output_depth], 2)
    else:
    # Option A: Zero-padding
    input_layer = tf.pad(inpt, [[0,0], [0,0], [0,0], [0, output_depth - input_depth]])
    else:
    input_layer = inpt

    res = conv2 + input_layer
    return res

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る