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.