Softmax matrix to 0/1 (OneHot) encoded matrix?
Why not combine tf.argmax() with tf.one_hot().
Y = tf.one_hot(tf.argmax(t, dimension = 1), depth = 2)
I have compared five ways to do the conversion with an input shape (20, 256, 256, 4) in TensorFlow 2.1.0, with the following average time per conversion in a 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))
The code used to generate these results is below:
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}")