TensorFlow:numpy.repeat()替代方案

问题描述 投票:36回答:9

我想以成对的方式比较我的神经网络中的预测值yp,所以我正在使用(回到我原来的numpy实现中):

idx = np.repeat(np.arange(len(yp)), len(yp))
jdx = np.tile(np.arange(len(yp)), len(yp))
s = yp[[idx]] - yp[[jdx]]

这基本上创建了一个索引网格,然后我使用它。 idx=[0,0,0,1,1,1,...],而jdx=[0,1,2,0,1,2...]。我不知道是否有更简单的做法...

无论如何,TensorFlow有一个tf.tile(),但它似乎缺乏tf.repeat()

idx = np.repeat(np.arange(n), n)
v2 = v[idx]

我收到错误:

TypeError: Bad slice index [  0   0   0 ..., 215 215 215] of type <type 'numpy.ndarray'>

使用TensorFlow常量进行索引也无效:

idx = tf.constant(np.repeat(np.arange(n), n))
v2 = v[idx]

-

TypeError: Bad slice index Tensor("Const:0", shape=TensorShape([Dimension(46656)]), dtype=int64) of type <class 'tensorflow.python.framework.ops.Tensor'>

我的想法是将我的RankNet实现转换为TensorFlow。

tensorflow
9个回答
35
投票

你可以使用np.repeat()tf.tile()的组合来达到tf.reshape()的效果:

idx = tf.range(len(yp))
idx = tf.reshape(idx, [-1, 1])    # Convert to a len(yp) x 1 matrix.
idx = tf.tile(idx, [1, len(yp)])  # Create multiple columns.
idx = tf.reshape(idx, [-1])       # Convert back to a vector.

你可以使用jdx简单地计算tf.tile()

jdx = tf.range(len(yp))
jdx = tf.tile(jdx, [len(yp)])

对于索引,您可以尝试使用tf.gather()yp张量中提取非连续切片:

s = tf.gather(yp, idx) - tf.gather(yp, jdx)

2
投票

看起来你的问题是如此受欢迎,人们refer it on TF tracker。遗憾的是,TF中仍然没有实现相同的功能。

你可以通过组合tf.tiletf.reshapetf.squeeze来实现它。这是一种从np.repeat转换示例的方法:

import numpy as np
import tensorflow as tf

x = [[1,2],[3,4]]
print np.repeat(3, 4)
print np.repeat(x, 2)
print np.repeat(x, 3, axis=1)

x = tf.constant([[1,2],[3,4]])
with tf.Session() as sess:
    print sess.run(tf.tile([3], [4]))
    print sess.run(tf.squeeze(tf.reshape(tf.tile(tf.reshape(x, (-1, 1)), (1, 2)), (1, -1))))
    print sess.run(tf.reshape(tf.tile(tf.reshape(x, (-1, 1)), (1, 3)), (2, -1)))

在最后一种情况下,每个元素的重复不同,你最有可能需要loops


2
投票

对于一维张量,我已经完成了这个功能

def tf_repeat(y,repeat_num)   
        return tf.reshape(tf.tile(tf.expand_dims(y,axis=-1),[1,repeat_num]),[-1]) 

1
投票

以防任何人对2D方法复制矩阵感兴趣。我认为这可行:

TF_obj = tf.zeros([128, 128])
tf.tile(tf.expand_dims(TF_obj, 2), [1, 1, 2])

1
投票
import numpy as np
import tensorflow as tf
import itertools    

x = np.arange(6).reshape(3,2)
x = tf.convert_to_tensor(x)
N = 3 # number of repetition
K = x.shape[0] # for here 3

order = list(range(0, N*K, K))
order = [[x+i for x in order] for i in range(K)]
order = list(itertools.chain.from_iterable(order))
x_rep = tf.gather(tf.tile(x, [N, 1]), order)

结果来自:

   [0, 1],
   [2, 3],
   [4, 5]]

