代码之家  ›  专栏  ›  技术社区  ›  Ujjwal

使用tf。cond()为训练和验证提供图形

  •  1
  • Ujjwal  · 技术社区  · 8 年前

    在我的TensorFlow代码中,我希望我的网络从其中一个获取输入 StagingArea 对象,这取决于我是想进行培训还是测试。 我编写的图形构造代码的一部分如下:

    with tf.device("/gpu:0"):
          for i in range(numgpus):
              with tf.variable_scope(tf.get_variable_scope(), reuse=i>0) as vscope:
                  with tf.device('/gpu:{}'.format(i)):
                      with tf.name_scope('GPU-Tower-{}'.format(i)) as scope:
                          phase = tf.get_variable("phase", [], initializer=tf.zeros_initializer(),dtype=tf.uint8, trainable=False)
                          phaseassigntest = phase.assign(1)
                          phaseassigntrain = phase.assign(0)
                          phasetest = tf.equal(phase, 0)
                          is_training = tf.cond(phasetest, lambda: tf.constant(True), lambda: tf.constant(False))
    
                          trainstagingarea = tf.contrib.staging.StagingArea([tf.float32, tf.int32], shapes=[[trainbatchsize, 3, 221, 221], [trainbatchsize]], capacity=20)
                          putoptrain = trainstagingarea.put(train_iterator.get_next())
                          trainputop.append(putoptrain)
                          getoptrain = trainstagingarea.get()
                          traingetop.append(getoptrain)
                          trainclearop = trainstagingarea.clear()
                          trainstageclear.append(trainclearop)
                          trainsizeop = trainstagingarea.size()
                          trainstagesize.append(trainsizeop)
    
                          valstagingarea = tf.contrib.staging.StagingArea([tf.float32, tf.int32], shapes=[[valbatchsize, 3, 221, 221], [valbatchsize]], capacity=20)
                          putopval = valstagingarea.put(val_iterator.get_next())
                          valputop.append(putopval)
                          getopval = valstagingarea.get()
                          valgetop.append(getopval)
                          valclearop = valstagingarea.clear()
                          valstageclear.append(valclearop)
                          valsizeop = valstagingarea.size()
                          valstagesize.append(valsizeop)
    
    
                          #elem = valgetop[i]
                          elem = tf.cond(is_training,lambda: traingetop[i],lambda: valgetop[i])
    
                          img = elem[0]
                          label = elem[1]
                          labelonehot = tf.one_hot(label, depth=numclasses)
                          net, networksummaries =  overfeataccurate(img,numclasses=numclasses, phase=is_training)
    

    tf.cond 确保网络由其中一个供电 阶段性区域 物体。一个用于培训,另一个用于验证。

    with tf.Session(graph=g,config=config) as sess:
        sess.run(init_op)
        sess.run(tf.local_variables_initializer())
        sess.run(val_initialize)
        for i in range(20):
            sess.run(valputop)
            print(sess.run(valstagesize))
        writer = tf.summary.FileWriter('.', graph=tf.get_default_graph())
        epoch = 0
        iter = 0
        print("Performing Validation")
        sess.run(phaseassigntest)
        saver = tf.train.Saver()
        while(epoch<10):
            time_init = time.time()
            while True:
                try:
                    [val_accu, _, summaries] = sess.run([towervalidation, towervalidationupdateop,validation_summary_op])
                    print(val_accu)
    

    何时而不是 tf.cond() 我直接分配 elem = valgetop[i] ,代码运行良好。

    基于我是想进行培训还是测试,给我的网络提供信息的正确方式是什么?

    注释 numgpus 到1。

    1 回复  |  直到 8 年前
        1
  •  3
  •   Multihunter bmu    7 年前

    你的问题

    你怎么想 tf.cond

    根据该标志,执行将traingetop[i]或valgetop[i]放入 elem 张量。

    tf。康德 实际上是这样的

    执行获取所需的内容 二者都 元素 张量。

    所以

    它永远挂起的原因是因为它正在等待一个元素添加到您的训练暂存区域(以便它可以获取该元素并将其丢弃)。原谅你没有意识到这是它在做什么;这实际上非常违反直觉。文档是 非常 不清楚如何应对。


    推荐解决方案(通过Tensorflow文档)

    如果您确实需要队列位于同一个图中,那么您需要制作整个图的两个副本,一个由您的训练暂存区提供,另一个由您的验证暂存区提供。然后你只需要在你的 sess.run 呼叫我建议创建一个函数,该函数采用队列输出张量,并返回 model_output 张量。现在你有一个 train_time_output 张量和a validation_time_output 张量,你可以选择在你的 sess。跑

    你需要确保你实际上没有创建新的变量来配合这些新的操作。待办事项 variables . 看起来他们已经将其从v0.12简化了,基本上可以归结为使用 tf.get_variable 而不是 tf.Variable


    我喜欢的工作环境

    虽然这是推荐的解决方案(AFAIK),但对我来说非常不满意;你在图上创建了一整套操作,恰好使用了相同的权重。通过滥用训练时间和测试/验证时间之间的分离,似乎存在很大的程序员错误的可能性(导致模型在这些时间的行为出乎意料地不同)。更糟的这并不能解决 tf。康德 要求两个分支的输入值,这只会迫使您复制整个图形,这并不总是可能的。

    我不希望我的队列像那样出现在图中,而是将模型视为一个函数,它可以提供一个示例,而不管它来自哪里。也就是说,我将用一个 tf.placeholder feed_dict 实际提供价值。它的功能是这样的

    #inside main training loop
    if time_to_train:
        example = sess.run(traingettop)
    else:
        example = sess.run(valgettop)
    result = sess.run(model_output, {input_placeholder: example})
    

    tf。康德

    a = tf.constant(some_value)
    b = tf.placeholder(tf.float32)
    flag = tf.placeholder(tf.bool, [])
    one_of_them = tf.cond(flag, a, b)
    model_output = build_graph(one_of_them)
    

    进入一个不这样的定义,比如:

    a = tf.constant(some_value)
    model_output = build_graph(a)
    

    a 在执行时:

    # In main training loop,
    sess.run(train_op, {a: some_other_value})
    

    if condition_satisfied:
        sess.run(train_op, {a:some_other_value})
    else:
        sess.run(train_op)
    

    性能问题

    几乎没有性能成本 对于此解决方案,当numpy阵列放入 example

    如果您以分布式方式使用tensorflow,那么此解决方案将破坏您的性能;它需要将示例从其所在的任何机器发送到主机,以便它可以将其发送回。

    推荐文章