【问题标题】:implement N-hot encoding in tf.slim在 tf.slim 中实现 N-hot 编码
【发布时间】:2018-11-09 00:45:47
【问题描述】:

如何根据 tf.int64 中 1 的索引实现 N-hot 编码?输入是包含几个 tf.int64 的张量。 N-hot 编码旨在替代 tf.slim 中的 one-hot 编码。

one_hot 编码实现如下:

def dense_to_one_hot(labels_dense, num_classes):
  """Convert class labels from scalars to one-hot vectors."""
  num_labels = labels_dense.shape[0]
  index_offset = numpy.arange(num_labels) * num_classes
  labels_one_hot = numpy.zeros((num_labels, num_classes))
  labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
  return labels_one_hot

N-not encoding表示:19=00010011,编码后的结果为[0,0,0,1,0,0,1,1]。

【问题讨论】:

  • N 是否始终是图构建时已知的常数值,还是可能是另一个 TensorFlow 操作的结果?

标签: numpy tensorflow encoding one-hot-encoding


【解决方案1】:

在下面找到@jdehesa 的一个很好的答案。此版本计算位长N 本身(但仅适用于单值张量 - 或包含相同位长值的张量):

import tensorflow as tf

def logn(x, n):
  numerator = tf.log(x)
  denominator = tf.log(tf.cast(n, dtype=numerator.dtype))
  return numerator / denominator

def count_bits(x):
    return tf.cast((logn(tf.cast(x, dtype=tf.float32), 2)) + 1, dtype=x.dtype)

def n_hot_encode(x):
    """
    Unpack an integer into its variable-length bit representation
    :param x: Int tensor of shape ()
    :return:  Bool tensor of shape (N,) with N = bit length of x
    """
    N = count_bits(x)
    bins = tf.bitwise.left_shift(1, tf.range(N))[::-1]
    x_unpacked = tf.reshape(tf.bitwise.bitwise_and(x, bins), [-1])
    x_bits = tf.cast(x_unpacked, dtype=tf.bool)
    return x_bits

with tf.Session() as sess:
    result = sess.run(n_hot_encode(tf.constant(19)))
    print(result)
    # > [ True False False  True  True]
    result = sess.run(n_hot_encode(tf.constant(255)))
    print(result)
    # > [ True  True  True  True  True  True  True  True]

上一个答案:

使用tf.one_hot()

labels_one_hot = tf.one_hot(labels_dense, num_classes)

【讨论】:

  • tf.one_hot 只编码一个热点。这不是我的意思。
  • 好吧,我可能搞糊涂了。我假设您想将您的 numpy 代码转换为 TF。你能否在你的问题中澄清你所说的“N-hot encoding”(例如使用伪代码或numpy)是什么意思?
  • 比如19=00010011,编码后的结果是[0,0,0,1,0,0,1,1]
  • 我用@jdehesa 的答案的替代方法更新了我的答案(取决于您的用例)
【解决方案2】:

这是一种解决方案:

import numpy as np
import tensorflow as tf

def n_hot_encoding(a, n):
    a = tf.convert_to_tensor(a)
    m = 1 << np.arange(n)[::-1]
    shape = np.r_[np.ones(len(a.shape), dtype=int), -1]
    m = m.reshape(shape)
    hits = tf.bitwise.bitwise_and(a[..., tf.newaxis], tf.cast(m, a.dtype))
    return tf.not_equal(hits, 0)


with tf.Graph().as_default(), tf.Session() as sess:
    n_hot = n_hot_encoding([19, 20, 21], 10)
    print(sess.run(tf.cast(n_hot, tf.int32)))

输出:

[[0 0 0 0 0 1 0 0 1 1]
 [0 0 0 0 0 1 0 1 0 0]
 [0 0 0 0 0 1 0 1 0 1]]

它假定N 是一个常规标量(不是TensorFlow 值)并且要转换的数组的维数是已知的(每个维的大小可以是动态的,但a.shape 不应该是只是None)。该函数可以像这样适用于仅 TensorFlow 的计算:

import tensorflow as tf

def n_hot_encoding(a, n):
    a = tf.convert_to_tensor(a)
    n = tf.convert_to_tensor(n)
    m = tf.bitwise.left_shift(1, tf.range(n)[::-1])
    shape = tf.concat([tf.ones([tf.rank(a)], dtype=tf.int64), [-1]], axis=0)
    m = tf.reshape(m, shape)
    hits = tf.bitwise.bitwise_and(a[..., tf.newaxis], tf.cast(m, a.dtype))
    return tf.not_equal(hits, 0)

这应该适用于任何输入,但可能会在每次图形运行时做更多的额外工作。

【讨论】:

  • 太棒了!但输出是布尔值。 slim.one_hot_encoding 的输出是 tf.float32。
  • @T.Wang 你可以使用tf.cast(n_hot, tf.float32)在函数内部或外部强制转换它。
  • 这不是@jdehesa 的热门编码吗?或者 n 热编码恰好是当您定义编码的长度时,例如预定义的 10?
  • @Nihat One-hot 编码意味着例如将[1, 3, 2] 转换为[[0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]。 OP 在这里想要的基本上是获取每个数字的每一位,所以 [1, 3, 2](二进制 [0b01, 0b11, 0b10])可能是 [[0, 1], [1, 1], [1, 0]]
  • @jdehesa 有道理,谢谢。但是我在文献中看到了 N 热编码的用法,找不到任何清楚的东西。您能否告诉我在这种情况下 N 热编码将如何发生?说 2 或 4 个热编码?
猜你喜欢
  • 2019-06-28
  • 2022-01-10
  • 2018-03-24
  • 1970-01-01
  • 2016-11-15
  • 2023-01-16
  • 1970-01-01
  • 2021-02-16
  • 1970-01-01
相关资源
最近更新 更多