Дублирующее имя узла в графе: 'conv2d_0/kernel/Adam'

Я просто сохранил модель, с помощью этого кода:

def train():    
with tf.Session() as sess:
    saver = tf.train.Saver(max_to_keep = 2)
    Loss = myYoloLoss([Scale1,Scale2,Scale3],[Y1, Y2 ,Y3])
    opt = tf.train.AdamOptimizer(2e-4).minimize(Loss)
    init = tf.global_variables_initializer()
    sess.run(init)
    imageNum = 0
    Num = 0
    while(1):
        #get batchInput
        batchImg,batchScale1,batchScale2,batchScale3 = getBatchImage(batchSize = BATCHSIZE)
        for epoch in range(75):
            _ , epochloss = sess.run([opt,Loss],feed_dict={X:batchImg,Y1:batchScale1,Y2:batchScale2,Y3:batchScale3})
            if(epoch%15 == 0):
                print(epochloss)
        imageNum = imageNum + BATCHSIZE
        Num = Num + 1
        if(Num%4 == 0):
            saver.save(sess,MODELPATH + 'MyModle__' + str(imageNum))            
        if(os.path.exists(STOPFLAGPATH)):
            saver.save(sess,MODELPATH + 'MyModle__Stop_' + str(imageNum))   
            print('checked stopfile,stop')
            break
return 0

И тогда я получаю несколько файлов:
MyModle__Stop_288.index
MyModle__Stop_288.meta
MyModle__Stop_288.data-00000-оф-00001
контрольно-пропускной пункт
Тогда я хочу продолжить обучение этой модели.

def reTrain():
with tf.Session() as sess:
    loder = tf.train.import_meta_graph('E:/MyYoloModel/MyModle__Stop_288.meta')
    loder.restore(sess, tf.train.latest_checkpoint('E:/MyYoloModel/'))
    graph = tf.get_default_graph()
    X = graph.get_tensor_by_name("X:0")
    Y1 = graph.get_tensor_by_name("Y1:0")
    Y2 = graph.get_tensor_by_name("Y2:0")
    Y3 = graph.get_tensor_by_name("Y3:0")
    Scale1 = graph.get_tensor_by_name("Scale1:0")
    Scale2 = graph.get_tensor_by_name("Scale2:0")
    Scale3 = graph.get_tensor_by_name("Scale3:0")  
    Loss = myYoloLoss([Scale1,Scale2,Scale3],[Y1, Y2 ,Y3])
    #error code 
    opt = tf.train.AdamOptimizer(2e-4).minimize(Loss)
    init = tf.global_variables_initializer()
    sess.run(init)
    batchImg,batchScale1,batchScale2,batchScale3 = getBatchImage(batchSize = BATCHSIZE)
    for epoch in range(10):
        _ ,epochloss = sess.run([opt,Loss],feed_dict={X:batchImg,Y1:batchScale1,Y2:batchScale2,Y3:batchScale3})
        print(epochloss)

И будет возникать эта ошибка: ValueError: Дубликат имени узла в графе: 'conv2d_0/kernel/Adam'
Как это можно исправить?

4 ответа

У меня была аналогичная ошибка:

ValueError: Duplicate node name in graph: 'packed/0'

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

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

это тривиальное решение смогло устранить проблему

Причина в том, что AdamOptimizer создает дополнительные переменные и операции на вашем графике. Когда вы сохраняете свою модель, эти операции сохраняются и загружаются вместе с графиком при восстановлении модели. Если ты бежишь

tf.Graph.get_operations(график)

вы можете увидеть список операций, которые загружены с вашей моделью. Вы увидите операции, в которых есть /Adam или train /Adam init. Когда вы пытаетесь найти-настроить или повторно использовать вашу модель, новый AdamOptimizer пытается снова создать эти операции, поэтому выдает ошибку "Повторяющееся имя узла". Один из способов решить эту проблему - дать имя вашему новому AdampOptimzer.

opt = tf.train.AdamOptimizer(2e-4m name='MyNewAdam'). Minimize(Потеря)

Однако мы еще не закончили. Поскольку вы хотите повторно использовать вес, вы не можете инициализировать переменную. Однако, если вы получите ошибку неинициализированных параметров при запуске обучения, которая возникает из-за новых переменных AdamOptimizer, которые еще не были инициализированы. Чтобы обойти это, вам нужно инициализировать эти новые переменные:

uninitialized_vars = []
for var in tf.all_variables():
    try:
        sess.run(var)
    except tf.errors.FailedPreconditionError:
        uninitialized_vars.append(var)

tf.initialize_variables(uninitialized_vars)

Примечание: неиспользуемые узлы не будут выполняться и, следовательно, не повлияют на время обучения.

Я также столкнулся с этой проблемой и решил ее, изменив код в моей виртуальной среде: venv\Lib\site-packages\tensorflow_core\python\framework\ops.py Там есть метод под названием "unique_name". Этот метод иногда допускает ошибки при создании имен. Особенно, когда он использует свой name_stack. Чтобы исправить это, я изменил метод и добавил небольшой метод splitAndSet, который решил проблему:

def splitAndSet(self, name, iInt):
#=================== Method splitAndSet =====================
    nameList = re.split("/", name)
    for nInt in range(len(nameList)):
        nameList[nInt] = "%s_%d" % (nameList[nInt], iInt)
    return "/".join(nameList)
#=============== END Method splitAndSet =====================

def unique_name(self, name, mark_as_used=True):
    if self._name_stack:
        name = self._name_stack + "/" + name

    # For the sake of checking for names in use, we treat names as case
    # insensitive (e.g. foo = Foo).
    name = self.splitAndSet(name, 0)
    name_key = self.splitAndSet(name.lower(), 0)
    i = self._names_in_use.get(name_key, 0)
    # Increment the number for "name_key".
    if mark_as_used:
        self._names_in_use[name_key] = i + 1
    if i > 0:
        base_name_key = name_key
        # Make sure the composed name key is not already used.
        while name_key in self._names_in_use:
            #name_key = "%s_%d" % (base_name_key, i)
            name_key = self.splitAndSet(base_name_key, i)
            i += 1
      # Mark the composed name_key as used in case someone wants
      # to call unique_name("name_1").
    if mark_as_used:
        self._names_in_use[name_key] = 1

    # Return the new name with the original capitalization of the given name.
    #name = "%s_%d" % (name, i - 1)
    name = self.splitAndSet(name, i - 1)
return name

Чтобы дать некоторый контекст того, как я получил эту ошибку, я пытался преобразовать веса даркнета в модель TensorFlow, следуя этому руководству. Я получил эту ошибку из-за следующего фрагмента кода:

      flags.DEFINE_string('output', './checkpoints/yolov4-416', 'path to output') 

Я указал неправильный путь в приведенном выше коде, мне потребовалось много времени, чтобы понять это после того, как я попробовал так много решений Stackoverflow. Это так тривиально, но я надеюсь, что это поможет кому-то застрять на этой ошибке.

Другие вопросы по тегам