Tensorflow 可变图像输入大小(自动编码器、放大...)
Tensorflow variable image input size (autoencoder, upscaling ...)
我一直在寻找解决方案,关于如何使用不同大小的图像作为 NN 的输入。
Numpy
第一个想法是使用 numpy
。但是由于每个图像的大小不同,我无法使用它,因为 tensorflow 不接受 numpy.ndarray
.
尝试简单的 list
也没有用,因为它不受支持。
数据集生成器
尝试使用 yield
实现自定义生成器,但 运行 加载 errors
:
完成 GeneratorDataset 迭代器时出错:已取消:操作已取消
使用数据集作为输入时不支持 tensorflow y 参数
没有为任何变量提供梯度
生成器产生了一个形状为 (50, 50, 3) 的元素,其中一个形状为 (None, None, None, 3) 的元素是预期的
tensorflow 无法转换为 tensorflow dtype
tensorflow 占位符与急切执行不兼容
在尝试有关如何实现生成器的不同解决方案(来自 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())
经过几个小时的努力,我找到了解决方案。我的具体答案采用输入图像,目标是将其放大 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
不接受生成器,而是对函数本身的引用(因此没有参数)。可以在 from_generator
中使用 args=()
,但在我的例子中,数据(路径)被转换为类似字节的对象,所以它对我不起作用。
警告
这只是一个示例,它使用相同的数据进行训练和验证(这很愚蠢)。请在调整此解决方案时为每个使用不同的数据。
培训
conv_model.fit(
train_dataset,
epochs=1,
validation_data=validate_dataset
)
自动分片策略
此工作流程在每个纪元之后(或者在期间,或者在随机时间,真的)产生一条非常长的警告消息,建议关闭自动分片或将 auto_shard_policy 切换到 DATA 以分片数据集。
但这只是一个警告,所以它仍然有效。有一个关于如何禁用它的解决方案:so link
备选
我还找到了另一种方法来完成这项工作。不同之处在于,它必须生成不同类型的输出(元组的元组)。不确定哪种方式是正确的,或者它们是否等价。
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
)
这真的很难弄清楚,希望它能帮助别人。
我一直在寻找解决方案,关于如何使用不同大小的图像作为 NN 的输入。
Numpy
第一个想法是使用 numpy
。但是由于每个图像的大小不同,我无法使用它,因为 tensorflow 不接受 numpy.ndarray
.
尝试简单的 list
也没有用,因为它不受支持。
数据集生成器
尝试使用 yield
实现自定义生成器,但 运行 加载 errors
:
完成 GeneratorDataset 迭代器时出错:已取消:操作已取消
使用数据集作为输入时不支持 tensorflow y 参数
没有为任何变量提供梯度
生成器产生了一个形状为 (50, 50, 3) 的元素,其中一个形状为 (None, None, None, 3) 的元素是预期的
tensorflow 无法转换为 tensorflow dtype
tensorflow 占位符与急切执行不兼容
在尝试有关如何实现生成器的不同解决方案(来自 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())
经过几个小时的努力,我找到了解决方案。我的具体答案采用输入图像,目标是将其放大 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
不接受生成器,而是对函数本身的引用(因此没有参数)。可以在 from_generator
中使用 args=()
,但在我的例子中,数据(路径)被转换为类似字节的对象,所以它对我不起作用。
警告
这只是一个示例,它使用相同的数据进行训练和验证(这很愚蠢)。请在调整此解决方案时为每个使用不同的数据。
培训
conv_model.fit(
train_dataset,
epochs=1,
validation_data=validate_dataset
)
自动分片策略
此工作流程在每个纪元之后(或者在期间,或者在随机时间,真的)产生一条非常长的警告消息,建议关闭自动分片或将 auto_shard_policy 切换到 DATA 以分片数据集。
但这只是一个警告,所以它仍然有效。有一个关于如何禁用它的解决方案:so link
备选
我还找到了另一种方法来完成这项工作。不同之处在于,它必须生成不同类型的输出(元组的元组)。不确定哪种方式是正确的,或者它们是否等价。
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
)
这真的很难弄清楚,希望它能帮助别人。