将每个张量值映射到列表中最接近的值
Map each tensor value to the closest value in a list
我有一个张量 A
,大小为 [batchSize,2,2,2]
,其中 batchSize
是一个占位符。在自定义层中,我想将此张量的每个值映射到长度为 n
的列表 c
中最接近的值。该列表是我的密码本,我想根据这个密码本量化张量中的每个值;即找到列表中每个张量值最接近的值,并用它替换张量值。
我想不出 'clean' 张量运算可以快速做到这一点。我无法循环遍历 batchSize
。在 Tensorflow 中有没有一种方法可以做到这一点?
如果我没理解错的话,tf.HashTable
是可以做到的。作为说明,我使用了 mean=0, stddev=4
.
的正态分布
a = tf.random.normal(
shape = [batch, 2, 2, 2],
mean=0.0,
stddev=4
)
并且我使用了只有 5 个桶的量化(参见标有数字 0、1、2、3、4 的图)。这可以扩展到任何长度 n
。请注意,我故意让桶的长度可变。
因此我的密码本是:
a <= -2 -> bucket 4
-2 < a < -0.5 -> bucket 3
-0.5 <= a < 0.5 -> bucket 0
0.5 <= a < 2.5 -> bucket 1
a >= 2.5 -> bucket 2
这个想法是 pre-create 从缩放的 a
到桶号的 key/value 映射。 (<key,value>
对的数量取决于您需要的输入粒度。这里我缩放了 10)。下面是初始化映射 table 和生成的映射(输入按 10 缩放)的代码。
# The boundary is chosen based on that we clip by min=-4, max=4.
# after scaling, the boundary becomes -40 and 40.
keys = range(-40, 41)
values = []
for k in keys:
if k <= -20:
values.append(4)
elif k < -5:
values.append(3)
elif k < 5:
values.append(0)
elif k < 25:
values.append(1)
else:
values.append(2)
for (k, v) in zip(keys, values):
print ("%2d -> %2d" % (k, v))
-40 -> 4
-39 -> 4
...
-22 -> 4
-21 -> 4
-20 -> 4
-19 -> 3
-18 -> 3
...
-7 -> 3
-6 -> 3
-5 -> 0
-4 -> 0
...
3 -> 0
4 -> 0
5 -> 1
6 -> 1
...
23 -> 1
24 -> 1
25 -> 2
26 -> 2
...
40 -> 2
batch = 3
a = tf.random.normal(
shape = [batch, 2, 2, 2],
mean=0.0,
stddev=4,
dtype=tf.dtypes.float32
)
clip_a = tf.clip_by_value(a, clip_value_min=-4, clip_value_max=4)
SCALE = 10
scaled_clip_a = tf.cast(clip_a * SCALE, tf.int32)
table = tf.contrib.lookup.HashTable(
tf.contrib.lookup.KeyValueTensorInitializer(keys, values), -1)
quantized_a = tf.reshape(
table.lookup(tf.reshape(scaled_clip_a, [-1])),
[batch, 2, 2, 2])
with tf.Session() as sess:
table.init.run()
a, clip_a, scaled_clip_a, quantized_a = sess.run([a, clip_a, scaled_clip_a, quantized_a])
print ('a\n%s' % a)
print ('clip_a\n%s' % clip_a)
print ('scaled_clip_a\n%s' % scaled_clip_a)
print ('quantized_a\n%s' % quantized_a)
结果:
a
[[[[-0.26980758 -5.56331968]
[ 5.04240322 -7.18292665]]
[[-7.11545467 -3.24369478]
[ 1.01861215 -0.04510783]]]
[[[-0.28768024 0.2472897 ]
[ 2.17780781 -5.79106379]]
[[ 8.45582008 4.53902292]
[ 0.138162 -6.19155598]]]
[[[-7.5134449 4.56302166]
[-0.30592337 -0.60313278]]
[[-0.06204566 3.42917275]
[-1.14547718 3.31167102]]]]
clip_a
[[[[-0.26980758 -4. ]
[ 4. -4. ]]
[[-4. -3.24369478]
[ 1.01861215 -0.04510783]]]
[[[-0.28768024 0.2472897 ]
[ 2.17780781 -4. ]]
[[ 4. 4. ]
[ 0.138162 -4. ]]]
[[[-4. 4. ]
[-0.30592337 -0.60313278]]
[[-0.06204566 3.42917275]
[-1.14547718 3.31167102]]]]
scaled_clip_a
[[[[ -2 -40]
[ 40 -40]]
[[-40 -32]
[ 10 0]]]
[[[ -2 2]
[ 21 -40]]
[[ 40 40]
[ 1 -40]]]
[[[-40 40]
[ -3 -6]]
[[ 0 34]
[-11 33]]]]
quantized_a
[[[[0 4]
[2 4]]
[[4 4]
[1 0]]]
[[[0 0]
[1 4]]
[[2 2]
[0 4]]]
[[[4 2]
[0 3]]
[[0 2]
[3 2]]]]
我有一个张量 A
,大小为 [batchSize,2,2,2]
,其中 batchSize
是一个占位符。在自定义层中,我想将此张量的每个值映射到长度为 n
的列表 c
中最接近的值。该列表是我的密码本,我想根据这个密码本量化张量中的每个值;即找到列表中每个张量值最接近的值,并用它替换张量值。
我想不出 'clean' 张量运算可以快速做到这一点。我无法循环遍历 batchSize
。在 Tensorflow 中有没有一种方法可以做到这一点?
如果我没理解错的话,tf.HashTable
是可以做到的。作为说明,我使用了 mean=0, stddev=4
.
a = tf.random.normal(
shape = [batch, 2, 2, 2],
mean=0.0,
stddev=4
)
并且我使用了只有 5 个桶的量化(参见标有数字 0、1、2、3、4 的图)。这可以扩展到任何长度 n
。请注意,我故意让桶的长度可变。
因此我的密码本是:
a <= -2 -> bucket 4
-2 < a < -0.5 -> bucket 3
-0.5 <= a < 0.5 -> bucket 0
0.5 <= a < 2.5 -> bucket 1
a >= 2.5 -> bucket 2
这个想法是 pre-create 从缩放的 a
到桶号的 key/value 映射。 (<key,value>
对的数量取决于您需要的输入粒度。这里我缩放了 10)。下面是初始化映射 table 和生成的映射(输入按 10 缩放)的代码。
# The boundary is chosen based on that we clip by min=-4, max=4.
# after scaling, the boundary becomes -40 and 40.
keys = range(-40, 41)
values = []
for k in keys:
if k <= -20:
values.append(4)
elif k < -5:
values.append(3)
elif k < 5:
values.append(0)
elif k < 25:
values.append(1)
else:
values.append(2)
for (k, v) in zip(keys, values):
print ("%2d -> %2d" % (k, v))
-40 -> 4
-39 -> 4
...
-22 -> 4
-21 -> 4
-20 -> 4
-19 -> 3
-18 -> 3
...
-7 -> 3
-6 -> 3
-5 -> 0
-4 -> 0
...
3 -> 0
4 -> 0
5 -> 1
6 -> 1
...
23 -> 1
24 -> 1
25 -> 2
26 -> 2
...
40 -> 2
batch = 3
a = tf.random.normal(
shape = [batch, 2, 2, 2],
mean=0.0,
stddev=4,
dtype=tf.dtypes.float32
)
clip_a = tf.clip_by_value(a, clip_value_min=-4, clip_value_max=4)
SCALE = 10
scaled_clip_a = tf.cast(clip_a * SCALE, tf.int32)
table = tf.contrib.lookup.HashTable(
tf.contrib.lookup.KeyValueTensorInitializer(keys, values), -1)
quantized_a = tf.reshape(
table.lookup(tf.reshape(scaled_clip_a, [-1])),
[batch, 2, 2, 2])
with tf.Session() as sess:
table.init.run()
a, clip_a, scaled_clip_a, quantized_a = sess.run([a, clip_a, scaled_clip_a, quantized_a])
print ('a\n%s' % a)
print ('clip_a\n%s' % clip_a)
print ('scaled_clip_a\n%s' % scaled_clip_a)
print ('quantized_a\n%s' % quantized_a)
结果:
a
[[[[-0.26980758 -5.56331968]
[ 5.04240322 -7.18292665]]
[[-7.11545467 -3.24369478]
[ 1.01861215 -0.04510783]]]
[[[-0.28768024 0.2472897 ]
[ 2.17780781 -5.79106379]]
[[ 8.45582008 4.53902292]
[ 0.138162 -6.19155598]]]
[[[-7.5134449 4.56302166]
[-0.30592337 -0.60313278]]
[[-0.06204566 3.42917275]
[-1.14547718 3.31167102]]]]
clip_a
[[[[-0.26980758 -4. ]
[ 4. -4. ]]
[[-4. -3.24369478]
[ 1.01861215 -0.04510783]]]
[[[-0.28768024 0.2472897 ]
[ 2.17780781 -4. ]]
[[ 4. 4. ]
[ 0.138162 -4. ]]]
[[[-4. 4. ]
[-0.30592337 -0.60313278]]
[[-0.06204566 3.42917275]
[-1.14547718 3.31167102]]]]
scaled_clip_a
[[[[ -2 -40]
[ 40 -40]]
[[-40 -32]
[ 10 0]]]
[[[ -2 2]
[ 21 -40]]
[[ 40 40]
[ 1 -40]]]
[[[-40 40]
[ -3 -6]]
[[ 0 34]
[-11 33]]]]
quantized_a
[[[[0 4]
[2 4]]
[[4 4]
[1 0]]]
[[[0 0]
[1 4]]
[[2 2]
[0 4]]]
[[[4 2]
[0 3]]
[[0 2]
[3 2]]]]