【问题标题】:Softmax matrix to 0/1 (OneHot) encoded matrix?Softmax矩阵到0/1(一个热)编码矩阵?
【发布时间】:2016-12-03 22:02:57
【问题描述】:

假设我有以下张量 t 作为 softmax 函数的输出:

t = tf.constant(value=[[0.2,0.8], [0.6, 0.4]])
>> [ 0.2,  0.8]
   [ 0.6,  0.4]

现在我想将此矩阵 t 转换为类似于 OneHot 编码矩阵的矩阵:

Y.eval()
>> [   0,    1]
   [   1,    0]

我熟悉c = tf.argmax(t),这会给我t 的每行索引应该是1。但是从cY 似乎相当困难。

我已经尝试过使用ct 转换为tf.SparseTensor,然后使用tf.sparse_tensor_to_dense() 得到Y。但是这种转换涉及相当多的步骤,而且对于这项任务来说似乎有些过头了——我什至还没有完全完成它,但我相信它可以工作。

有没有更合适/更简单的方法来进行我所缺少的这种转换。

我需要这个的原因是因为我在 Python 中有一个自定义的 OneHot 编码器,我可以在其中输入 Ytf.one_hot() 不够广泛 - 不允许自定义编码。

相关问题:

【问题讨论】:

    标签: python tensorflow softmax


    【解决方案1】:

    我比较了五种在 TensorFlow 2.1.0 中使用输入形状(20、256、256、4)进行转换的方法,在 Quadro RTX 8000 中每次转换的平均时间如下。

    one_hot-argmax (0.802 us):

        y = tf.one_hot(tf.argmax(x, axis=3), x.shape[3])
    

    cast-reduce_max(0.719 us):

    y = tf.cast(tf.equal(x, tf.reduce_max(x, axis=3, keepdims=True)),
                tf.float32)
    

    cast-tile-reduce_max (0.862 us)

    y = tf.cast(tf.equal(x, tf.tile(tf.reduce_max(x, axis=3, keepdims=True),
                                    [1, 1, 1, x.shape[3]])),
                tf.float32)
    

    where-reduce_max (1.850 us):

    y = tf.where(tf.equal(x, tf.reduce_max(x, axis=3, keepdims=True)),
                 tf.constant(1., shape=x.shape),
                 tf.constant(0., shape=x.shape))
    

    where-tile-reduce_max (1.691 us):

    y = tf.where(tf.equal(x, tf.tile(tf.reduce_max(x, axis=3, keepdims=True),
                                     [1, 1, 1, x.shape[3]])),
                 tf.constant(1., shape=x.shape),
                 tf.constant(0., shape=x.shape))
    

    用于生成这些结果的代码如下:

    import time
    import tensorflow as tf
    
    shape = (20, 256, 256, 4)
    N = 1000
    
    def one_hot():
        for i in range(N):
            x = tf.random.normal(shape)
            x = tf.nn.softmax(tf.random.normal(shape), axis=3)
            x = tf.one_hot(tf.argmax(x, axis=3), x.shape[3])
        return None
        
    def cast_reduce_max():
        for i in range(N):
            x = tf.random.normal(shape)
            x = tf.nn.softmax(tf.random.normal(shape), axis=3)
            x = tf.cast(tf.equal(x, tf.reduce_max(x, axis=3, keepdims=True)),
                        tf.float32)
        return None
    
    def cast_tile():
        for i in range(N):
            x = tf.random.normal(shape)
            x = tf.nn.softmax(tf.random.normal(shape), axis=3)
            x = tf.cast(tf.equal(x, tf.tile(tf.reduce_max(x, axis=3, keepdims=True), [1, 1, 1, x.shape[3]])),
                        tf.float32)
        return None    
        
    def where_reduce_max():
        for i in range(N):
            x = tf.random.normal(shape)
            x = tf.nn.softmax(tf.random.normal(shape), axis=3)
            x = tf.where(tf.equal(x, tf.reduce_max(x, axis=3, keepdims=True)),
                         tf.constant(1., shape=x.shape),
                         tf.constant(0., shape=x.shape))
        return None
    
    def where_tile():
        for i in range(N):
            x = tf.random.normal(shape)
            x = tf.nn.softmax(tf.random.normal(shape), axis=3)
            x = tf.where(tf.equal(x, tf.tile(tf.reduce_max(x, axis=3, keepdims=True), [1, 1, 1, x.shape[3]])),
                         tf.constant(1., shape=x.shape),
                         tf.constant(0., shape=x.shape))
        return None
    
    def blank():
        for i in range(N):
            x = tf.random.normal(shape)
            x = tf.nn.softmax(tf.random.normal(shape), axis=3)
        return None
    
    t0 = time.time()
    one_hot()
    print(f"one_hot:\t{time.time()-t0}")    
    
    t0 = time.time()
    cast_reduce_max()
    print(f"cast_reduce_max:\t{time.time()-t0}")
    
    t0 = time.time()
    cast_tile()
    print(f"cast_tile:\t{time.time()-t0}")
    
    t0 = time.time()
    where_reduce_max()
    print(f"where_reduce_max:\t{time.time()-t0}")
    
    t0 = time.time()
    where_tile()
    print(f"where_tile:\t{time.time()-t0}")
    
    t0 = time.time()
    blank()
    print(f"blank:\t{time.time()-t0}")
    

    【讨论】:

      【解决方案2】:

      为什么不将 tf.argmax() 与 tf.one_hot() 结合起来。

      Y = tf.one_hot(tf.argmax(t, dimension = 1), depth = 2)

      【讨论】:

      • 这太明显了!真的因为没有早点看到而感到很傻。我认为你是对的。尽管tf.one_hot() 是用于分类而不是为索引分配 1,但考虑到指定的深度,它似乎确实在执行后者(根据我的有限测试)。谢谢!
      猜你喜欢
      • 2022-08-05
      • 2020-11-27
      • 2013-02-28
      • 2011-12-24
      • 1970-01-01
      • 2018-05-05
      • 2023-03-03
      • 2013-12-12
      • 2020-06-01
      相关资源
      最近更新 更多