Эффективный TensorFlow Глава 2. Понимание статических и динамических фигур

TensorFlow

Эта статья переведена с:«Понимание статических и динамических форм», Если есть какое-либо нарушение, пожалуйста, свяжитесь, чтобы удалить его, только для академических обменов, пожалуйста, не используйте его в коммерческих целях. Если есть какие-либо ошибки, пожалуйста, свяжитесь, чтобы указать.

Тензоры в TensorFlow имеют свойство статической формы, которое определяется при построении графа. Статические формы могут быть неопределенными. Например, мы можем определить тензор формы [None, 128]:

import tensorflow as tf
a = tf.placeholder(tf.float32, [None, 128])

Это означает, что первое измерение может быть любого размера и будет вSession.run()Период определяется динамически. Вы можете запросить статическую форму тензора следующим образом:

static_shape = a.shape.as_list()  # returns [None, 128]

Чтобы получить динамическую форму тензора, вы можете вызватьtf.shapeметод, который возвращает форму, представленную данным тензором:

dynamic_shape = tf.shape(a)

можно использоватьTensor.set_shape()Метод задает статическую форму тензора:

a.set_shape([32, 128])  # static shape of a is [32, 128]
a.set_shape([None, 128])  # first dimension of a is determined dynamically

ты можешь использовать этоtf.reshapeФункция динамически изменяет заданный тензор:

a =  tf.reshape(a, [32, 128])

Было бы удобно иметь функцию, которая возвращает статическую форму, когда она доступна, и динамическую форму, когда она недоступна. Лучшая реализация программы выглядит следующим образом:

def get_shape(tensor):
  static_shape = tensor.shape.as_list()
  dynamic_shape = tf.unstack(tf.shape(tensor))
  dims = [s[1] if s[0] is None else s[0]
          for s in zip(static_shape, dynamic_shape)]
  return dims

Теперь предположим, что мы хотим преобразовать 3D-тензор в 2D-тензор, объединив второе и третье измерения в одно. мы можем использоватьget_shape()функция для этого:

b = tf.placeholder(tf.float32, [None, 10, 32])
shape = get_shape(b)
b = tf.reshape(b, [shape[0], shape[1] * shape[2]])

Стоит отметить, что это работает независимо от того, задана ли форма статически или нет.

На самом деле, мы можем написать общийreshape()функция, чтобы свернуть любой список измерений:

import tensorflow as tf
import numpy as np

def reshape(tensor, dims_list):
  shape = get_shape(tensor)
  dims_prod = []
  for dims in dims_list:
    if isinstance(dims, int):
      dims_prod.append(shape[dims])
    elif all([isinstance(shape[d], int) for d in dims]):
      dims_prod.append(np.prod([shape[d] for d in dims]))
    else:
      dims_prod.append(tf.prod([shape[d] for d in dims]))
  tensor = tf.reshape(tensor, dims_prod)
  return tensor

Затем свернуть второе измерение становится очень просто:

b = tf.placeholder(tf.float32, [None, 10, 32])
b = reshape(b, [0, [1, 2]])