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

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

ただいまの
回答率

90.13%

CNNの学習が出来ない時の対応

受付中

回答 1

投稿 編集

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

AK777

score 7

CNNの学習が実施されない

CNNで画像処理を行いたいのですが、学習結果が下記のようになって実施されません。コードのどの部分が原因で学習が出来ないのでしょうか?

 発生している問題

----------------------------------
epoch: 1 , step: 1
Batch loss: 1.37
Batch accuracy: 18.8%
Validation loss: 1.08
Validation acuuracy: 47.4%
----------------------------------
epoch: 1 , step: 11
Batch loss: 1.38
Batch accuracy: 15.6%
Validation loss: 1.22
Validation acuuracy: 33.6%
----------------------------------
epoch: 1 , step: 21
Batch loss: 1.55
Batch accuracy: 0.0%
Validation loss: 1.22
Validation acuuracy: 33.6%
----------------------------------

(以下同様の学習効率)

 該当のソースコード

import os
import glob
import sys
import cv2
import tensorflow as tf
import numpy as np
import pandas as pd
from numpy.random import permutation
import time

image_size = 28
image_channnel = 1
imgpx = image_size * image_size * image_channnel
category = 6
np.random.seed(1)

flags = tf.app.flags
FLAGS = flags.FLAGS
flags.DEFINE_string('log_path', '/tmp/cnn/', 'Directory to put the training data')
flags.DEFINE_string('save_name', os.getcwd() + '/var.ckpt', 'path to save variables')
flags.DEFINE_integer('max_steps', 200, 'Number of steps to run trainer')
flags.DEFINE_integer('batch_size', 32, '')
flags.DEFINE_integer('training_epoch', 100, '')
flags.DEFINE_integer('validation_interval', 10, 'validation interval')
flags.DEFINE_float('learning_rate', 1e-4, 'Initial learning rate')
flags.DEFINE_float('dropout_keep_prob', 0.5, '')

def next_batch(data, label, batch_size):
    perm = np.arange(data.shape[0])
    np.random.shuffle(perm)
    return data[perm][:batch_size], label[perm][:batch_size]

def input_placeholder(size, channel, label):
    with tf.name_scope('input') as scope:
        inputs = tf.placeholder("float", [None, size, size, channel], 'inputs')
        labels = tf.placeholder("float", [None, label], 'labels')
    dropout_keep_prob = tf.placeholder("float", None, 'keep_prob')
    learning_rate = tf.placeholder("float", None, name='learning_rate')    
    return inputs, labels, dropout_keep_prob, learning_rate

def get_im(path): # reading imagefile and resizing    
    img = cv2.imread(path, 0)
    resize = cv2.resize(img, (image_size, image_size))
    return resize

def read_train_data(ho=0):     
    train_data = []
    train_target = []

    for j in range(3, 6): 

        path = 'c:/Users/mitsutaka/Documents/resize/data2/%i/*.png'%(j)
        files = sorted(glob.glob(path))

        for fl in files:

            flbase = os.path.basename(fl)
            img = get_im(fl)
            img = np.array(img, dtype=np.float32)
            img -= np.mean(img)
            img /= np.std(img)
            tmp = np.zeros(3)
            tmp[int(j-3)] = 1

            train_data.append(img)
            train_target.append(tmp)

    train_data = np.array(train_data, dtype=np.float32)
    train_target = np.array(train_target, dtype=np.uint8)    
    return train_data, train_target

def read_test_data(test_class):

    path = 'c:/Users/mitsutaka/Documents/%i/*.png'%(test_class)    
    files = sorted(glob.glob(path))
    X_test = []
    X_test_id = []

    for fl in files:

        flbase = os.path.basename(fl)

        img = get_im(fl)
        img = np.array(img, dtype=np.float32)
        img -= np.mean(img)
        img /= np.std(img)

        X_test.append(img)
        X_test_id.append(flbase)

    test_data = np.array(X_test, dtype=np.float32)    
    return test_data, X_test_id

def inference(images_placeholder, keep_prob):

    def weight(shape):
        initial = tf.truncated_normal(shape, stddev=0.1)       
        return tf.Variable(initial)

    def bias(shape):
        initial = tf.zeros(shape)
        return tf.Variable(initial)

    def conv2d(x, W):
        return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding='SAME')

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

    x_image = tf.reshape(images_placeholder, [-1, image_size, image_size, image_channnel])
    tf.summary.image('input', x_image, 10)

    with tf.name_scope('Convolution1') as scope:
        W_conv1 = weight([3, 3, image_channnel, 32])
        b_conv1 = bias([32])
        h_conv1 = tf.nn.relu(conv2d(images_placeholder, W_conv1) + b_conv1)

    with tf.name_scope('Convolution2') as scope:
        W_conv2 = weight([3, 3, 32, 32])
        b_conv2 = bias([32])
        h_conv2 = tf.nn.relu(conv2d(h_conv1, W_conv2) + b_conv2)

    with tf.name_scope('Pooling1') as scope:
        h_pool1 = MaxPooling(h_conv2)

    with tf.name_scope('Convolution3') as scope:
        W_conv3 = weight([3, 3, 32, 64])
        b_conv3 = bias([64])
        h_conv3 = tf.nn.relu(conv2d(h_pool1, W_conv3) + b_conv3)

    with tf.name_scope('Convolution4') as scope:
        W_conv4 = weight([3, 3, 64, 64])
        b_conv4 = bias([64])
        h_conv4 = tf.nn.relu(conv2d(h_conv3, W_conv4) + b_conv4)

    with tf.name_scope('Pooling2') as scope:
        h_pool2 = MaxPooling(h_conv4)        

    with tf.name_scope('FullyConnected1') as scope:
        flat = tf.contrib.layers.flatten(h_pool1)
        tensor_shape = flat.get_shape().as_list()
        W_fc1 = weight([tensor_shape[1], 1024])
        b_fc1 = bias([1024])
        h_fc1 = tf.nn.relu(tf.matmul(flat, W_fc1) + b_fc1)
        h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

    with tf.name_scope('FullyConnected2') as scope:
        W_fc2 = weight([1024, 1024])
        b_fc2 = bias([1024])
        h_fc2 = tf.nn.relu(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
        h_fc2_drop = tf.nn.dropout(h_fc2, keep_prob)

    with tf.name_scope('SoftMax') as scope:
        W_sf = weight([1024, 3])
        b_sf = bias([3])
        y = tf.nn.softmax(tf.matmul(h_fc2_drop, W_sf) + b_sf)

    return y

def loss(logits, labels):

    with tf.name_scope('loss'):
        loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits = logits, labels = labels))
        tf.summary.scalar('loss', loss)
    return loss

