2016-02-17 2 views
12

У меня есть изображение, которое составляет 478 x 717 x 3 = 1028178 пикселей, с рангом 1. Я проверил его, вызвав tf.shape и tf.rank.Уточнение на tf.Tensor.set_shape()

Когда я вызываю image.set_shape ([478, 717, 3]), он выдает следующую ошибку.

"Shapes %s and %s must have the same rank" % (self, other)) 
ValueError: Shapes (?,) and (478, 717, 3) must have the same rank 

Я проверил еще раз, выполнив первое литье до 1028178, но ошибка все еще существует.

ValueError: Shapes (1028178,) and (478, 717, 3) must have the same rank 

Ну, это имеет смысл, потому что один имеет ранг 1, а другой имеет ранг 3. Однако, почему необходимо бросить ошибку, так как общее количество пикселей по-прежнему совпадают.

Я мог бы, конечно, использовать tf.resape, и это работает, но я думаю, что это не оптимально.

Как указано на TensorFlow FAQ

В чем разница между x.set_shape() и х = tf.reshape (х)?

Метода tf.Tensor.set_shape() обновляет статическую форму тензорной объекта, и он, как правило, используется, чтобы обеспечить дополнительную информацию ФОРМЫ, когда это не может быть выведено непосредственно. Он не меняет динамическую форму тензора.

Операция tf.reshape() создает новый тензор с другой динамической формой.

Создание нового тензора связано с распределением памяти и потенциально может быть более дорогостоящим, когда задействованы дополнительные примеры обучения. Это по дизайну, или я что-то пропустил?

+1

Реальный вопрос заключается в том, изменил ли тензор Тензорный буфер данных с оригинальным тензором или выполнил ли он копию. Я не мог сказать из быстрого чтения кода, но если он делает копию, это то, что должно быть исправлено. –

+0

mrry выяснил, что это мелкая копия в его ответе ниже. – jkschin

ответ

34

Насколько я знаю (и я написал этот код), в Tensor.set_shape() нет ошибки. Я думаю, что недоразумение проистекает из запутанного имени этого метода.

Выработать на FAQ entry you quoted, Tensor.set_shape() является чисто Python функции, которая улучшает информации формы для данного tf.Tensor объекта. «Улучшает», я имею в виду «делает более конкретным».

Таким образом, если у вас есть Tensor объект t с формой (?,), то есть одномерный тензор неизвестной длины. Вы можете позвонить t.set_shape((1028178,)), а затем t будет иметь форму (1028178,), когда вы позвоните t.get_shape(). Это не влияет на лежащую в основе хранения, да и вообще что-либо на внутреннем интерфейсе: это просто означает, что после вывода формы с помощью t может опираться на утверждение, что вектор длины 1028178.

t If имеет форму (?,), вызов t.set_shape((478, 717, 3)) не удастся, потому что TensorFlow уже знает, что t - это вектор, поэтому он не может иметь форму (478, 717, 3). Если вы хотите создать новый тензор с этой формой из содержимого t, вы можете использовать reshaped_t = tf.reshape(t, (478, 717, 3)). Это создает новый объект tf.Tensor в Python; фактический implementation of tf.reshape() делает это, используя мелкую копию тензорного буфера, поэтому на практике это недорого.

Одна из аналогий заключается в том, что Tensor.set_shape() похож на время выполнения на объектно-ориентированном языке, таком как Java. Например, если у вас есть указатель на Object, но знаете, что на самом деле это String, вы можете сделать листинг (String) obj, чтобы передать obj методу, ожидающему аргумент String. Однако если у вас есть s и попробуйте отправить его на java.util.Vector, компилятор даст вам ошибку, потому что эти два типа не связаны.

+0

Большое вам спасибо за подробный ответ! – jkschin

Смежные вопросы