0

我有以下自定义生成器,用于为连体网络构建图像对,因为不幸的是,我的所有训练数据都不适合我的 GPU 内存:

import numpy as np
np.random.seed(42)  # for reproducibility

import random
from keras.datasets import mnist
from keras.models import Sequential, Model
from keras.layers import Dense, Dropout, Input, Lambda
from keras.optimizers import SGD, RMSprop
from keras import backend as K
from sklearn.utils import shuffle
from sklearn.model_selection import train_test_split

class DataGenerator(object):
    def __init__(self, batch_sz):
       
        print("[INFO] loading dataset...")

        trainX=np.load("features_and_labels/energy/train1-images.npy") 
        trainY=np.load("features_and_labels/energy/train1-labels.npy") 
 
        trainX, trainY = shuffle(trainX, trainY)

        trainX, testX, trainY, testY = train_test_split(trainX, trainY, test_size=0.30, stratify=trainY, random_state=42)
        
        trainX = trainX / 255.0
        testX = testX / 255.0
                 
        print("READY")
            # create training+test positive and negative pairs
        digit_indices = [np.where(trainY == i)[0] for i in range(8)]
        self.tr_pairs, self.tr_y = self.create_pairs(trainX, digit_indices)
        digit_indices = [np.where(testY == i)[0] for i in range(8)]
        self.te_pairs, self.te_y = self.create_pairs(testX, digit_indices)

        self.tr_pairs_0 = self.tr_pairs[:, 0]
        self.tr_pairs_1 = self.tr_pairs[:, 1]
        self.te_pairs_0 = self.te_pairs[:, 0]
        self.te_pairs_1 = self.te_pairs[:, 1]

        self.batch_sz = batch_sz
        self.samples_per_train  = (self.tr_pairs.shape[0]/self.batch_sz)*self.batch_sz
        self.samples_per_val    = (self.te_pairs.shape[0]/self.batch_sz)*self.batch_sz
        self.cur_train_index=0
        self.cur_val_index=0
        del trainX, trainY,
        #(pairTest, labelTest) = utils.make_pairs(testX, testY)
        print("DONE")
        del testX,testY

    def create_pairs(self, x, digit_indices):
        pairs = []
        labels = []
        n = min([len(digit_indices[d]) for d in range(8)]) - 1
        for d in range(8):
            for i in range(n):
                z1, z2 = digit_indices[d][i], digit_indices[d][i+1]
                pairs += [[x[z1], x[z2]]]
                inc = random.randrange(0, 8)
                dn = (d + inc) % 7
                z1, z2 = digit_indices[d][i], digit_indices[dn][i]
                pairs += [[x[z1], x[z2]]]
                labels += [1, 0]
        return np.array(pairs), np.array(labels)

    def next_train(self):
        while 1:
            self.cur_train_index += self.batch_sz
            if self.cur_train_index >= self.samples_per_train:
                        self.cur_train_index=0
            yield ([self.tr_pairs_0[self.cur_train_index:self.cur_train_index+self.batch_sz],              self.tr_pairs_1[self.cur_train_index:self.cur_train_index+self.batch_sz]],self.tr_y[self.cur_train_index:self.cur_train_index+self.batch_sz])

    def next_val(self):
        while 1:
            self.cur_val_index += self.batch_sz
            if self.cur_val_index >= self.samples_per_val:
                self.cur_val_index=0
            yield ([self.te_pairs_0[self.cur_val_index:self.cur_val_index+self.batch_sz], self.te_pairs_1[self.cur_val_index:self.cur_val_index+self.batch_sz]],                    self.te_y[self.cur_val_index:self.cur_val_index+self.batch_sz])

我想在这些图像对中使用以下数据增强技术:

 augmentator=ImageDataGenerator(
    rotation_range=20,
    zoom_range=0.15,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.15,
    horizontal_flip=True,
    fill_mode="nearest")

但是,我在调用它时遇到以下问题,这是我的做法

