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

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

ただいまの
回答率

89.10%

CNNの学習が上がらない原因を見つけたい

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 3,212

Fdoragon

score 10

 前提・実現したいこと

ubuntuのjupyter notebook上でpythonを用いて畳み込みニューラルネットワーク(CNN)を使って"寿司"、"サラダ"、"麻婆豆腐"を見分けるプログラムを作る。

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

エラーなく実行できたのですが、学習状況を表すグラフが横ばいで全く変化しません。

 該当のソースコード

import cnn_model #cnn_modelは下記のcnn_model.pyからインポートする
import keras
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import train_test_split
import cv2

#入力と出力を指定
im_rows = 32 #画像の縦ピクセル
im_cols = 32 #画像の横ピクセル
im_color = 3 #画像の色空間
in_shape = (im_rows, im_cols, im_color)
nb_classes = 3

#写真データを読み込み
photos = np.load('image/photos.npz')
x = photos['x']
y = photos['y']

#読み込んだデータの三次元配列に変換
x = x.reshape(-1, im_rows, im_cols, im_color)
x = x.astype('float32')/255
#ラベルデータをone-hotベクトルに直す
y = keras.utils.np_utils.to_categorical(y.astype('int32'),nb_classes)

#学習用とテスト用に分ける
x_train, x_test, y_train, y_test = train_test_split(
    x, y, train_size=0.8)

# 学習用データの水増し
x_new = []
y_new = []
for i, xi in enumerate(x_train):
    yi = y_train[i]
    for ang in range(-30, 30, 5):
        #回転させる
        center = (16, 16)
        mtx = cv2.getRotationMatrix2D(center, ang, 1.0)
        xi2 = cv2.warpAffine(xi, mtx, (32, 32))
        x_new.append(xi2)
        y_new.append(yi)
        #更に左右反転させる
        xi3 = cv2.flip(xi2, 1)
        x_new.append(xi3)
        y_new.append(yi)

#水増しした画像を学習用に置き換える
print('水増し前=',len(y_train))
x_train = np.array(x_new)
y_train = np.array(y_new)
print('水増し後=',len(y_train))

#CNNモデルを取得
model = cnn_model.get_model(in_shape, nb_classes)

#学習を実行
hist = model.fit(x_train, y_train,
                batch_size=10,
                epochs=5,
                verbose=1,
                validation_data=(x_test, y_test))

#モデルを評価
score = model.evaluate(x_test,y_test,verbose=1)
print('正解率=', score[1], 'loss=', score[0])

#学習の様子をグラフへ描画
#正解率の推移をプロット
plt.plot(hist.history['acc'])
plt.plot(hist.history['val_acc'])
plt.title('Accuracy')
plt.legend(['train','test'],loc='upper left')
plt.show()

#ロスの推移をプロット
plt.plot(hist.history['loss'])
plt.plot(hist.history['val_loss'])
plt.title('Loss')
plt.legend(['train','test'],loc='upper left')
plt.show()

model.save_weights('./image/photos-model-light.hdf5')

#####################################cnn_model.py############################################
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.optimizers import RMSprop

#CNNのモデルを定義する
def def_model(in_shape, nb_classes):
    model = Sequential()
    model.add(Conv2D(32,
                    kernel_size=(3, 3),
                    activation='relu',
                    input_shape=in_shape))
    model.add(Conv2D(32, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))

    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))

    model.add(Flatten())
    model.add(Dense(512, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(nb_classes, activation='softmax'))
    return model

#コンパイル済のCNNモデルを返す
def get_model(in_shape, nb_classes):
    model = def_model(in_shape, nb_classes)
    model.compile(
        loss='categorical_crossentropy',
        optimizer=RMSprop(),
        metrics=['accuracy'])
    return model


イメージ説明

 試したこと

batchサイズの変更、トレーニング用の画像を再取得、トレーニング用の画像の水増し(約5000枚)

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • tiitoi

    2018/10/18 23:03 編集

    学習は fine-tuning ではなく、フルスクラッチで (1から学習すること) やっていますか?

    キャンセル

  • Fdoragon

    2018/10/19 22:09

    はい、1からの学習です。

    キャンセル

回答 1

+1

ざっと思うところ。

  • 訓練誤差が落ちていないので、過学習以前に学習ができていない。
  • フルスクラッチ学習ではなく、fine-tuning で学習したほうがよい。
  • エポック数5で止めるのは早い気がする。もう少し学習を続けて様子をみたほうがよい。
  • 画像サイズ 32, 32 は小さくしすぎて情報が落ちてしまっているのでは?モデルの入力を (224, 224)  ぐらいにしてみては。
  • Optimizer を adam にしてみる。

まず汎化性能はおいておいて、学習データの Accuracy が 100 %に近づくようがんばりましょう。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/10/19 22:03

    返信ありがとうございます、やってみます!

    キャンセル

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

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