Должен ли я использовать @ tf.function для всех функций? - PullRequest
8 голосов
/ 21 января 2020

Официальный учебник по @tf.function гласит:

Чтобы получить максимальную производительность и развернуть модель в любом месте, используйте функцию tf.function для создания графиков из ваших программ. , Благодаря AutoGraph, удивительно большое количество Python кода работает только с tf.function, но есть все еще ловушки, которые следует опасаться.

Основные выводы и рекомендации:

  • Не полагайтесь на Python побочные эффекты, такие как объектная мутация или добавление в список.
  • Функция tf.function лучше всего работает с операциями TensorFlow, а не с NumPy операциями или Python примитивами.
  • Если сомневаетесь, используйте идиому for x in y.

В нем упоминается только как для реализации @tf.function аннотированных функций, но не при чтобы использовать его.

Существует ли закон c о том, как решить, следует ли мне хотя бы попытаться аннотировать функцию с помощью tf.function? Кажется, что нет причин не делать этого, если только мне не лень убирать побочные эффекты или изменять некоторые вещи, такие как range() -> tf.range(). Но если я готов сделать это ...

Есть ли причина не использовать @tf.function для всех функций?

Ответы [ 2 ]

4 голосов
/ 30 апреля 2020

TLDR: Это зависит от вашей функции и от того, заняты ли вы производством или разработкой. Не используйте tf.function, если хотите легко отлаживать свою функцию или если она подпадает под ограничения совместимости кода AutoGraph или tf.v1. Я бы настоятельно рекомендовал смотреть выступления Inside TensorFlow о функциях AutoGraph и , а не сессиях .

. Далее я разберу причины, которые все приняты из информации, доступной в Интернете через Google.

Как правило, декоратор tf.function вызывает компиляцию функции как вызываемой, которая выполняет график TensorFlow. Это влечет за собой:

  • Преобразование кода через AutoGraph при необходимости (включая любые функции, вызываемые из аннотированной функции)
  • Отслеживание и выполнение сгенерированного кода графа

За этим стоит подробная информация об идеях дизайна.

Преимущества украшения функции с помощью tf.function

Общие преимущества

  • Ускоренное выполнение , особенно если функция состоит из множества маленьких операций (Источник)

Для функций с Python кодом / Использование AutoGraph через tf.function украшение

Если вы хотите использовать AutoGraph, настоятельно рекомендуется использовать tf.function вместо прямого вызова AutoGraph. Причины этого включают в себя: Automati c управление зависимостями, требуется для некоторых API, больше кэширования и помощников по исключениям (Source) .

Недостатки украшения функции с помощью tf.function

Общие недостатки

  • Если функция состоит только из нескольких дорогих операций, ускорение не будет большим (Источник)

Для функций с Python кодом / Использование AutoGraph через tf.function оформление

  • Нет перехвата исключений (должно выполняться в активном режиме; вне оформленной функции) (Источник)
  • Отладка намного сложнее
  • Ограничения из-за скрытых побочных эффектов и потока управления TF

Доступна подробная информация об ограничениях AutoGraph.

Для функций с кодом tf.v1

  • В tf.function нельзя создавать переменные более одного раза, но это может измениться, так как код tf.v1 поэтапно out (Источник)
* 10 80 * Для функций с кодом tf.v2
  • Без указания c Недостатки

Примеры ограничений

Создание переменных более одного раза

Не разрешается создавать переменные более одного раза, например v в следующем примере:

@tf.function
def f(x):
    v = tf.Variable(1)
    return tf.add(x, v)

f(tf.constant(2))

# => ValueError: tf.function-decorated function tried to create variables on non-first call.

В следующем коде это можно исправить, убедившись, что self.v только создано один раз:

class C(object):
    def __init__(self):
        self.v = None
    @tf.function
    def f(self, x):
        if self.v is None:
            self.v = tf.Variable(1)
        return tf.add(x, self.v)

c = C()
print(c.f(tf.constant(2)))

# => tf.Tensor(3, shape=(), dtype=int32)

Скрытые побочные эффекты, не захваченные AutoGraph

Изменения, например self.a, в этом примере не могут быть скрыты, что приводит к ошибке, поскольку перекрестная функция анализ еще не сделан (пока) (Источник) :

class C(object):
    def change_state(self):
        self.a += 1

    @tf.function
    def f(self):
        self.a = tf.constant(0)
        if tf.constant(True):
            self.change_state() # Mutation of self.a is hidden
        tf.print(self.a)

x = C()
x.f()

# => InaccessibleTensorError: The tensor 'Tensor("add:0", shape=(), dtype=int32)' cannot be accessed here: it is defined in another function or code block. Use return values, explicit Python locals or TensorFlow collections to access it. Defined in: FuncGraph(name=cond_true_5, id=5477800528); accessed from: FuncGraph(name=f, id=5476093776).

Изменения в поле зрения не являются проблемой:

class C(object):
    @tf.function
    def f(self):
        self.a = tf.constant(0)
        if tf.constant(True):
            self.a += 1 # Mutation of self.a is in plain sight
        tf.print(self.a)

x = C()
x.f()

# => 1

Пример ограничения из-за контроля TF flow

Этот оператор if приводит к ошибке, поскольку для управляющего потока TF необходимо определить значение else:

@tf.function
def f(a, b):
    if tf.greater(a, b):
        return tf.constant(1)

# If a <= b would return None
x = f(tf.constant(3), tf.constant(2))   

# => ValueError: A value must also be returned from the else branch. If a value is returned from one branch of a conditional a value must be returned from all branches.
2 голосов
/ 30 апреля 2020

Функция tf.function полезна при создании и использовании вычислительных графиков, их следует использовать при обучении и развертывании, однако она не требуется для большинства ваших функций.

Допустим, мы создаем специальный слой, который будет отделен от более крупной модели. Мы не хотели бы иметь декоратор tf.function над функцией, которая создает этот слой, потому что это просто определение того, как этот слой будет выглядеть.

С другой стороны, давайте скажем, что мы собираемся либо сделайте прогноз, либо продолжите обучение, используя какую-то функцию. Мы бы хотели иметь декоратор tf.function, потому что мы на самом деле используем вычислительный граф для получения некоторого значения.

Отличным примером будет построение модели кодер-декодер. Не помещайте декоратор вокруг функции создания кодера или декодера или любого слоя, это только определение того, что он будет делать. НЕОБХОДИМО поместить декоратор вокруг метода «train» или «Forents», потому что они фактически будут использовать вычислительный граф для вычислений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...