Ответ 1
Иногда форма тензора зависит от значения, которое вычисляется во время выполнения. Возьмем следующий пример, где x
определяется как вектор tf.placeholder()
с четырьмя элементами:
x = tf.placeholder(tf.int32, shape=[4])
print x.get_shape()
# ==> '(4,)'
Значение x.get_shape()
- статическая форма x
, а (4,
) означает, что это вектор длины 4. Теперь применим tf.unique()
op to x
y, _ = tf.unique(x)
print y.get_shape()
# ==> '(?,)'
(?,)
означает, что y
- вектор неизвестной длины. Почему это неизвестно? tf.unique(x)
возвращает уникальные значения из x
, а значения x
неизвестны, так как это tf.placeholder()
, поэтому не имеет значения, пока вы его не загрузите. Посмотрите, что произойдет, если вы загрузите два разных значения:
sess = tf.Session()
print sess.run(y, feed_dict={x: [0, 1, 2, 3]}).shape
# ==> '(4,)'
print sess.run(y, feed_dict={x: [0, 0, 0, 0]}).shape
# ==> '(1,)'
Надеюсь, это даст понять, что тензор может иметь другую статическую и динамическую форму. Динамическая форма всегда полностью определена — она не имеет размеров ?
&mdash, но статическая форма может быть менее конкретной. Это позволяет TensorFlow поддерживать такие операции, как tf.unique()
и tf.dynamic_partition()
, которые могут иметь выходы с переменным размером и использоваться в расширенных приложениях.
Наконец, tf.shape()
op можно использовать для получения динамической формы тензора и использования его в вычислении TensorFlow:
z = tf.shape(y)
print sess.run(z, feed_dict={x: [0, 1, 2, 3]})
# ==> [4]
print sess.run(z, feed_dict={x: [0, 0, 0, 0]})
# ==> [1]