def training(loss, learning_rate):

    train_step = tf.train.AdamOptimizer(learning_rate).minimize(loss)
    return train_step

def accuracy(logits, labels):

    with tf.name_scope('accuracy'):
        correct_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(labels, 1))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        tf.summary.scalar('accuracy', accuracy)
    return accuracy

def train():

    inputs, labels, dropout_keep_prob, learning_rate =input_placeholder(image_size, image_channnel, 3)
    logits = inference(inputs, dropout_keep_prob)

    acc = accuracy(logits, labels)
    loss_value = loss(logits, labels)
    train = training(loss_value, learning_rate)

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())

    merged = tf.summary.merge_all()
    train_writer = tf.summary.FileWriter(FLAGS.log_path + '/train/', sess.graph)
    validation_writer = tf.summary.FileWriter(FLAGS.log_path + '/validation/')

    saver = tf.train.Saver()
    if os.path.isfile(FLAGS.save_name):
        saver.restore(sess, FLAGS.save_name)

    ho = 0
    train_dataset, train_labels = read_train_data(ho)
    train_dataset=np.expand_dims(train_dataset,axis=-1)
    print(train_dataset.shape)
    validation_dataset, validation_labels = read_train_data(ho)
    validation_dataset=np.expand_dims(validation_dataset,axis=-1)    

    i=0
    print("Initialized")
    cur_learning_rate = FLAGS.learning_rate

    t1 = time.time()
    for epoch in range(FLAGS.training_epoch):
        step = 0
        if epoch % 10 == 0 and epoch > 0:
            cur_learning_rate /= 10
        for start, end in zip(range(0, len(train_dataset), FLAGS.batch_size), range(FLAGS.batch_size, len(train_dataset), FLAGS.batch_size)):

            step += 1
            batch_data = train_dataset[start:end]
            batch_labels = train_labels[start:end]
            print(step)
            feed_dict_batch ={inputs: batch_data, labels: batch_labels, dropout_keep_prob: FLAGS.dropout_keep_prob, learning_rate: cur_learning_rate}

            if i% FLAGS.validation_interval == 0:
                summary, _, loss_batch, acc_batch = sess.run([merged, train, loss_value, acc], feed_dict=feed_dict_batch)
                train_writer.add_summary(summary, i)

                summary_valid, loss_valid, acc_valid = sess.run([merged, loss_value, acc], feed_dict={inputs: validation_dataset,
                                                                                                     labels: np.squeeze(validation_labels),
                                                                                                     dropout_keep_prob: 1.0})

                validation_writer.add_summary(summary_valid, i)
                print('----------------------------------')
                print('epoch:', epoch + 1, ', step:', step)
                print("Batch loss: {:.2f}".format(loss_batch))
                print("Batch accuracy: {0:.01%}".format(acc_batch))               
                print("Validation loss: {:.2f}".format(loss_valid))
                print("Validation acuuracy: {0:.01%}".format(acc_valid))
            else:
                sess.run(train, feed_dict=feed_dict_batch)
            i+=1

    t2 = time.time()

    elapsed_time = t2-t1
    print(f"経過時間:{elapsed_time}") 
    train_writer.close()
    validation_writer.close()

if __name__ == '__main__':

    param = sys.argv
    run_type = param[1]
    if run_type == 'train':
        train()
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

0

私が思いつく改善点は2点あります.

  • 初期化方法を変更する.
    convolutionの初期化方法を変更することで学習できる可能性があります.具体的な変更点は,
def weight(shape):
        # shapeは(kernel, kernel, in_c, out_c)を想定.
        stddev = np.sqrt(2 / shape[2])
        initial = tf.truncated_normal(shape, stddev=stddev)       
        return tf.Variable(initial)


と変更してみては如何ですか.この初期化方法はhe初期化と呼ばれる方法でよく利用されています.

  • ネットワーク構造を変更してみる.
    3クラス分類のわりに,CNNの後に続くFullyConnected2層がパラメータが多くDropoutを入れたとしても学習を難しくしているように思えます.そのためFullyConnected層を削除して,Convolution4 -> GlobalAveragePooling層 -> SoftMax層の構成に変更してみては如何でしょうか.

以上です.

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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