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

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

ただいまの
回答率

90.00%

Tensorflowを使ったCNNの学習

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 524

tohoho

score 4

 前提・実現したいこと

Tensorflowを使ったCNNの学習
本に載っていたプログラムでMNISTデータでの学習が行えたので、自ら作ったデータセットでCNNをしてみたいです。
データは64x64のグレースケール、出力は2つにクラス分けをするプログラム。

 発生している問題

学習、検証のいずれのデータを使った正解率が更新されません。

INFO:tensorflow:Summary name validation error is illegal; using validation_error instead.
Epoch: 0001 cost = 0.693147182
Validation Error: 0.5
Epoch: 0002 cost = 0.693147182
Validation Error: 0.5
Epoch: 0003 cost = 0.693147182
Validation Error: 0.5
Epoch: 0004 cost = 0.693147182
Validation Error: 0.5
Epoch: 0005 cost = 0.693147182
Validation Error: 0.5
Optimization Finished!
Test Accuracy: 0.5

 該当のソースコード

readData に自分で作成したデータセットのデータを取り出すプログラムが入っています。
trainImage:学習用の画像データ、形は[3200][64][64]で、前半の1900個にラベル[1,0]となるデータ、残り1300個はラベル[0,1]となる画像データ
trainLabel:学習データのラベル、形は[3200][2]、前半の1900個にラベル[1,0]となるデータ、残り1300個はラベル[0,1]となるラベルのデータ
valiImage,testImage:それぞれ検証、テストの画像データ、形は[200][64][64]、前半の100個にラベル[1,0]となるデータ、残り100個はラベル[0,1]となる画像データ
valiLabel,testLabel:検証、テスト画像のラベル、形は[200][2]、前半の100個にラベル[1,0]となるデータ、残り100個はラベル[0,1]となるラベルのデータ

tl:学習データ[3200]個をシャッフルするためのリスト

# -*- coding: utf-8 -*-
import tensorflow as tf
import time

import numpy as np
import cv2
import matplotlib.pyplot as plt
import readData as rd
trainImage,trainLabel,valiImage,valiLabel,testImage,testLabel = rd.readData()
valiImage = np.asarray(valiImage)
valiImage = valiImage.reshape([200, 4096])
testImage = np.asarray(testImage)
testImage = testImage.reshape([200, 4096])

import random
tl= list(range(len(trainImage)))
random.shuffle(tl)


# Parameters
learning_rate = 0.0001
training_epochs = 5
batch_size = 100
display_step = 1

def conv2d(input, weight_shape, bias_shape):
    incoming = weight_shape[0] * weight_shape[1] * weight_shape[2]
    weight_init = tf.random_normal_initializer(stddev=(2.0/incoming)**0.5)
    W = tf.get_variable("W", weight_shape, initializer=weight_init)
    bias_init = tf.constant_initializer(value=0)
    b = tf.get_variable("b", bias_shape, initializer=bias_init)
    return tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(input, W, strides=[1, 1, 1, 1], padding='SAME'), b))

def max_pool(input, k=2):
    return tf.nn.max_pool(input, ksize=[1, k, k, 1], strides=[1, k, k, 1], padding='SAME')

def layer(input, weight_shape, bias_shape):
    weight_init = tf.random_normal_initializer(stddev=(2.0/weight_shape[0])**0.5)
    bias_init = tf.constant_initializer(value=0)
    W = tf.get_variable("W", weight_shape, initializer=weight_init)
    b = tf.get_variable("b", bias_shape, initializer=bias_init)
    return tf.nn.relu(tf.matmul(input, W) + b)

def inference(x, keep_prob):
    x = tf.reshape(x, shape=[-1, 64, 64, 1])
    with tf.variable_scope("conv_1"):
        conv_1 = conv2d(x, [5, 5, 1, 32], [32])
        pool_1 = max_pool(conv_1)
    with tf.variable_scope("conv_2"):
        conv_2 = conv2d(pool_1, [5, 5, 32, 64], [64])
        pool_2 = max_pool(conv_2)
    with tf.variable_scope("fc"):
        pool_2_flat = tf.reshape(pool_2, [-1, 16 * 16 * 64])
        fc_1 = layer(pool_2_flat, [16*16*64, 1024], [1024])
        # apply dropout
        fc_1_drop = tf.nn.dropout(fc_1, keep_prob)
    with tf.variable_scope("output"):
        output = layer(fc_1_drop, [1024, 2], [2])

    return output

def loss(output, y):
    xentropy = tf.nn.softmax_cross_entropy_with_logits(logits=output, labels=y)    
    loss = tf.reduce_mean(xentropy)
    return loss

def training(cost, global_step):
    tf.summary.scalar("cost", cost)
    optimizer = tf.train.AdamOptimizer(learning_rate)
    train_op = optimizer.minimize(cost, global_step=global_step)
    return train_op

