У меня есть собственный файл, содержащий пути ко всем моим изображениям и их меткам, которые я загружаю в фрейм данных, используя:

MyIndex=pd.read_table('./MySet.txt')

MyIndex имеет два интересующих столбца: ImagePath и ClassName .

Затем я делаю несколько тестовых разделений и кодирую выходные метки как:

images=[]
for index, row in MyIndex.iterrows():
    img_path=basePath+row['ImageName']
    img = image.load_img(img_path, target_size=(299, 299))
    img_path=None
    img_data = image.img_to_array(img)
    img=None
    images.append(img_data)
    img_data=None


images[0].shape

Classes=Sample['ClassName']
OutputClasses=Classes.unique().tolist()

labels=Sample['ClassName']
images=np.array(images, dtype="float") / 255.0
(trainX, testX, trainY, testY) = train_test_split(images,labels, test_size=0.10, random_state=42)
trainX, valX, trainY, valY = train_test_split(trainX, trainY, test_size=0.10, random_state=41)

images=None
labels=None

encoder = LabelEncoder()
encoder=encoder.fit(OutputClasses)
encoded_Y = encoder.transform(trainY)
# convert integers to dummy variables (i.e. one hot encoded)
trainY = to_categorical(encoded_Y, num_classes=len(OutputClasses))

encoded_Y = encoder.transform(valY)
# convert integers to dummy variables (i.e. one hot encoded)
valY = to_categorical(encoded_Y, num_classes=len(OutputClasses))

encoded_Y = encoder.transform(testY)
# convert integers to dummy variables (i.e. one hot encoded)
testY = to_categorical(encoded_Y, num_classes=len(OutputClasses))

datagen=ImageDataGenerator(rotation_range=90,horizontal_flip=True,vertical_flip=True,width_shift_range=0.25,height_shift_range=0.25)
datagen.fit(trainX,augment=True)

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


batch_size=128
model.fit_generator(datagen.flow(trainX,trainY,batch_size=batch_size), epochs=500, 
                    steps_per_epoch=trainX.shape[0]//batch_size,validation_data=(valX,valY))

Проблема, с которой я сталкиваюсь, состоит в том, что данные, загруженные за один раз, слишком велики, чтобы поместиться в текущую машинную память, и поэтому я не могу работать с полным набором данных.

Я пытался работать с генератором данных, но не хочу следовать принятым в нем соглашениям о каталогах, а также не могу устранить часть дополнения.

Вопрос в том, есть ли способ загрузки пакетов с диска, обеспечивающий два заявленных условия.

5
pure_virtual 28 Июн 2019 в 14:09

2 ответа

Лучший ответ

Я полагаю, что вам следует взглянуть на эту запись

Что вам нужно, так это K eras flow_from_dataframe , который позволяет загружать пакеты с диска, предоставляя имена ваших файлов и их метки в кадре данных, а также указывать путь к верхнему каталогу, который содержит все ваши изображения .

Сделав немного изменений в вашем коде и позаимствовав некоторые из ссылки, которую вы делили:

MyIndex=pd.read_table('./MySet.txt')

Classes=MyIndex['ClassName']
OutputClasses=Classes.unique().tolist()

trainDf=MyIndex[['ImageName','ClassName']]
train, test = train_test_split(trainDf, test_size=0.10, random_state=1)


#creating a data generator to load the files on runtime
traindatagen=ImageDataGenerator(rotation_range=90,horizontal_flip=True,vertical_flip=True,width_shift_range=0.25,height_shift_range=0.25,
    validation_split=0.1)
train_generator=traindatagen.flow_from_dataframe(
    dataframe=train,
    directory=basePath,#the directory containing all your images
    x_col='ImageName',
    y_col='ClassName',
    class_mode='categorical',
    target_size=(299, 299),
    batch_size=batch_size,
    subset='training'
)
#Also a generator for the validation data
val_generator=traindatagen.flow_from_dataframe(
    dataframe=train,
    directory=basePath,#the directory containing all your images
    x_col='ImageName',
    y_col='ClassName',
    class_mode='categorical',
    target_size=(299, 299),
    batch_size=batch_size,
    subset='validation'
)


STEP_SIZE_TRAIN=train_generator.n//train_generator.batch_size
STEP_SIZE_VALID=val_generator.n//val_generator.batch_size
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

model.fit_generator(generator=train_generator, steps_per_epoch=STEP_SIZE_TRAIN,
                    validation_data=val_generator,
                    validation_steps=STEP_SIZE_VALID,
                    epochs=500)

Также обратите внимание, что теперь вам не нужно кодировать метки, как это было в исходном коде, а также не указывать код загрузки изображения.

Я не пробовал этот код сам по себе, поэтому постарайтесь исправить любые ошибки, с которыми вы можете столкнуться, так как основной задачей было донести до вас основную идею.

В ответ на ваш комментарий: Если у вас есть все файлы в разных каталогах, то одним из решений было бы, чтобы ваше ImagesName сохраняло относительный путь, включая промежуточный каталог по пути, например, «./Dir/File.jpg», а затем перемещал все каталоги в одну папку и использовал один как базовый путь, а все остальное остается прежним. Кроме того, глядя на ваш сегмент кода, который загружал файлы, выглядело так, как будто у вас уже есть пути к файлам, хранящиеся в столбце ImageName, поэтому предложенный подход должен работать для вас.

images=[]
for index, row in MyIndex.iterrows():
    img_path=basePath+row['ImageName']
    img = image.load_img(img_path, target_size=(299, 299))
    img_path=None
    img_data = image.img_to_array(img)
    img=None
    images.append(img_data)
    img_data=None

Если все еще существует некоторая двусмысленность, не стесняйтесь спрашивать снова.

2
Tayyab 28 Июн 2019 в 11:51

Если вы хотите загрузить с диска, это удобно делать с ImageDataGenerator, который вы использовали.

Есть два способа сделать это. Указав каталог данных с помощью flow_from_directory. В качестве альтернативы вы можете использовать flow_from_dataframe с фреймом данных Pandas

Если вы хотите иметь список путей, вы не должны использовать собственный генератор, который выдает пакеты изображений. Вот заглушка:

def load_image_from_path(path):
    "Loading and preprocessing"
    ...

def my_generator():
    length = df.shape[0]
    for i in range(0, length, batch_size)
        batch = df.loc[i:min(i+batch_size, length-1)]
        x, y = map(load_image_from_path, batch['ImageName']), batch['ClassName']
        yield x, y

Примечание. В fit_generator есть дополнительный генератор с именем validation_data, который, как вы уже догадались, это - проверка. Один из вариантов - передать генераторам индексы на выбор, чтобы разделить поезд и проверить (при условии, что данные перемешаны, если нет, проверьте это из ) .

2
Nadav 28 Июн 2019 в 14:32