web-dev-qa-db-ja.com

サブディレクトリ構造を維持したまま、データディレクトリをトレーニングおよびテストディレクトリに分割

KerasのImageDataGeneratorをデータ拡張に使用することに興味があります。ただし、クラスのサブディレクトリを含むトレーニングディレクトリと検証ディレクトリは、以下のように個別にフィードする必要があります(これはKerasのドキュメントにあります)。 2つのクラス(Data/Class1とData/Class2)の2つのサブディレクトリを持つ単一のディレクトリがあります。これをトレーニングディレクトリと検証ディレクトリにランダムに分割する方法

    train_datagen = ImageDataGenerator(
    rescale=1./255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

    test_datagen = ImageDataGenerator(rescale=1./255)

    train_generator = train_datagen.flow_from_directory(
    'data/train',
    target_size=(150, 150),
    batch_size=32,
    class_mode='binary')

   validation_generator = test_datagen.flow_from_directory(
    'data/validation',
    target_size=(150, 150),
    batch_size=32,
    class_mode='binary')

   model.fit_generator(
    train_generator,
    steps_per_Epoch=2000,
    epochs=50,
    validation_data=validation_generator,
    validation_steps=800)

ランダムトレーニングと検証データ分割でアルゴリズムを複数回再実行することに興味があります。

11

君たちありがとう!トレーニングとテストのデータセットを作成するための独自の関数を書くことができました。これが、探している人のためのコードです。

import os
source1 = "/source_dir"
dest11 = "/dest_dir"
files = os.listdir(source1)
import shutil
import numpy as np
for f in files:
    if np.random.Rand(1) < 0.2:
        shutil.move(source1 + '/'+ f, dest11 + '/'+ f)
11

https://stackoverflow.com/a/52372042/10111155 最も簡単な方法を提供:ImageDataGeneratorは、サブディレクトリを持つ単一のディレクトリから直接train/testに分割できるようになりました。

これはその回答から直接コピーされ、変更はありません。私は信用しません。私はそれを試しました、そしてそれは完全に働きました。

train_data_dirtrain_generatorvalidation_generatorで同じであることに注意してください。 ImageDataGeneratorを使用して3方向の分割(train/test/valid)が必要な場合は、ソースコードを変更する必要があります---ニースの指示があります here

train_datagen = ImageDataGenerator(rescale=1./255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    validation_split=0.2) # set validation split

train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary',
    subset='training') # set as training data

validation_generator = train_datagen.flow_from_directory(
    train_data_dir, # same directory as training data
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary'
    subset='validation') # set as validation data

model.fit_generator(
    train_generator,
    steps_per_Epoch = train_generator.samples // batch_size,
    validation_data = validation_generator, 
    validation_steps = validation_generator.samples // batch_size,
    epochs = nb_epochs)
3
Beau Hilton

残念ながら、現在のkeras.preprocessing.image.ImageDataGeneratorの実装(2017年10月14日現在)は不可能ですが、これは本当に要求されている機能であるため、近い将来に追加される予定です。

しかし、これは標準のPython os操作を使用して行うことができます。データセットのサイズによっては、最初にすべての画像をRAMにロードしてから、データをランダムに分割できる従来のfitメソッドを使用します。

2
Marcin Możejko

トレーニングデータの一部を手動でコピーして検証ディレクトリに貼り付けるか、データをトレーニングディレクトリから検証ディレクトリにランダムに移動するプログラムを作成する必要があります。これらのオプションのいずれかを使用する場合は、検証ディレクトリにパスとして検証ImageDataGenerator().flow_from_directory()を渡す必要があります。

ディレクトリ構造でデータを整理するための詳細は このビデオ で説明されています。

1

画像に変換を適用せずに画像データのみを分割する場合は、次のコードを使用します。

from keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(
        validation_split=0.4)

train_generator = train_datagen.flow_from_directory(
        'path_to_data_directory',
        subset='training')

validation_generator = train_datagen.flow_from_directory(
        'path_to_data_directory', #same as in train generator
        subset='validation')

これは、指定された 'path_to_data_directory'を取得し、そのディレクトリからサブフォルダから画像を取得し、それぞれのサブフォルダ名を画像のクラス名として。

出力例

Found 43771 images belonging to 9385 classes.
Found 22490 images belonging to 9385 classes.

Model.fit_generatorを使用して、このデータをモデルにロードできます。

詳細は https://keras.io/preprocessing/image/ を参照してください。

0
codeslord

ソリューションはうまくいきました。

   import os
   import shutil
   import numpy as np

   sourceN = base_dir + "\\train\\NORMAL\\"
   destN = base_dir + "\\val\\NORMAL"
   sourceP = base_dir + "\\train\\PNEUMONIA"
   destP = base_dir + "\\val\\PNEUMONIA"

   filesN = os.listdir(sourceN)
   filesP = os.listdir(sourceP)       

   for f in filesN:
       if np.random.Rand(1) < 0.2:
       shutil.move(sourceN + '\\'+ f, destN + '\\'+ f)

   for i in filesP:
       if np.random.Rand(1) < 0.2:
       shutil.move(sourceP + '\\'+ i, destP + '\\'+ i)

   print(len(os.listdir(sourceN)))
   print(len(os.listdir(sourceP)))
   print(len(os.listdir(destN)))
   print(len(os.listdir(destP)))
0
Jordy

これが私のアプローチです:

# Create temporary validation set.
with TemporaryDirectory(dir=train_image_folder) as valid_image_folder, TemporaryDirectory(dir=train_label_folder) as valid_label_folder:
    train_images = os.listdir(train_image_folder)
    train_labels = os.listdir(train_label_folder)

    for img_name in train_images:
        single_name, ext = os.path.splitext(img_name)
        label_name = single_name + '.png'
        if label_name not in train_labels:
            continue
        if random.uniform(0, 1) <= train_val_split:
            # Move the files.
            shutil.move(os.path.join(train_image_folder, img_name), os.path.join(valid_image_folder, img_name))
            shutil.move(os.path.join(train_label_folder, label_name), os.path.join(valid_label_folder, img_name))

すべてを戻すことを忘れないでください。

0
Richard