我有以下自定义生成器,用于为连体网络构建图像对,因为不幸的是,我的所有训练数据都不适合我的 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'
当然,我没有正确调用生成器上的数据增强器,我还检查了其他类似的帖子,例如this、this和this ,但它们对我没有帮助。因此,我应该如何在我的连体网络的自定义生成器上调用数据增强?