def evaluate(output, y):
    correct_prediction = tf.equal(tf.argmax(output, 1), tf.argmax(y, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    tf.summary.scalar("validation error", (1.0 - accuracy))
    return accuracy

if __name__ == '__main__':
    with tf.device("/gpu:0"):
        with tf.Graph().as_default():
            with tf.variable_scope("mnist_conv_model"):
                x = tf.placeholder("float", [None, 4096])
                y = tf.placeholder("float", [None, 2])
                keep_prob = tf.placeholder(tf.float32) # dropout probability

                output = inference(x, keep_prob)
                cost = loss(output, y)
                global_step = tf.Variable(0, name='global_step', trainable=False)
                train_op = training(cost, global_step)
                eval_op = evaluate(output, y)
                summary_op = tf.summary.merge_all()
                saver = tf.train.Saver()
                sess = tf.Session()
                summary_writer = tf.summary.FileWriter("conv_mnist_logs/",graph=sess.graph)
                init_op = tf.global_variables_initializer()
                sess.run(init_op)

                # Training cycle
                for epoch in range(training_epochs):   #エポック(学習画像すべて使う)の回数だけ学習
                    avg_cost = 0.
                    total_batch = int(len(trainImage)/batch_size) #訓練画像/バッチサイズ = 訓練画像使い切る回数

                    random.shuffle(tl)   #シャッフルするためのリストをシャッフルする

                    # Loop over all batches
                    for i in list(range(total_batch)):  #訓練画像を使い切るまでバッチ単位で回す
                        #訓練画像からバッチサイズだけ画像をランダムで取得
                        #入力データと正解ラベルを取得
                        bi = []
                        bl = []
                        for m in list(range(batch_size)):  ##バッチデータとして100取り出す、ラベルも
                            bi.append(trainImage[tl[m+i*batch_size]])
                            bl.append(trainLabel[tl[m+i*batch_size]])

                        minibatch_x = bi
                        minibatch_y = bl
                        minibatch_x = np.asarray(minibatch_x)
                        minibatch_y = np.asarray(minibatch_y)
                        minibatch_x = minibatch_x.reshape([100, 4096])

                        # Fit training using batch data
                        sess.run(train_op, feed_dict={x: minibatch_x, y: minibatch_y, keep_prob: 0.5})
                        # Compute average loss
                        avg_cost += sess.run(cost, feed_dict={x: minibatch_x, y: minibatch_y, keep_prob: 0.5})/total_batch

                    # Display logs per epoch step
                    if epoch % display_step == 0:
                        print("Epoch:", '%04d' % (epoch+1), "cost =", "{:.9f}".format(avg_cost))
                        accuracy = sess.run(eval_op, feed_dict={x: valiImage, y: valiLabel, keep_prob: 1})
                        print("Validation Error:", (1 - accuracy))
                        summary_str = sess.run(summary_op, feed_dict={x: minibatch_x, y: minibatch_y, keep_prob: 0.5})
                        summary_writer.add_summary(summary_str, sess.run(global_step))

                        saver.save(sess, "conv_mnist_logs/model-checkpoint", global_step=global_step)


                print("Optimization Finished!")

                #feed としてテスト用の画像データとその正解ラベルを与える
                accuracy = sess.run(eval_op, feed_dict={x: testImage, y: testLabel, keep_prob: 1})

                print("Test Accuracy:", accuracy)

 試したこと

検証、テストデータでの正解率が0.5なのは、常にクラス分けが[1,0]になされているためのようです。
試しに検証データのvaliImageを前半の100個(ラベルがすべて[1,0]のデータ)にすると、正解率が1.0になりました。

Tensorflow初心者なのでとんちんかんなことをしているかもしれません。ご指摘お願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

0

こうした現象でよくある例が、学習するときに行っていた前処理等をテスト時に行っていないということがあるのですが、その点は大丈夫でしょうか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/11/06 19:38

    前処理とはどのような処理のことでしょうか

    キャンセル

  • 2018/11/06 19:46

    例えば、画像の例だと [0, 1] に正規化する等です。
    readData.py の中身がわからないので憶測でのコメントになりますが、学習データとテストデータは同じ条件のものとなっていますか?

    キャンセル

  • 2018/11/06 22:55 編集

    すべて確認してみましたが
    画像データは、64x64で1チャンネルのデータ
    ラベルは、 2のデータで[0,1]か[1,0]のどちらかになっていました。
    学習とテストで条件は揃えたつもりではあります。

    元はmnistのCNN学習だったのをちょっと変えただけなのが不具合の原因だったりしますでしょうか?
    データサイズもクラス分類の数も勝手に変えてしまったので不安があります。

    キャンセル

  • 2018/11/07 00:05

    変えたのは入力の形状だけですよね?モデルの構築は問題にないように思います。
    なので、学習データでは精度が100%近くでてるのに、テストデータだと出力が全部同じになってしまうというのは、データを作る部分のコードになにか問題があるのではないかと思っているのですが、その部分が質問欄には記載されていないのでわかりません。

    キャンセル

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

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