【发布时间】:2021-12-19 21:36:26
【问题描述】:
Tensorflow:2.6.0,Ubuntu 20.04.3 LTS,GPU:GeForce MX130,CUDA 版本:11.2
我有一个数据集,其中包含 32 位图像文件和 8 位掩码文件,均为 tiff 格式。这是一个巨大的数据集。因此,我想以 tf.data.Dataset 格式而不是 numpy 数组加载我的数据(因为这可以加快加载速度并避免内存问题)。使用 tf.io.read_file(img_path) 解码我的 tiff 文件,然后使用 tfio.experimental.image.decode_tiff(img) 在这里不起作用,因为它会引发以下错误: TIFFReadDirectory:警告,遇到标记为 42113 (0xa481) 的未知字段。 TIFFReadDirectory:警告,遇到标记为 42113 (0xa481) 的未知字段。 内存:抱歉,无法处理具有 32 位样本的图像。
因此我决定使用 tiffile 库来解码数据,如下所示: img = tiff.imread(img_path)
这是我的一段代码:
full_dataset = tf.data.Dataset.list_files(dataset_path + "*.tif", shuffle=False)
full_dataset = full_dataset.shuffle(buffer_size=100, seed=42)
train_dataset = full_dataset.take(train_size)
test_dataset = full_dataset.skip(train_size)
val_dataset = test_dataset.skip(val_size)
test_dataset = test_dataset.take(test_size)
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_dataset = train_dataset.map(lambda x: tf.py_function(preprocess, inp=[x], Tout= [tf.float32, tf.uint8]))
val_dataset = val_dataset.map(lambda x: tf.py_function(preprocess, inp=[x], Tout=[tf.float32, tf.uint8]))
test_dataset = test_dataset.map(lambda x: tf.py_function(preprocess, inp=[x], Tout=[tf.float32, tf.uint8]))
我在这里使用 tf.py_function 是因为我想在 map 函数中使用 tiff 库来读取图像。为此,我需要图像路径为 python 字符串格式。我注意到,如果我使用通常的 map 函数,路径将作为字符串类型的张量发送给函数。
这里是预处理函数:
def preprocess(img_path: str):
f_name = bytes.decode(img_path.numpy()) # for this you need tf.py_function
img = tiff.imread(f_name)
img = img[:, :, [0, 2, 3]] # The image has 4 channels, I need only 3 of them. Therefore extracting those using indices
img[:, :, 0] = img[:, :, 0] / img[:, :, 0].max() # normaliing values in all 3 channels
img[:, :, 1] = img[:, :, 1] / img[:, :, 1].max()
img[:, :, 2] = img[:, :, 2] / img[:, :, 2].max()
mask_path = tf.strings.regex_replace(img_path, "Images/", "Masks/mask_")
mask = tf.io.read_file(mask_path)
mask = tfio.experimental.image.decode_tiff(mask)
mask = mask[:, :, 0:1] # 1 channel for mask
img = tf.image.resize(img, (128, 128))
mask = tf.image.resize(mask, (128, 128))
mask = tf.cast(mask, tf.float32) / 255.0 # normalizing mask
img = tf.image.convert_image_dtype(img, tf.float32)
mask = tf.image.convert_image_dtype(mask, tf.uint8) # since the tf.py_function is expecting Tout to be tf.float32 and tf.uint8
return img, mask
在此之后,我将开始训练我的模型:
train_dataset = train_dataset.batch(10)
train_dataset = train_dataset.prefetch(buffer_size=AUTOTUNE)
val_dataset = val_dataset.batch(10)
val_dataset = val_dataset.prefetch(buffer_size=AUTOTUNE)
test_dataset = test_dataset.batch(10)
test_dataset = test_dataset.prefetch(buffer_size=AUTOTUNE)
为了确认我的数据集不为空,我将在此之后绘制图像并从中蒙版。效果很好。
for images_batch, masks_batch in train_dataset.take(1):
fig, arr = plt.subplots(1, 2, figsize=(14, 10))
print(images_batch.shape)
print(masks_batch.shape)
arr[0].imshow(images_batch[0], interpolation='nearest')
arr[1].imshow(masks_batch[0], cmap='gray')
plt.show()
它还打印图像的大小和遮罩批次: (10, 128, 128, 3) (10, 128, 128, 1)
打印数据集:
print(train_dataset)
print(val_dataset)
print(test_dataset)
给出以下输出:
<PrefetchDataset shapes: ((None, 128, 128, None), (None, 128, 128, None)), types: (tf.float32, tf.uint8)>
<PrefetchDataset shapes: ((None, 128, 128, None), (None, 128, 128, None)), types: (tf.float32, tf.uint8)>
<PrefetchDataset shapes: ((None, 128, 128, None), (None, 128, 128, None)), types: (tf.float32, tf.uint8)>
现在拟合模型:
model.fit(train_dataset, epochs=20,
steps_per_epoch=STEPS_PER_EPOCH,
validation_steps=VALIDATION_STEPS,
batch_size=10,
validation_data=val_dataset,
callbacks=callbacks)
给出以下错误:
line 39, in train_using_tf_data
history = model.fit(train_dataset, epochs=attributes.EPOCHS,
File "/home/user/TfProjects/venv/lib/python3.8/site-packages/tensorflow/python/keras/engine/training.py", line 1204, in fit
raise ValueError('Expect x to be a non-empty array or dataset.')
ValueError: Expect x to be a non-empty array or dataset.
我以为我在预处理函数之后返回了一个 tf.data.Dataset。我还可以从返回的数据集中绘制数据。数据集在哪里可能是空的? 我的猜测是 tf.py_fucntion 在某种程度上搞砸了。但我不明白在哪里以及如何解决它。有人知道吗?
【问题讨论】:
标签: python tiff ubuntu-20.04 tensorflow2.x