Tensorflow,在另一个tf.estimator model_fn中使用tf.estimator训练的模型

时间:2018-04-29 08:06:46

标签: python tensorflow

有没有办法在另一个模型B中使用tf.estimator训练的模型A?

这是情况, 假设我有一个训练有素的模型A'使用model_a_fn()。 '模型A'获取图像作为输入,并输出一些类似于MNIST分类器的向量浮动值。 还有另一个'模型B'在model_b_fn()中定义。 它还将图像作为输入,并且需要矢量输出'模型A'在培训'模型B'。

基本上我想训练'模型B'需要输入作为图像&预测输出'模型A'。 (不再需要训练'模型A'只是为了在训练时获得预测输出'模型B')

我已经尝试过三种情况:

  1. 在model_b_fn()
  2. 中使用估算对象('模型A')
  3. 已导出'模型A'使用tf.estimator.export_savedmodel(),并创建预测函数。用params dict将它传递给model_b_fn()。
  4. 与2相同,但恢复'模型A'在model_b_fn()
  5. 但所有案例都显示错误:

    1. ...必须与...相同的图表。
    2. TypeError:无法挑选_thread.RLock对象
    3. TypeError:Feed的值不能是tf.Tensor对象。
    4. 这是我用过的代码......只附上重要的部分

      train_model_a.py

      def model_a_fn(features, labels, mode, params):
          # ...
          # ...
          # ...
          return
      
      def main():
          # model checkpoint location
          model_a_dir = './model_a'
      
          # create estimator for Model A
          model_a = tf.estimator.Estimator(model_fn=model_a_fn, model_dir=model_a_dir)
      
          # train Model A
          model_a.train(input_fn=lambda : input_fn_a)
          # ...
          # ...
          # ...
      
          # export model a
          model_a.export_savedmodel(model_a_dir, serving_input_receiver_fn=serving_input_receiver_fn)
          # exported to ./model_a/123456789
          return
      
      if __name__ == '__main__':
          main()
      

      train_model_b_case_1.py

      # follows model_a's input format
      def bypass_input_fn(x):
          features = {
              'x': x,
          }
          return features
      
      def model_b_fn(features, labels, mode, params):
          # parse input
          inputs = tf.reshape(features['x'], shape=[-1, 28, 28, 1])
      
          # get Model A's response
          model_a = params['model_a']
          predictions = model_a.predict(
              input_fn=lambda: bypass_input_fn(inputs)
          )
          for results in predictions:
              # Error occurs!!!
              model_a_output = results['class_id']
      
          # build Model B
          layer1 = tf.layers.conv2d(inputs, 32, 5, same, activation=tf.nn.relu)
          layer1 = tf.layers.max_pooling2d(layer1, pool_size=[2, 2], strides=2)
      
          # ...
          # some layers added...
          # ...
      
          flatten = tf.layers.flatten(prev_layer)
          layern = tf.layers.dense(10)
      
          # let say layern's output shape and model_a_output's output shape is same
          add_layer = tf.add(flatten, model_a_output)
      
          # ...
          # do more... stuff
          # ...
          return
      
      def main():
          # load pretrained model A
          model_a_dir = './model_a'
          model_a = tf.estimator.Estimator(model_fn=model_a_fn, model_dir=model_a_dir)
      
          # model checkpoint location
          model_b_dir = './model_b/'
      
          # create estimator for Model A
          model_b = tf.estimator.Estimator(
              model_fn=model_b_fn,
              model_dir=model_b_dir,
              params={
                  'model_a': model_a,
              }
          )
      
          # train Model B
          model_b.train(input_fn=lambda : input_fn_b)
          return
      
      if __name__ == '__main__':
          main()
      

      train_model_b_case_2.py

      def model_b_fn(features, labels, mode, params):
          # parse input
          inputs = tf.reshape(features['x'], shape=[-1, 28, 28, 1])
      
          # get Model A's response
          model_a_predict_fn = params['model_a_predict_fn']
          model_a_prediction = model_a_predict_fn(
              {
                  'x': inputs
              }
          )
          model_a_output = model_a_prediction['output']
      
          # build Model B
          layer1 = tf.layers.conv2d(inputs, 32, 5, same, activation=tf.nn.relu)
          layer1 = tf.layers.max_pooling2d(layer1, pool_size=[2, 2], strides=2)
      
          # ...
          # some layers added...
          # ...
      
          flatten = tf.layers.flatten(prev_layer)
          layern = tf.layers.dense(10)
      
          # let say layern's output shape and model_a_output's output shape is same
          add_layer = tf.add(flatten, model_a_output)
      
          # ...
          # do more... stuff
          # ...
          return
      
      def main():
          # load pretrained model A
          model_a_dir = './model_a/123456789'
          model_a_predict_fn = tf.contrib.predictor.from_saved_model(export_dir=model_a_dir)
      
          # model checkpoint location
          model_b_dir = './model_b/'
      
          # create estimator for Model A
          # Error occurs!!!
          model_b = tf.estimator.Estimator(
              model_fn=model_b_fn,
              model_dir=model_b_dir,
              params={
                  'model_a_predict_fn': model_a_predict_fn,
              }
          )
      
          # train Model B
          model_b.train(input_fn=lambda : input_fn_b)
          return
      
      if __name__ == '__main__':
          main()
      

      train_model_b_case_3.py

      def model_b_fn(features, labels, mode, params):
          # parse input
          inputs = tf.reshape(features['x'], shape=[-1, 28, 28, 1])
      
          # get Model A's response
          model_a_predict_fn = tf.contrib.predictor.from_saved_model(export_dir=params['model_a_dir'])
          # Error occurs!!!
          model_a_prediction = model_a_predict_fn(
              {
                  'x': inputs
              }
          )
          model_a_output = model_a_prediction['output']
      
          # build Model B
          layer1 = tf.layers.conv2d(inputs, 32, 5, same, activation=tf.nn.relu)
          layer1 = tf.layers.max_pooling2d(layer1, pool_size=[2, 2], strides=2)
      
          # ...
          # some layers added...
          # ...
      
          flatten = tf.layers.flatten(prev_layer)
          layern = tf.layers.dense(10)
      
          # let say layern's output shape and model_a_output's output shape is same
          add_layer = tf.add(flatten, model_a_output)
      
          # ...
          # do more... stuff
          # ...
          return
      
      def main():
          # load pretrained model A
          model_a_dir = './model_a/123456789'
      
          # model checkpoint location
          model_b_dir = './model_b/'
      
          # create estimator for Model A
          # Error occurs!!!
          model_b = tf.estimator.Estimator(
              model_fn=model_b_fn,
              model_dir=model_b_dir,
              params={
                  'model_a_dir': model_a_dir,
              }
          )
      
          # train Model B
          model_b.train(input_fn=lambda : input_fn_b)
          return
      
      if __name__ == '__main__':
          main()
      

      所以在另一个tf.estimator中使用经过培训的自定义tf.estimator的任何想法都可以吗?

1 个答案:

答案 0 :(得分:0)

我已经找到解决这个问题的一种方法。

如果遇到相同的问题,可以使用此方法。

  1. 创建一个运行tensorflow.contrib.predictor.from_saved_model()的函数->将其称为'pretrained_predictor()'
  2. 在模型B的model_fn()中,在预定义的'pretrained_predictor()'上方调用tensorflow.py_func()

例如,请参见https://github.com/moono/tf-cnn-mnist/blob/master/4_3_estimator_within_estimator.py以获取简单的用例。