2016-11-28 5 views
1

Я понял, что есть некоторые напуганные вещи, связанные с тем, как Tensorflow, похоже, управляет графиками.Как Tensorflow управляет графиками?

Поскольку модели зданий (и перестройки) настолько утомительны, я решил обернуть свою собственную модель в классе, чтобы я мог легко повторно создать ее в другом месте.

Когда я тренировал и тестировал код (в исходном месте), он работал бы отлично, однако в коде, где я загружал переменные графа, я получал всевозможные странные ошибки - переменные переопределения и все остальное. Это (из моего последнего вопроса о подобной вещи) было намеком на то, что все вызывается дважды.

После выполнения TON трассировки, это сводилось к тому, как я использовал загруженный код. Он используется внутри класса, который имел структуру, как так

class MyModelUser(object): 
    def forecast(self): 
     # .. build the model in the same way as in the training code 
     # load the model checkpoint 
     # call the "predict" function on the model 
     # manipulate the prediction and return it 

А потом в какой-то код, который использует MyModelUser я имел

def test_the_model(self): 
    model_user = MyModelUser() 
    print(model_user.forecast()) # 1 
    print(model_user.forecast()) # 2 

и я (очевидно) ожидал увидеть два прогноза, когда это назывался. Вместо этого, первый прогноз был вызван и работал, как и ожидалось, но второй вызов бросил TON переменной повторного использования ValueError пример одного из них был:

ValueError: Variable weight_def/weights already exists, disallowed. Did you mean to set reuse=True in VarScope? 

мне удалось подавить ошибки, добавив ряд блоков try/except, которые использовали get_variable для создания переменной, а затем в качестве исключения, называемой reuse_variables, а затем get_variable без названия. Это привело на новый набор неприятных ошибок, один из которых был:

tensorflow.python.framework.errors.NotFoundError: Tensor name "weight_def/weights/Adam_1" not found in checkpoint files 

На прихоти я сказал «что если перенести код моделирования здания в __init__ поэтому его только построили один раз?»

Мой новый пользователь модель:

class MyModelUser(object): 
    def __init__(self): 
     # ... build the model in the same way as in the training code 
     # load the model checkpoint 


    def forecast(self): 
     # call the "predict" function on the model 
     # manipulate the prediction and return it 

и теперь:

def test_the_model(self): 
    model_user = MyModelUser() 
    print(model_user.forecast()) # 1 
    print(model_user.forecast()) # 2 

работает, как ожидалось, печать двух прогнозов без ошибок. Это заставляет меня поверить, что я также могу избавиться от переименования переменных.

Мой вопрос заключается в следующем:

Почему это исправить? Теоретически граф должен быть восстановлен каждый раз в исходном методе предсказания, поэтому он не должен создавать более одного графика. Сохраняет ли Tensorflow график даже после завершения функции? Именно поэтому сработал код создания до __init__? Это оставило меня безнадежно запутанным.

ответ

2

По умолчанию TensorFlow использует один глобальный экземпляр tf.Graph, созданный при первом вызове API TensorFlow.Если вы не создадите явно tf.Graph, все операции, тензоры и переменные будут созданы в этом экземпляре по умолчанию. Это означает, что каждый вызов вашего кода до model_user.forecast() будет добавлять операции к одному и тому же глобальному графику, что несколько расточительно.

Есть (по крайней мере) два возможных направления действий здесь:

  • Идеальное действие было бы перестроить свой код так, что MyModelUser.__init__() строит целую tf.Graph со всеми операциями, необходимыми для осуществления прогнозирования, и MyModelUser.forecast() просто выполняет sess.run() звонки по существующему графику. В идеале вы бы создали только один tf.Session, потому что TensorFlow кэширует информацию о графике в сеансе, и выполнение будет более эффективным.

  • Менее инвазивные — но, вероятно, менее эффективный — изменение будет создавать новый tf.Graph для каждого вызова MyModelUser.forecast(). Неясно от вопроса, как создается много состояния в методе MyModelUser.__init__(), но вы могли бы сделать что-то вроде следующего, чтобы поместить два вызова в разных графах:

    def test_the_model(self): 
        with tf.Graph(): # Create a local graph 
        model_user_1 = MyModelUser() 
        print(model_user_1.forecast()) 
        with tf.Graph(): # Create another local graph 
        model_user_2 = MyModelUser() 
        print(model_user_2.forecast()) 
    
0

TF имеет график по умолчанию, в который добавляются новые операции и т. Д. Когда вы дважды вызываете свою функцию, вы добавите те же самые вещи дважды к одному и тому же графу. Итак, постройте график один раз и оцените его несколько раз (как вы это делали, что также является «нормальным»), или, если вы хотите что-то изменить, вы можете использовать reset_default_graph https://www.tensorflow.org/versions/r0.11/api_docs/python/framework.html#reset_default_graph, чтобы сбросить график, чтобы свежее состояние.

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