这里记录论文END-TO-END OPTIMIZED IMAGE COMPRESSION相关代码报错的记录(我这里运行的tensorflow1.15版本对应的代码) github:https://github.com/tensorflow/compression 数据集用的是imagenet的验证集
1、cuda设备问题
tensorflow.python.framework.errors_impl.InvalidArgumentError: Invalid device ordinal value (1). Valid range is [0, 0].
while setting up XLA_GPU_JIT device number 1
解决方法 最后在命令前面加上CUDA_VISIBLE_DEVICE:
CUDA_VISIBLE_DEVICES=0 python bls2017.py --verbose train --train_glob="/home/ll/END-TO-END-OPTIMIZED-IMAGE-COMPRESSION/image/*JPEG"
或者在代码中加入
import os
os.environ['CUDA_VISIBLE_DEVICES']='0'
2、参数范围错误(实际解决问题,参见问题3)
tensorflow.python.framework.errors_impl.InvalidArgumentError: {{function_node __inference_Dataset_map_<lambda>_122}} assertion failed: [Need value.shape >= size, got ] [230 170 3] [256 256 3]
[[{{node random_crop/Assert/Assert}}]]
[[IteratorGetNext]]
这个问题一般是由于设置的参数范围错误的问题 tf.random_crop随机地将张量裁剪为给定的大小,以一致选择的偏移量将一个形状 size 部分从 value 中切出,需要的条件:value.shape >= size. 而这里实际剪裁的图片没有最后剪裁的大小大
这里我自己的做法是(有更好的欢迎补充):
''' 添加获取原图片进行剪裁的方法,以免原图片小于剪裁后的大小'''
def getXValue (x, args):
x_shape = tf.shape(x)
if x_shape[0] > args.patchsize:
x_value = tf.random_crop(x, (args.patchsize, args.patchsize, 3))
else:
x_value = x
return x_value
train_dataset = train_dataset.map(
lambda x: getXValue(x, args))
3、层名称与层不兼容问题
ValueError: in converted code:
bls2017.py:97 call *
tensor = layer(tensor)
/home/ll/.conda/envs/TF115GPU/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/base_layer.py:819 __call__
self.name)
/home/ll/.conda/envs/TF115GPU/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/input_spec.py:165 assert_input_compatibility
layer_name + ' is incompatible with the layer: '
ValueError: Input 0 of layer layer_0 is incompatible with the layer: its rank is undefined, but the layer requires a defined rank.
出现这个问题发现问题2不能这样解决,我们在预处理的裁剪过程中必须保证图片尺寸固定256256,所以必须挑选出图片尺寸大于256256的图片进行操作
4、将图片反向排序,取后8000个
size_files = sorted(glob.glob(args.train_glob), key=os.path.getsize)
print(len(size_files), 'len(size_files)')
reversed_files = size_files[len(size_files)-8000:len(size_files)]
train_dataset = tf.data.Dataset.from_tensor_slices(reversed_files)
train_dataset = train_dataset.shuffle(buffer_size=len(reversed_files)).repeat()
train_dataset = train_dataset.map(
read_png, num_parallel_calls=args.preprocess_threads)
train_dataset = train_dataset.map(
lambda x: tf.random_crop(x, (args.patchsize, args.patchsize, 3)))
train_dataset = train_dataset.batch(args.batchsize)
train_dataset = train_dataset.prefetch(32)
5、重新改造问题2、3、4
峰回路转,倒序取8000个还是有图片尺寸不达标,如果再减少取得数量,可能导致损失函数不收敛,而且治标不治本,所以我打算过滤出达标的图片。
虽然想的很简单,但是博主从来没接触过过tensorflow,一步步来吧 (1)首先我们从目标文件路径读取到了以文件路径表示的list:train_files
train_files = glob.glob(args.train_glob)
if not train_files:
raise RuntimeError(
"No training images found with glob '{}'.".format(args.train_glob))
(2)截取排序后的8000个元素组成的list
size_files = sorted(glob.glob(args.train_glob), key=os.path.getsize)
reversed_files = size_files[len(size_files)-8000:len(size_files)]
这里顺便验证一下排序 按大小降序,第一个文件对应我们排序后的list的最后一个元素 (3)通过tf.data.Dataset.from_tensor_slices创建dataset 这里部分基础知识可以通过tensorflow理解
train_dataset = tf.data.Dataset.from_tensor_slices(reversed_files)
train_dataset = train_dataset.shuffle(buffer_size=len(reversed_files)).repeat()
train_dataset = train_dataset.map(read_png, num_parallel_calls=args.preprocess_threads)
因为不知道转换后的dataset中的元素是什么样的,所以我们进行读取(每个读取1个元素)
iterator = train_dataset.make_one_shot_iterator()
one_element = iterator.get_next()
with tf.Session() as sess:
for i in range(1):
print(sess.run(one_element))
经过(1)
train_dataset = tf.data.Dataset.from_tensor_slices(reversed_files)
经过(2) 是一个重复的操作
经过(3)
train_dataset = train_dataset.map(read_png, num_parallel_calls=args.preprocess_threads)
iterator = train_dataset.make_one_shot_iterator()
one_element = iterator.get_next()
with tf.Session() as sess:
for i in range(1):
print(sess.run(one_element), '3333333333')
print(tf.shape(sess.run(one_element)), 'shape11111')
print(len(sess.run(one_element)), 'sess.run(one_element).len')
也就是说这个张量的最外维度的长度对应图片的长,每一层维度的长对应宽图片的宽。
(4)添加一个过滤函数(在裁剪之前)
train_dataset = train_dataset.filter(lambda x: filterImg(x, args))
def filterImg (x, args):
x_shape = tf.shape(x)
print(x_shape, 'x_shape')
print(len(x), 'x.len')
这里我们先看看打印的数据类型,在进行修改 这里进来的x好像和之前打印的张量不一样,具体看看dataset.filter这个方法
未解之谜: 通过在dataset.filter调用函数,根本没有办法拿到x的值,显示属性为空,但是如果直接在dataset.filter中使用判断就可以了,有没有大神看到可以解答一下,感激不尽
train_dataset = train_dataset.filter(lambda x: len(x) > args.patchsize)
|