Tensorflow 可变图像输入大小(自动编码器、放大......)

问题描述 投票:0回答:1

编辑:警告 不建议使用具有不同图像尺寸的图像,因为张量需要具有相同的尺寸以允许并行化。

我一直在寻找解决方案,了解如何使用不同大小的图像作为神经网络的输入。

Numpy

第一个想法是使用

numpy
。然而,由于每个图像的大小不同,我无法使用它,因为张量流不接受
numpy.ndarray

尝试简单的

list
也不起作用,因为它不受支持。

数据集生成器

尝试使用

yield
实现自定义生成器,但遇到了
errors
的负载:
完成 GeneratorDataset 迭代器时发生错误:已取消:操作已取消
使用数据集作为输入时不支持tensorflow y参数
没有为任何变量提供梯度
生成器生成形状为 (50, 50, 3) 的元素,其中预期形状为 (None, None, None, 3) 的元素
张量流无法转换为张量流dtype
张量流占位符与急切执行不兼容

在尝试不同的解决方案来实现生成器(来自 SO 和其他站点)时,发生了这些错误和其他错误。

文件结构

/1
  -0.png
  -1.png
/2
  -0.png
  -1.png
/3
  -0.png
  -1.png

文件夹

1
内的图像为50x50像素,
2
为100x100像素,
3
为200x200像素。

升级模型

input_img = keras.Input(shape=(None, None, 3))

upscaled = layers.UpSampling2D((2, 2), interpolation='bilinear')(input_img)
out = layers.Conv2D(3, (3, 3), activation='sigmoid', padding='same')(upscaled)

conv_model = keras.Model(input_img, out)
conv_model.compile(optimizer='adam', loss=tf.keras.losses.MeanSquaredError())
python tensorflow keras generator tensorflow-datasets
1个回答
1
投票

编辑:警告 不建议使用具有不同图像尺寸的图像,因为张量需要具有相同的尺寸以允许并行化。

经过几个小时的研究,我找到了解决方案。我的具体答案采用输入图像,目标是将其放大 2 倍。

加载所有输入和输出(目标)数据的路径:

path = 'path_to_parent_dir'
in_paths = [path + '/1/' + f for f in ['0.png', '1.png']] + [path + '/2/' + f for f in ['0.png', '1.png']]
out_paths = [path + '/2/' + f for f in ['0.png', '1.png']] + [path + '/3/' + f for f in ['0.png', '1.png']]

发电机:

def data_generator(in_paths, out_paths):

    for i in range(len(in_paths)):
        yield cv2.imread(in_paths[i]) / 255, cv2.imread(out_paths[i]) / 255

转换为数据集

train_dataset = tf.data.Dataset.from_generator(
    lambda: data_generator(in_paths, out_paths), 
    output_types=(tf.float32, tf.float32), 
    output_shapes=((None, None, 3), (None, None, 3))
).batch(1)

validate_dataset = tf.data.Dataset.from_generator(
    lambda: data_generator(in_paths, out_paths), 
    output_types=(tf.float32, tf.float32), 
    output_shapes=((None, None, 3), (None, None, 3))
).batch(1)

lambda
函数是必需的,因为
from_generator
不接受生成器,而是接受对函数本身的引用(因此没有参数)。可以在
args=()
中使用
from_generator
,但就我而言,数据(路径)已转换为类似字节的对象,因此它对我不起作用。

警告

这只是一个示例,它使用相同的数据进行训练和验证(这是愚蠢的)。适应此解决方案时,请为每个使用不同的数据。

培训

conv_model.fit(
    train_dataset,
    epochs=1,
    validation_data=validate_dataset
)

自动分片政策

此工作流程会在每个 epoch 后(或者实际上是在其中或在随机时间)生成一条非常长的警告消息,建议关闭自动分片或将 auto_shard_policy 切换为 DATA 以对数据集进行分片。

但这只是一个警告,所以即使有它也能工作。有一个关于如何禁用此功能的解决方案:so 链接

替代方案

我还找到了另一种方法来完成这项工作。不同之处在于,它必须生成不同类型的输出(元组的元组)。不确定哪种方式是正确的,或者它们是否等效。

def data_generator_(in_paths, out_paths):

    for i in range(len(in_paths)):
        yield (cv2.imread(in_paths[i]) / 255, ), (cv2.imread(out_paths[i]) / 255, )
train_dataset = tf.data.Dataset.from_generator(
    lambda: data_generator_2(in_paths, out_paths), 
    output_types=(tf.float32, tf.float32), 
    output_shapes=((None, None, None, 3), (None, None, None, 3))
)

validate_dataset = tf.data.Dataset.from_generator(
    lambda: data_generator_2(in_paths, out_paths), 
    output_types=(tf.float32, tf.float32), 
    output_shapes=((None, None, None, 3), (None, None, None, 3))
)
conv_model.fit(
    train_dataset,
    epochs=1,
    batch_size=1,
    validation_data=validate_dataset
)

这是一个真正痛苦的弄清楚,希望它能帮助别人。

© www.soinside.com 2019 - 2024. All rights reserved.