convnet = resnet50.ResNet50(weights='imagenet', include_top=False, input_shape=(224,224,3))
# Add the final fully connected layers
x = convnet.output
x = Flatten()(x)
x = Dense(1024, activation="relu")(x)
x = Dropout(0.3)(x)
preds = Dense(18, activation='sigmoid')(x) # Apply sigmoid
convnet = Model(inputs=convnet.input, outputs=preds)

#Applying above model for both the left and right images
encoded_l = convnet(left_input)
encoded_r = convnet(right_input)
# Euclidian Distance between the two images or encodings through the Resnet-50 architecture
Euc_layer = Lambda(lambda tensor:K.abs(tensor[0] - tensor[1]))
# use and add the distance function
Euc_distance = Euc_layer([encoded_l, encoded_r])
#identify the prediction
prediction = Dense(1,activation='sigmoid')(Euc_distance)
#Define the network with the left and right inputs and the ouput prediction
siamese_net = Model(inputs=[left_input,right_input],outputs=prediction)

#Calling the generator for me
datagen = mycustomgenerator_v2.DataGenerator(config.BATCH_SIZE)

print("[INFO] compiling model...")
   
siamese_net.compile(loss="binary_crossentropy", optimizer="sgd", metrics="accuracy")
       
# train the model
print("[INFO] training model...")

lr_reducer= ReduceLROnPlateau(monitor='val_loss', factor=np.sqrt(0.1), cooldown=0, patience=3, min_lr=0.5e-6)
early_stopper=EarlyStopping(monitor='val_accuracy', min_delta=0.1, patience=250,restore_best_weights=True,verbose=1)
model_checkpoint= ModelCheckpoint("best_weight.h5", monitor="val_accuracy", save_best_only=True, save_weights_only=True,mode='auto')
callbacks=[lr_reducer,early_stopper,model_checkpoint]

augmentator=ImageDataGenerator(
        rotation_range=20,
        zoom_range=0.15,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.15,
        horizontal_flip=True,
        fill_mode="nearest")

history=siamese_net.fit(augmentator.flow(datagen.next_train()), steps_per_epoch=datagen.samples_per_train, epochs=config.EPOCHS, validation_data=datagen.next_val(), validation_steps=datagen.samples_per_val, callbacks=callbacks)

然后以下错误返回给我

 File "train_siamese_network.py", line 163, in <module>
    history=siamese_net.fit(augmentator.flow(datagen.next_train()), steps_per_epoch=datagen.samples_per_train, epochs=config.EPOCHS, validation_data=datagen.next_val(), validation_steps=datagen.samples_per_val, callbacks=callbacks)
  File "/home/me/.local/lib/python3.8/site-packages/tensorflow/python/keras/preprocessing/image.py", line 854, in flow
    return NumpyArrayIterator(
  File "/home/me/.local/lib/python3.8/site-packages/tensorflow/python/keras/preprocessing/image.py", line 450, in __init__
    super(NumpyArrayIterator, self).__init__(
  File "/home/me/.local/lib/python3.8/site-packages/keras_preprocessing/image/numpy_array_iterator.py", line 121, in __init__
    self.x = np.asarray(x, dtype=self.dtype)
  File "/home/me/.local/lib/python3.8/site-packages/numpy/core/_asarray.py", line 83, in asarray
    return array(a, dtype, copy=False, order=order)
TypeError: float() argument must be a string or a number, not 'generator'

当然,我没有正确调用生成器上的数据增强器,我还检查了其他类似的帖子,例如thisthisthis ,但它们对我没有帮助。因此,我应该如何在我的连体网络的自定义生成器上调用数据增强?

4

1 回答 1

1

我不知道如何在 Pairs Dataset 中应用 ImageDataAugmentation。但我可以告诉你,一种可能性是在你的磁盘中生成图像。这意味着您将从原始数据集生成图像(当没有对时),并在下一步中将其转换为对。

缺点是,这种方法会将非常相似的图像放入测试和训练数据中,这可能意味着过度拟合。

于 2021-10-29T20:51:44.627 回答