【问题标题】:How can I create a Tensor from an Example object in Java?如何从 Java 中的示例对象创建张量?
【发布时间】:2018-01-26 13:19:52
【问题描述】:

我的用例: 我正在尝试使用 libtensorflow_jni 在我们现有的 JVM 服务中提供由 python 训练的模型。

现在我可以使用SavedModelBundle.load() 加载模型。但我发现很难将请求输入模型。因为我的用户请求不仅仅是一个标量矩阵,而是一个特征图,比如:

{'gender':1, 'age': 20, 'country': 100, other features ...}

通过搜索张量流教程,我发现Example 协议缓冲区可能适合这里,因为它基本上包含功能列表。但我不确定如何将其转换为 Java Tensor 对象。

如果我直接使用序列化的示例对象创建张量,TensorFlow 运行时似乎对数据类型不满意。例如,我做以下,

Tensor inputTensor = Tensor.create(example.toByteArray());
s.runner().feed(inputTensorName, inputTensor).fetch(outputTensorName).run().get(0);

我会得到一个 IllegalArgumentException:

java.lang.IllegalArgumentException: Expected serialized to be a vector, got shape: []

如果你碰巧知道或有相同的用例,你们能否阐明我如何从这里继续前进?

谢谢!

【问题讨论】:

    标签: java tensorflow tensorflow-serving


    【解决方案1】:

    查看您的错误消息,问题似乎在于您的模型需要一个字符串张量向量(很可能对应于一批序列化的Example 协议缓冲区消息,可能来自tf.parse_example)但是你'重新给它一个标量弦张量。

    不幸的是,在解析issue #8531 之前,Java API 无法创建除标量之外的字符串Tensor。一旦解决了这个问题,事情就会变得更容易。

    与此同时,您可以通过构建 TensorFlow“模型”将标量字符串转换为大小为 1 的向量来解决此问题 :)。这可以通过以下方式完成:

    // A TensorFlow "model" that reshapes a string scalar into a vector.
    // Should be much prettier once https://github.com/tensorflow/tensorflow/issues/7149
    // is resolved.
    private static class Reshaper implements AutoCloseable {
      Reshaper() {
        this.graph = new Graph();
        this.session = new Session(graph);
        this.in =
            this.graph.opBuilder("Placeholder", "in")
                .setAttr("dtype", DataType.STRING)
                .build()
                .output(0);
        try (Tensor shape = Tensor.create(new int[] {1})) {
          Output vectorShape =
              this.graph.opBuilder("Const", "vector_shape")
                  .setAttr("dtype", shape.dataType())
                  .setAttr("value", shape)
                  .build()
                  .output(0);
          this.out =
              this.graph.opBuilder("Reshape", "out").addInput(in).addInput(vectorShape).build().output(0);
        }
      }
    
      @Override
      public void close() {
        this.session.close();
        this.graph.close();
      }
    
      public Tensor vector(Tensor input) {
        return this.session.runner().feed(this.in, input).fetch(this.out).run().get(0);
      }
    
      private final Graph graph;
      private final Session session;
      private final Output in;
      private final Output out;
    }
    

    通过上述方法,您可以将示例原型张量转换为向量,并将其输入到您感兴趣的模型中,如下所示:

    Tensor inputTensor = null;
    try (Tensor scalar = Tensor.create(example.toByteArray())) {
      inputTensor = reshaper.vector(scalar);
    }
    s.runner().feed(inputTensorName, inputTensor).fetch(outputTensorName).run().get(0);
    

    欲知详情,see this example on github

    希望有帮助!

    【讨论】:

    • 谢谢,这很好用。顺便说一句,你知道我如何从 Tensorflow 返回的张量中读取字符串向量吗?例如,如果 s.runner().fetch(outputTensorName).run().get(0) 返回字符串向量的张量。在 java 中,我没有看到从张量中检索值的 API。
    猜你喜欢
    • 2018-11-04
    • 1970-01-01
    • 2020-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多