至:

  [[0, 1],
   [0, 1],
   [0, 1],
   [2, 3],
   [2, 3],
   [2, 3],
   [4, 5],
   [4, 5],
   [4, 5]]

如果你想:

  [[0, 1],
   [2, 3],
   [4, 5],
   [0, 1],
   [2, 3],
   [4, 5],
   [0, 1],
   [2, 3],
   [4, 5]]

只需使用tf.tile(x, [N, 1])


1
投票

根据tf api documenttf.keras.backend.repeat_elements()np.repeat()做同样的工作。例如,

x = tf.constant([1, 3, 3, 1], dtype=tf.float32)
rep_x = tf.keras.backend.repeat_elements(x, 5, axis=0)
# result: [1. 1. 1. 1. 1. 3. 3. 3. 3. 3. 3. 3. 3. 3. 3. 1. 1. 1. 1. 1.]

0
投票

您可以通过tf.repeating自身模拟缺少的tf.stack

value = np.arange(len(yp))  # what to repeat
repeat_count = len(yp)      # how many times
repeated = tf.stack ([value for i in range(repeat_count)], axis=1)

我建议仅在小重复计数时使用它。


0
投票

虽然已经给出了许多干净且有效的解决方案,但它们似乎都是基于每次迭代从头开始生成索引集。

虽然在培训期间生成这些节点的成本通常不显着,但如果使用您的模型进行推理可能会很重要。

重复tf.range(就像你的例子)已经出现了几次,所以我构建了以下函数创建器。给定重复某些事物的最大次数以及需要重复的最大事物数量,它返回一个与np.repeat(np.arange(len(multiples)), multiples)产生相同值的函数。

import tensorflow as tf
import numpy as np


def numpy_style_repeat_1d_creator(max_multiple=100, max_to_repeat=10000):
    board_num_lookup_ary = np.repeat(
        np.arange(max_to_repeat),
        np.full([max_to_repeat], max_multiple))
    board_num_lookup_ary = board_num_lookup_ary.reshape(max_to_repeat, max_multiple)

    def fn_to_return(multiples):
        board_num_lookup_tensor = tf.constant(board_num_lookup_ary, dtype=tf.int32)
        casted_multiples = tf.cast(multiples, dtype=tf.int32)
        padded_multiples = tf.pad(
            casted_multiples,
            [[0, max_to_repeat - tf.shape(multiples)[0]]])

        return tf.boolean_mask(
            board_num_lookup_tensor,
            tf.sequence_mask(padded_multiples, maxlen=max_multiple))

    return fn_to_return

#Here's an example of how it can be used
with tf.Session() as sess:
    repeater = numpy_style_repeat_1d_creator(5,4)
    multiples = tf.constant([4,1,3])

    repeated_values = repeater(multiples)
    print(sess.run(repeated_values))

一般的想法是存储一个重复的张量,然后掩盖它,但它可能有助于在视觉上看到它(这是上面给出的例子):

In the example above the following Tensor is produced:
[[0,0,0,0,0],
 [1,1,1,1,1],
 [2,2,2,2,2],
 [3,3,3,3,3]]

For multiples [4,1,3] it will collect the non-X values:
[[0,0,0,0,X],
 [1,X,X,X,X],
 [2,2,2,X,X],
 [X,X,X,X,X]]

resulting in:
[0,0,0,0,1,2,2,2]

tl; dr:为了避免每次产生指数(可能代价高昂),预先重复所有内容然后每次掩盖该张量


0
投票

relatively fast实现最近添加了1.13的RaggedTensor实用程序,但它不是正式导出的API的一部分。你仍然可以使用它,但它有可能会消失。

from tensorflow.python.ops.ragged.ragged_util import repeat

从源代码:

# This op is intended to exactly match the semantics of numpy.repeat, with
# one exception: numpy.repeat has special (and somewhat non-intuitive) behavior
# when axis is not specified.  Rather than implement that special behavior, we
# simply make `axis` be a required argument.
© www.soinside.com 2019 - 2024. All rights reserved.