首页 文章

如何根据Tensorflow队列中的张量属性(“过采样”)来复制输入张量?

提问于
浏览
1

我正在为我自己的目的移植Tensorflow Cifar-10教程文件,并且由于Tensorflow的图形和会话架构而遇到了一个我无法轻易概念化的有趣问题 .

问题是我的输入数据集是高度不 balancer 的,因此我需要在输入管道中以条件为标签对其进行某些图像处理 . 在普通的Python环境中,我可以设置一个形式为 if label then duplicate 的简单控制流语句,但是我无法在Tensorflow中编写相同的语法,因为在正在运行的会话之外存在控制流操作,而 label 在这种情况下不会返回一个值 .

我的问题是,在Tensorflow队列中过度采样张量的最简单方法是什么?

我知道我可以在输入操作之前简单地复制感兴趣的数据,但这显然可以消除运行时过采样所带来的任何存储节省 .

我想要做的是评估Tensor 's label (in the Cifar-10 case, by checking the 1D image.label attribute) and then duplicate that Tensor by a fixed factor (say, 4x if the label is 2511945 ) and send all the Tensors down to the batching operation. My original approach was to attempt the duplication step after the Reader operation and before the batching operation, but this too is outside of a running session. I was thinking of utilizing TF' s while 控制流语句,但我不确定这个函数是否能够执行除修改输入Tensor之外的任何操作 . 你怎么看?


更新#1

基本上我试图创建一个py_func(),它接受展平的图像字节和标签字节,并根据标签的值垂直堆叠相同的图像字节N次,然后将其作为(N x image_bytes)张量返回( py_func()自动将输入张量转换为numpy和back) . 我试图从变量高度张量创建一个input_queue,其形状报告为(?,image_bytes),然后实例化一个读取器以撕掉image_byte大小的记录 . 好吧,你似乎无法 Build 未知数据大小的队列,所以这种方法对我来说不起作用,事后才有意义,但我仍然无法概念化识别队列中记录的方法,并重复该记录具体次数 .


更新#2

好吧48小时后我终于想出了一个解决方法,多亏了this SO thread我能够挖掘出来 . 该线程中概述的解决方案仅假设2类数据,因此 tf.cond() 函数足以在 pred 为True时对一个类进行过采样,如果 pred 为False则对其他类进行过采样 . 为了得到一个n路条件,我试图 Build 一个导致 ValueError: Cannot infer Tensor's ranktf.case() 函数 . 事实证明, tf.case() 函数不保留 shape 属性,并且图形构造失败,因为输入管道末端的任何批处理操作必须采用形状参数,或者采用定义形状的张量,如documentation中的此注释所示:

N.B . :您必须确保(i)形状参数通过,或(ii)张量中的所有张量必须具有完全定义的形状 . 如果这些条件都不成立,则会引发ValueError .

进一步的挖掘表明这是一个known issue,其中 tf.case() 尚未在2016年12月得到解决 . 这只是Tensorflow众多控制流程中的一个 . 无论如何,我对n路过采样问题的精简解决方案是:

# Initiate a queue of "raw" input data with embedded Queue Runner.
queue = tf.train.string_input_producer(rawdata_filename) 

# Instantiate Reader Op to read examples from files in the filename queue.
reader = tf.FixedLengthRecordReader(record_bytes)

# Pull off one instance, decode and cast image and label to 3D, 1D Tensors.
result.key, value = reader.read(queue)
image_raw, label_raw = decode(value)
image = tf.cast(image_raw, dtype) #3D tensor
label = tf.cast(label_raw, dtype) #1D tensor

# Assume your oversampling factors per class are fixed
# and you have 4 classes.
OVERSAMPLE_FACTOR = [1,2,4,10]

# Now we need to reshape input image tensors to 4D, where the 
# first dimension is the image number in a batch of oversampled tensors.
# images = tf.expand_dims(image, 0) # so, (*,height,width,channels) in 4D

# Set up your predicates, which are 1D boolean tensors.
# Note you will have to squash the boolean tensors to 0-dimension.
# This seems illogical to me, but it is what it is.
pred0 = tf.reshape(tf.equal(label, tf.convert_to_tensor([0])), []) #0D tf.bool
pred1 = tf.reshape(tf.equal(label, tf.convert_to_tensor([1])), []) #0D tf.bool
pred2 = tf.reshape(tf.equal(label, tf.convert_to_tensor([2])), []) #0D tf.bool
pred3 = tf.reshape(tf.equal(label, tf.convert_to_tensor([3])), []) #0D tf.bool

# Build your callables (functions) that vertically stack an input image and
# label tensors X times depending on the accompanying oversample factor.
def f0(): return tf.concat(0, [images]*OVERSAMPLE_FACTOR[0]), tf.concat(0, [label]*OVERSAMPLE_FACTOR[0])
def f1(): return tf.concat(0, [images]*OVERSAMPLE_FACTOR[1]), tf.concat(0, [label]*OVERSAMPLE_FACTOR[1])
def f2(): return tf.concat(0, [images]*OVERSAMPLE_FACTOR[2]), tf.concat(0, [label]*OVERSAMPLE_FACTOR[2])
def f3(): return tf.concat(0, [images]*OVERSAMPLE_FACTOR[3]), tf.concat(0, [label]*OVERSAMPLE_FACTOR[3])

# Here we have N conditionals, one for each class.  These are exclusive
# but due to tf.case() not behaving every conditional gets evaluated.
[images, label] = tf.cond(pred0, f0, lambda: [images,label])
[images, label] = tf.cond(pred1, f1, lambda: [images,label])
[images, label] = tf.cond(pred2, f2, lambda: [images,label])
[images, label] = tf.cond(pred3, f3, lambda: [images,label])

# Pass the 4D batch of oversampled tensors to a batching op at the end
# of the input data queue.  The batching op must be set up to accept
# batches of tensors (4D) as opposed to individual tensors (in our case, 3D).
images, label_batch = tf.train.batch([images, label],
                                     batch_size=batch_size,
                                     num_threads=num_threads,
                                     capacity=capacity,
                                     enqueue_many = True) #accept batches

1 回答

  • 1

    我的问题的解决方案是一种解决方法,并在原始问题的“更新2”中进行了概述 .

相关问题