我想以成对的方式比较我的神经网络中的预测值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。
你可以使用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)
看起来你的问题是如此受欢迎,人们refer it on TF tracker。遗憾的是,TF中仍然没有实现相同的功能。
你可以通过组合tf.tile,tf.reshape,tf.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。
对于一维张量,我已经完成了这个功能
def tf_repeat(y,repeat_num)
return tf.reshape(tf.tile(tf.expand_dims(y,axis=-1),[1,repeat_num]),[-1])
以防任何人对2D方法复制矩阵感兴趣。我认为这可行:
TF_obj = tf.zeros([128, 128])
tf.tile(tf.expand_dims(TF_obj, 2), [1, 1, 2])
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])
根据tf api document,tf.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.]
您可以通过tf.repeat
ing自身模拟缺少的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)
我建议仅在小重复计数时使用它。
虽然已经给出了许多干净且有效的解决方案,但它们似乎都是基于每次迭代从头开始生成索引集。
虽然在培训期间生成这些节点的成本通常不显着,但如果使用您的模型进行推理可能会很重要。
重复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:为了避免每次产生指数(可能代价高昂),预先重复所有内容然后每次掩盖该张量
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.