python - Custom ImageDataGenerator (Keras) for large Dataset and multi input
问题描述
I have been trying to implement a custom ImageDataGenerator for a two input and one output image classification model from an hdf5 file (large dataset of 88k paired images). The network works as follow:
- Each pair of images is fed into a VGG16 model, for feature extraction purposes, (both network have shared parameters and the layers are frozen for training purposes)
- The output of each VGG16 net is concatenated and fed into a 3-FC layers.
- The final output is a probability to decide if these two images are compatible (top and bottom cloth types for outfit matching).
This is the code of my custom generator which reads an hdf5 with two dataset on it, the paired images (88000,2,224,224,3) and the labels (88000,), 1-match 0-notmatch.
class HDF5DataGenerator:
def __init__(self, dbPath, batchSize, preprocessors=None,aug=None,binarize=True,classes=2):
self.batchSize = batchSize
self.preprocessors = preprocessors
self.aug = aug
self.binarize = binarize
self.classes = classes
self.db = h5py.File(dbPath, 'r')
self.numImages = self.db['images'].shape[0]
def generator(self, passes=np.inf):
epochs=0
while epochs < passes:
idx = np.array(range(0,numImages),dtype='int')
np.random.shuffle(idx)
for i in np.arange(0, self.numImages, self.batchSize):
idxBatch = np.array(idx[i:i+batchSize])
idxBatch.sort()
imagesA = self.db['images'][idxBatch,0]
imagesB = self.db['images'][idxBatch,1]
labels = self.db['labels'][idxBatch]
if self.binarize:
labels = to_categorical(labels, self.classes)
if self.preprocessors is not None:
procImagesA = []
for image in imagesA:
for p in self.preprocessors:
image = p.preprocess(image)
procImagesA.append(image)
imagesA = np.array(procImagesA)
procImagesB = []
for image in imagesB:
for p in self.preprocessors:
image = p.preprocess(image)
procImagesB.append(image)
imagesB = np.array(procImagesB)
if self.aug is not None:
(imagesA,labels) = next(self.aug.flow(imagesA, labels, batch_size=self.batchSize))
(imagesB,labels) = next(self.aug.flow(imagesB, labels, batch_size=self.batchSize))
yield [imagesA,imagesB],labels
epochs +=1
def close(self):
self.db.close()
When passing the generator to the fit_generation
function as the following:
trainGen = HDF5DataGenerator('train.hdf5',
BATCH_SIZE,
preprocessors=[mp,iap],
aug=aug,
classes=2)
history = model.fit(trainGen.generator(),
steps_per_epoch = trainGen.numImages // BATCH_SIZE,
#validation_data= testGen.generator(),
#validation_steps = testGen.numImages // BATCH_SIZE,
epochs=EPOCHS,
max_queue_size=10)
I get the following error which frankly I don't understand. I already checked the dimensionality of all the images written in the file since the incompatibility erro shows (None,224,224,1), which make me think that there was something wrong with the data, but that was not the issue.
ValueError: in user code:
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py:805 train_function *
return step_function(self, iterator)
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py:795 step_function **
outputs = model.distribute_strategy.run(run_step, args=(data,))
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/distribute/distribute_lib.py:1259 run
return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/distribute/distribute_lib.py:2730 call_for_each_replica
return self._call_for_each_replica(fn, args, kwargs)
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/distribute/distribute_lib.py:3417 _call_for_each_replica
return fn(*args, **kwargs)
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py:788 run_step **
outputs = model.train_step(data)
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py:755 train_step
loss = self.compiled_loss(
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/keras/engine/compile_utils.py:203 __call__
loss_value = loss_obj(y_t, y_p, sample_weight=sw)
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/keras/losses.py:152 __call__
losses = call_fn(y_true, y_pred)
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/keras/losses.py:256 call **
return ag_fn(y_true, y_pred, **self._fn_kwargs)
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/util/dispatch.py:201 wrapper
return target(*args, **kwargs)
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/keras/losses.py:1537 categorical_crossentropy
return K.categorical_crossentropy(y_true, y_pred, from_logits=from_logits)
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/util/dispatch.py:201 wrapper
return target(*args, **kwargs)
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/keras/backend.py:4833 categorical_crossentropy
target.shape.assert_is_compatible_with(output.shape)
/Users/nicolas/.virtualenvs/cv/lib/python3.8/site-packages/tensorflow/python/framework/tensor_shape.py:1134 assert_is_compatible_with
raise ValueError("Shapes %s and %s are incompatible" % (self, other))
ValueError: Shapes (None, None) and (None, 224, 224, 1) are incompatible
Hope you guys can help me to point me in the right direction to solve the issue.
Thank you for taking some time to read the post!
EDIT-1:
The following is the code of the model to be trained. I fixed the dimension problem.
from keras.layers import concatenate
img_shape = (224,224,3)
img_top = Input(shape=img_shape)
img_bottom = Input(shape=img_shape)
featureExtractor = vgg(img_shape)
feats_top = featureExtractor(img_top)
feats_bottom = featureExtractor(img_bottom)
combined = concatenate([feats_top,feats_bottom])
x = Dense(4096, activation='relu')(combined)
x = Dense(4096, activation='relu')(x)
x = Dense(4096, activation='relu')(x)
x = Dense(2, activation='softmax')(x)
model = Model(inputs=[img_top,img_bottom], outputs=x)
解决方案
推荐阅读
- javascript - 即使在生成另一个脚本时劫持节点也需要
- c - 如何更新世界以获得下一次死/活细胞迭代
- tsql - 将 Jet SQL IsNull 更改为 SQL IsNull 函数
- azure - Microsoft.Azure.Documents.BadRequestException:ResourceType 文档是意外的
- r - 为 gganimate 的动画添加动态文本
- arduino - 读取具有格雷码输出的绝对编码器
- angular - 角度路由器插座无法识别
- flutter - 可以将触摸手势传递给兄弟小部件吗?
- amazon-s3 - 使用 Shrine 上传视频文件并生成缩略图
- visual-studio-code - 如何在 Windows 10 上的 VSCode 上启用具有子像素抗锯齿功能的 ClearType 渲染?