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

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

ただいまの
回答率

90.77%

  • Python

    6900questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • TensorFlow

    608questions

  • Keras

    166questions

kerasによる交差検証(k-fold)

解決済

回答 1

投稿 編集

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

sayaka1202

score 7

前提・実現したいこと

現在画像認識をこちらを参考にkerasで行おうと考えています.
その際,交差検証(K-fold)を利用したいと思っているのですが,どう記述すればよいかわかりません.
参考1参考2あたり目を通しましたが,flow_from_directory()を用いている時自分ではどうすればよいかわかりませんでした,手助けお願い致します.

該当のソースコード

import os
from keras.applications.inception_v3 import InceptionV3
from keras.applications.inception_v3 import preprocess_input
from keras.models import Sequential, Model
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D, ZeroPadding2D, GlobalAveragePooling2D, AveragePooling2D
from keras.regularizers import l2
from keras.utils import np_utils
from keras.utils import plot_model
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import ModelCheckpoint, EarlyStopping, TensorBoard
import matplotlib.pyplot as plt
import keras.backend as K
import keras.backend.tensorflow_backend as KTF
import tensorflow as tf
from keras.optimizers import SGD
from sklearn.model_selection import KFold

epoch = 10

result_dir = ''
train_dir = ''
test_dir = ''
save_dir = ''
cp_fname = ''
txt_name = ''
acc_name = ""
loss_name = ""
if not os.path.exists(result_dir):
    os.mkdir(result_dir)


def plot_history(history):
    savefile = acc_name
    # 精度の履歴をプロット
    plt.plot(history.history['acc'], "o-", label="accuracy")
    plt.plot(history.history['val_acc'], "o-", label="val_acc")
    plt.title('model accuracy')
    plt.xlabel('epoch')
    plt.ylabel('accuracy')
    plt.legend(loc="lower right")
    plt.savefig(savefile)
    savefile = loss_name
    #plt.show()
    plt.clf()

    # 損失の履歴をプロット
    plt.plot(history.history['loss'], "o-", label="loss", )
    plt.plot(history.history['val_loss'], "o-", label="val_loss")
    plt.title('model loss')
    plt.xlabel('epoch')
    plt.ylabel('loss')
    plt.legend(loc='lower right')
    plt.savefig(savefile)
    #plt.show()


def save_history(history, result_file):
    loss = history.history['loss']
    acc = history.history['acc']
    val_loss = history.history['val_loss']
    val_acc = history.history['val_acc']
    nb_epoch = len(acc)

    with open(result_file, "w") as fp:
        fp.write("epoch\tloss\tacc\tval_loss\tval_acc\n")
        for i in range(nb_epoch):
            fp.write("%d\t%f\t%f\t%f\t%f\n" % (i, loss[i], acc[i], val_loss[i], val_acc[i]))


if __name__ == '__main__':
    classes = ['a', 'b', 'c', 'd']

    batch_size = 32
    nb_classes = len(classes)
    img_rows, img_cols = 299, 299
    channels = 3

    samples_per_epoch = 1600
    nb_val_samples = 400

    # 交差検証KFold法5分割
    kf = KFold(n_splits=5, shuffle=True)
    sum_accuracy = 0
    accuracy = []

    # TensorBoard
    old_session = KTF.get_session()
    session = tf.Session('')
    KTF.set_session(session)
    KTF.set_learning_phase(1)

    # CNNを構築
    # Inception v3モデルの読み込み,最終層は読み込まない
    base_model = InceptionV3(weights='imagenet', include_top=False)
    # 最終層の設定
    x = base_model.output
    x = GlobalAveragePooling2D()(x)

    predictions = Dense(nb_classes, kernel_initializer="glorot_uniform", activation="softmax",
                        kernel_regularizer=l2(.0005))(x)


    model = Model(inputs=base_model.input, outputs=predictions)
    plot_model(model, show_shapes=True, to_file=os.path.join(result_dir, 'model.png'))
    model.summary()

    # base_modelはweightsを更新しない
    for layer in base_model.layers:
        layer.trainable = False

    model.compile(loss='categorical_crossentropy',
                  optimizer='adam',
                  metrics=['accuracy'])


    # ディレクトリの画像を使ったジェネレータ
    train_datagen = ImageDataGenerator(
        samplewise_center=False,  
        featurewise_center=False,  
        featurewise_std_normalization=False,
        samplewise_std_normalization=False,
        rotation_range=20, 
        width_shift_range=0.1,  
        # height_shift_range=0.1, 
        horizontal_flip=True,  
        vertical_flip=False, 
        zoom_range=0.1,
        channel_shift_range=20,
        # fill_mode='nearest'
    )

    test_datagen = ImageDataGenerator(rescale=1.0 // 255)

    train_generator = train_datagen.flow_from_directory(
        directory=train_dir,
        target_size=(img_rows, img_cols),
        color_mode='rgb',
        classes=classes,
        class_mode='categorical',
        batch_size=batch_size,
        shuffle=True,
        save_to_dir=save_dir)

    print(train_generator.class_indices)

    test_generator = test_datagen.flow_from_directory(
        directory=test_dir,
        target_size=(img_rows, img_cols),
        color_mode='rgb',
        classes=classes,
        class_mode='categorical',
        batch_size=batch_size,
        shuffle=True)

    cp_cb = ModelCheckpoint(filepath=cp_fname, verbose=1,
                            save_best_only=True)

    es_cb = EarlyStopping(monitor='val_loss', patience=3, verbose=1, mode='auto')

    tb_cb = TensorBoard(log_dir="{}tensorlog".format(result_dir), histogram_freq=1, write_graph=True)

    history = model.fit_generator(
        train_generator,
        steps_per_epoch=samples_per_epoch // batch_size,
        epochs=epoch,
        validation_data=test_generator,
        validation_steps=nb_val_samples // batch_size,
        callbacks=[cp_cb, es_cb, tb_cb])

    save_history(history, os.path.join(result_dir, txt_name))
    plot_history(history)

    # TensorBoard
    KTF.set_session(old_session)

    K.clear_session()
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

英語に抵抗がないのであれば、ここを参考にすればよいと思います。

いずれにしろ、ImageDataGeneratorの.flow_from_directory()を使うのは問題あるように感じます。
と言いますのも、KFoldをする理由というのは異なるデータセットで汎用性を確かめたいためです。
しかし、ImageDataGeneratorではもとは同じ画像を変形させたりして大量にデータを作成します。
この複製されたデータに対してKFoldしても過学習することになります。
ですので、ImageDataGeneratorに読み込ませる時点でデータを分ける必要があります。

train_originalというフォルダを用意して、train_fit, train_validにシンボリックリンクをはり、それぞれに対して2つのImageDataGeneratorを作成するべきです。
これをos.listdir(path), sklearn.model_selection.StratifiedKFold(), os.symlink(src, dst)を組み合わせることで作ることができます。

ポイントはもとの教師データを2つのフォルダに分けるための関数を作ることです。
それさえできれば、後はすんなり行くはずです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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

  • Python

    6900questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • TensorFlow

    608questions

  • Keras

    166questions