如何将输入数据传递给现有的 TensorFlow 2.x 模型(使用 Java)?

huangapple go评论111阅读模式
英文:

How to pass input data to an existing tensorflow 2.x model in Java?

问题

以下是翻译好的部分:

  1. 我正在使用`tensorflow`迈出我的第一步在使用PythonMNIST数据创建了一个简单的模型之后我现在想将这个模型导入Java并在分类中使用它然而我无法将输入数据传递给模型
  2. 这是用于模型创建的Python代码
  3. from tensorflow.keras.datasets import mnist
  4. from tensorflow.keras.utils import to_categorical
  5. (train_images, train_labels), (test_images, test_labels) = mnist.load_data()
  6. train_images = train_images.reshape((60000, 28, 28, 1))
  7. train_images = train_images.astype('float32')
  8. train_images /= 255
  9. test_images = test_images.reshape((10000, 28, 28, 1))
  10. test_images = test_images.astype('float32')
  11. test_images /= 255
  12. train_labels = to_categorical(train_labels)
  13. test_labels = to_categorical(test_labels)
  14. NrTrainimages = train_images.shape[0]
  15. NrTestimages = test_images.shape[0]
  16. import os
  17. import numpy as np
  18. from tensorflow.keras.callbacks import TensorBoard
  19. from tensorflow.keras.models import Sequential
  20. from tensorflow.keras.layers import Dense, Dropout, Flatten
  21. from tensorflow.keras.layers import Conv2D, MaxPooling2D
  22. from tensorflow.keras import backend as K
  23. # 网络结构
  24. model = Sequential()
  25. mnist_inputshape = train_images.shape[1:4]
  26. # 卷积块1
  27. model.add(Conv2D(32, kernel_size=(5,5),
  28. activation = 'relu',
  29. input_shape=mnist_inputshape,
  30. name = 'Input_Layer'))
  31. model.add(MaxPooling2D(pool_size=(2,2)))
  32. # 卷积块2
  33. model.add(Conv2D(64, kernel_size=(5,5),activation= 'relu'))
  34. model.add(MaxPooling2D(pool_size=(2,2)))
  35. model.add(Dropout(0.5))
  36. # 预测块
  37. model.add(Flatten())
  38. model.add(Dense(128, activation='relu', name='features'))
  39. model.add(Dropout(0.5))
  40. model.add(Dense(64, activation='relu'))
  41. model.add(Dense(10, activation='softmax', name = 'Output_Layer'))
  42. model.compile(loss='categorical_crossentropy',
  43. optimizer='Adam',
  44. metrics=['accuracy'])
  45. LOGDIR = "logs"
  46. my_tensorboard = TensorBoard(log_dir = LOGDIR,
  47. histogram_freq=0,
  48. write_graph=True,
  49. write_images=True)
  50. my_batch_size = 128
  51. my_num_classes = 10
  52. my_epochs = 5
  53. history = model.fit(train_images, train_labels,
  54. batch_size=my_batch_size,
  55. callbacks=[my_tensorboard],
  56. epochs=my_epochs,
  57. use_multiprocessing=False,
  58. verbose=1,
  59. validation_data=(test_images, test_labels))
  60. score = model.evaluate(test_images, test_labels)
  61. modeldir = 'models'
  62. model.save(modeldir, save_format = 'tf')

对于Java,我试图调整在此处发布的App.java代码。

我正在努力替换这个片段:

  1. Tensor result = s.runner()
  2. .feed("input_tensor", inputTensor)
  3. .feed("dropout/keep_prob", keep_prob)
  4. .fetch("output_tensor")
  5. .run().get(0);

在这段代码中,使用了特定的输入张量来传递数据,而在我的模型中,只有层,没有单独的命名张量。因此,以下代码无法工作:

  1. Tensor<?> result = s.runner()
  2. .feed("Input_Layer/kernel", inputTensor)
  3. .fetch("Output_Layer/kernel")
  4. .run().get(0);

我应该如何在Java中传递数据并获取模型的输出?

  1. <details>
  2. <summary>英文:</summary>
  3. I&#39;m doing my first steps with `tensorflow`. After having created a simple model for MNIST data in Python, I now want to import this model into Java and use it for classification. However, I don&#39;t manage to pass the input data to the model.
  4. Here is the Python code for model creation:
  5. from tensorflow.keras.datasets import mnist
  6. from tensorflow.keras.utils import to_categorical.
  7. (train_images, train_labels), (test_images, test_labels) = mnist.load_data()
  8. train_images = train_images.reshape((60000, 28, 28, 1))
  9. train_images = train_images.astype(&#39;float32&#39;)
  10. train_images /= 255
  11. test_images = test_images.reshape((10000, 28, 28, 1))
  12. test_images = test_images.astype(&#39;float32&#39;)
  13. test_images /= 255
  14. train_labels = to_categorical(train_labels)
  15. test_labels = to_categorical(test_labels)
  16. NrTrainimages = train_images.shape[0]
  17. NrTestimages = test_images.shape[0]
  18. import os
  19. import numpy as np
  20. from tensorflow.keras.callbacks import TensorBoard
  21. from tensorflow.keras.models import Sequential
  22. from tensorflow.keras.layers import Dense, Dropout, Flatten
  23. from tensorflow.keras.layers import Conv2D, MaxPooling2D
  24. from tensorflow.keras import backend as K
  25. # Network architecture
  26. model = Sequential()
  27. mnist_inputshape = train_images.shape[1:4]
  28. # Convolutional block 1
  29. model.add(Conv2D(32, kernel_size=(5,5),
  30. activation = &#39;relu&#39;,
  31. input_shape=mnist_inputshape,
  32. name = &#39;Input_Layer&#39;))
  33. model.add(MaxPooling2D(pool_size=(2,2)))
  34. # Convolutional block 2
  35. model.add(Conv2D(64, kernel_size=(5,5),activation= &#39;relu&#39;))
  36. model.add(MaxPooling2D(pool_size=(2,2)))
  37. model.add(Dropout(0.5))
  38. # Prediction block
  39. model.add(Flatten())
  40. model.add(Dense(128, activation=&#39;relu&#39;, name=&#39;features&#39;))
  41. model.add(Dropout(0.5))
  42. model.add(Dense(64, activation=&#39;relu&#39;))
  43. model.add(Dense(10, activation=&#39;softmax&#39;, name = &#39;Output_Layer&#39;))
  44. model.compile(loss=&#39;categorical_crossentropy&#39;,
  45. optimizer=&#39;Adam&#39;,
  46. metrics=[&#39;accuracy&#39;])
  47. LOGDIR = &quot;logs&quot;
  48. my_tensorboard = TensorBoard(log_dir = LOGDIR,
  49. histogram_freq=0,
  50. write_graph=True,
  51. write_images=True)
  52. my_batch_size = 128
  53. my_num_classes = 10
  54. my_epochs = 5
  55. history = model.fit(train_images, train_labels,
  56. batch_size=my_batch_size,
  57. callbacks=[my_tensorboard],
  58. epochs=my_epochs,
  59. use_multiprocessing=False,
  60. verbose=1,
  61. validation_data=(test_images, test_labels))
  62. score = model.evaluate(test_images, test_labels)
  63. modeldir = &#39;models&#39;
  64. model.save(modeldir, save_format = &#39;tf&#39;)
  65. For `Java`, I am trying to adapt the `App.java` code published [here][1].
  66. I am struggling with replacing this snippet:
  67. Tensor result = s.runner()
  68. .feed(&quot;input_tensor&quot;, inputTensor)
  69. .feed(&quot;dropout/keep_prob&quot;, keep_prob)
  70. .fetch(&quot;output_tensor&quot;)
  71. .run().get(0);
  72. While in this code, a particular input tensor is used to pass the data, in my model, there are only layers and no individual named tensors. Thus, the following doesn&#39;t work:
  73. Tensor&lt;?&gt; result = s.runner()
  74. .feed(&quot;Input_Layer/kernel&quot;, inputTensor)
  75. .fetch(&quot;Output_Layer/kernel&quot;)
  76. .run().get(0);
  77. How do I pass the data to and get the output from my model in Java?
  78. [1]: https://github.com/kalaspuffar/tensorflow-mnist-test/tree/master/src/main/java/org/ea/tensorflow
  79. </details>
  80. # 答案1
  81. **得分**: 1
  82. 我终于成功找到了解决方法。为了获取图中的所有张量名称,我使用了以下代码:
  83. ```java
  84. for (Iterator it = smb.graph().operations(); it.hasNext();) {
  85. Operation op = (Operation) it.next();
  86. System.out.println("Operation name: " + op.name());
  87. }

通过这个,我找到了以下有效的方法:

  1. SavedModelBundle smb = SavedModelBundle.load("./model", "serve");
  2. Session s = smb.session();
  3. Tensor<Float> inputTensor = Tensor.<Float>create(imagesArray, Float.class);
  4. Tensor<Float> result = s.runner()
  5. .feed("serving_default_Input_Layer_input", inputTensor)
  6. .fetch("StatefulPartitionedCall")
  7. .run().get(0).expect(Float.class);
英文:

I finally managed to find a solution. To get all the tensor names in the graph, I used the following code:

  1. for (Iterator it = smb.graph().operations(); it.hasNext();) {
  2. Operation op = (Operation) it.next();
  3. System.out.println(&quot;Operation name: &quot; + op.name());
  4. }

From this, I figured out that the following works:

  1. SavedModelBundle smb = SavedModelBundle.load(&quot;./model&quot;, &quot;serve&quot;);
  2. Session s = smb.session();
  3. Tensor&lt;Float&gt; inputTensor = Tensor.&lt;Float&gt;create(imagesArray, Float.class);
  4. Tensor&lt;Float&gt; result = s.runner()
  5. .feed(&quot;serving_default_Input_Layer_input&quot;, inputTensor)
  6. .fetch(&quot;StatefulPartitionedCall&quot;)
  7. .run().get(0).expect(Float.class);

答案2

得分: 1

使用最新版本的TensorFlow Java,您无需自行查找模型签名或图形中输入/输出张量的名称。您只需调用以下方法:

  1. try (SavedModelBundle model = SavedModelBundle.load("./model", "serve");
  2. Tensor<TFloat32> image = TFloat32.tensorOf(...); // 有许多方法可以传递图像字节
  3. Tensor<TFloat32> result = model.call(image).expect(TFloat32.DTYPE)) {
  4. System.out.println("Result is " + result.data().getFloat());
  5. }

TensorFlow Java将自动处理将您的输入/输出张量映射到正确的节点。

英文:

With the newest version of TensorFlow Java, you don't need to search for yourself the name of the input/output tensors from the model signature or from the graph. You can simply call the following:

  1. try (SavedModelBundle model = SavedModelBundle.load(&quot;./model&quot;, &quot;serve&quot;);
  2. Tensor&lt;TFloat32&gt; image = TFloat32.tensorOf(...); // There a many ways to pass you image bytes here
  3. Tensor&lt;TFloat32&gt; result = model.call(image).expect(TFloat32.DTYPE)) {
  4. System.out.println(&quot;Result is &quot; + result.data().getFloat());
  5. }
  6. }

TensorFlow Java will automatically take care of mapping your input/output tensors to the right nodes.

huangapple
  • 本文由 发表于 2020年10月3日 20:53:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/64184509.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定