aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar A. Unique TensorFlower <gardener@tensorflow.org>2018-05-16 22:33:38 -0700
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2018-05-16 22:36:14 -0700
commitd86dcdb8e8d284be1a2897f9d1e00b92eed5ac68 (patch)
treeb4151494afef20fc0746647cd5df448b5c9dfd50
parent23e17c68c76b01c7389065da9c0c4f829177ca8c (diff)
Move BUILD file to OVIC folder and add model validation.
PiperOrigin-RevId: 196940252
-rw-r--r--tensorflow/contrib/lite/java/BUILD54
-rw-r--r--tensorflow/contrib/lite/java/ovic/BUILD68
-rw-r--r--tensorflow/contrib/lite/java/ovic/README.md30
-rw-r--r--tensorflow/contrib/lite/java/ovic/demo/app/BUILD2
-rw-r--r--tensorflow/contrib/lite/java/ovic/src/main/java/org/tensorflow/ovic/OvicValidator.java94
5 files changed, 191 insertions, 57 deletions
diff --git a/tensorflow/contrib/lite/java/BUILD b/tensorflow/contrib/lite/java/BUILD
index 1e57922603..593af81a18 100644
--- a/tensorflow/contrib/lite/java/BUILD
+++ b/tensorflow/contrib/lite/java/BUILD
@@ -1,7 +1,9 @@
# Description:
# TensorFlow Lite Java API.
-package(default_visibility = ["//visibility:private"])
+package(default_visibility = [
+ "//tensorflow/contrib/lite/java/ovic:__pkg__",
+])
licenses(["notice"]) # Apache 2.0
@@ -46,38 +48,6 @@ android_library(
],
)
-android_library(
- name = "ovicbenchmarkerlib",
- srcs = [
- "ovic/src/main/java/org/tensorflow/ovic/OvicClassifier.java",
- "ovic/src/main/java/org/tensorflow/ovic/OvicSingleImageResult.java",
- ],
- manifest = "AndroidManifest.xml",
- visibility = ["//visibility:public"],
- deps = [
- ":tensorflowlite",
- "//tensorflow/contrib/lite/java/src/testhelper/java/org/tensorflow/lite:testhelper",
- "@org_checkerframework_qual",
- ],
-)
-
-java_library(
- name = "ovicbenchmarkerlib_java",
- srcs = [
- "ovic/src/main/java/org/tensorflow/ovic/OvicClassifier.java",
- "ovic/src/main/java/org/tensorflow/ovic/OvicSingleImageResult.java",
- ],
- javacopts = JAVACOPTS,
- visibility = ["//visibility:public"],
- deps = [
- ":libtensorflowlite_jni.so",
- ":tensorflowlite_java",
- "//tensorflow/contrib/lite/java/src/main/native",
- "//tensorflow/contrib/lite/java/src/testhelper/java/org/tensorflow/lite:testhelper",
- "@org_checkerframework_qual",
- ],
-)
-
java_library(
name = "tensorflowlitelib",
srcs = glob(
@@ -180,24 +150,6 @@ java_test(
],
)
-java_test(
- name = "OvicClassifierTest",
- size = "medium",
- srcs = ["ovic/src/test/java/org/tensorflow/ovic/OvicClassifierTest.java"],
- data = [
- "//tensorflow/contrib/lite/java/ovic/src/testdata:labels.txt",
- "//tensorflow/contrib/lite/java/ovic/src/testdata:ovic_testdata",
- ],
- javacopts = JAVACOPTS,
- test_class = "org.tensorflow.ovic.OvicClassifierTest",
- visibility = ["//visibility:public"],
- deps = [
- ":ovicbenchmarkerlib_java",
- "@com_google_truth",
- "@junit",
- ],
-)
-
filegroup(
name = "libtensorflowlite_jni",
srcs = select({
diff --git a/tensorflow/contrib/lite/java/ovic/BUILD b/tensorflow/contrib/lite/java/ovic/BUILD
new file mode 100644
index 0000000000..362d93636f
--- /dev/null
+++ b/tensorflow/contrib/lite/java/ovic/BUILD
@@ -0,0 +1,68 @@
+# Description:
+# OVIC Benchmarker Java API.
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"]) # Apache 2.0
+
+load("//tensorflow/java:build_defs.bzl", "JAVACOPTS")
+
+java_test(
+ name = "OvicClassifierTest",
+ size = "medium",
+ srcs = ["src/test/java/org/tensorflow/ovic/OvicClassifierTest.java"],
+ data = [
+ "//tensorflow/contrib/lite/java/ovic/src/testdata:labels.txt",
+ "//tensorflow/contrib/lite/java/ovic/src/testdata:ovic_testdata",
+ ],
+ javacopts = JAVACOPTS,
+ test_class = "org.tensorflow.ovic.OvicClassifierTest",
+ visibility = ["//visibility:public"],
+ deps = [
+ "//tensorflow/contrib/lite/java/ovic:ovicbenchmarkerlib_java",
+ "@com_google_truth",
+ "@junit",
+ ],
+)
+
+java_binary(
+ name = "ovic_validator",
+ srcs = ["src/main/java/org/tensorflow/ovic/OvicValidator.java"],
+ data = [
+ "//tensorflow/contrib/lite/java/ovic/src/testdata:labels.txt",
+ ],
+ main_class = "org.tensorflow.ovic.OvicValidator",
+ deps = [
+ "//tensorflow/contrib/lite/java/ovic:ovicbenchmarkerlib_java",
+ ],
+)
+
+android_library(
+ name = "ovicbenchmarkerlib",
+ srcs = [
+ "src/main/java/org/tensorflow/ovic/OvicClassifier.java",
+ "src/main/java/org/tensorflow/ovic/OvicSingleImageResult.java",
+ ],
+ manifest = "//tensorflow/contrib/lite/java:AndroidManifest.xml",
+ deps = [
+ "//tensorflow/contrib/lite/java:tensorflowlite",
+ "//tensorflow/contrib/lite/java/src/testhelper/java/org/tensorflow/lite:testhelper",
+ "@org_checkerframework_qual",
+ ],
+)
+
+java_library(
+ name = "ovicbenchmarkerlib_java",
+ srcs = [
+ "src/main/java/org/tensorflow/ovic/OvicClassifier.java",
+ "src/main/java/org/tensorflow/ovic/OvicSingleImageResult.java",
+ ],
+ javacopts = JAVACOPTS,
+ deps = [
+ "//tensorflow/contrib/lite/java:libtensorflowlite_jni.so",
+ "//tensorflow/contrib/lite/java:tensorflowlite_java",
+ "//tensorflow/contrib/lite/java/src/main/native",
+ "//tensorflow/contrib/lite/java/src/testhelper/java/org/tensorflow/lite:testhelper",
+ "@org_checkerframework_qual",
+ ],
+)
diff --git a/tensorflow/contrib/lite/java/ovic/README.md b/tensorflow/contrib/lite/java/ovic/README.md
index 77799b3569..5efa70987e 100644
--- a/tensorflow/contrib/lite/java/ovic/README.md
+++ b/tensorflow/contrib/lite/java/ovic/README.md
@@ -37,19 +37,37 @@ unzip -j /tmp/ovic.zip -d tensorflow/contrib/lite/java/ovic/src/testdata/
You can run test with Bazel as below. This helps to ensure that the installation is correct.
```sh
-bazel test --cxxopt=--std=c++11 //tensorflow/contrib/lite/java:OvicClassifierTest --cxxopt=-Wno-all --test_output=all
+bazel test --cxxopt=--std=c++11 //tensorflow/contrib/lite/java/ovic:OvicClassifierTest --cxxopt=-Wno-all --test_output=all
```
### Test your submissions
-Once you have a submission that follows the instructions from the [competition site](https://rebootingcomputing.ieee.org/home/sitemap/14-lpirc/80-low-power-image-recognition-challenge-lpirc-2018), you can verify it as below.
+Once you have a submission that follows the instructions from the [competition site](https://rebootingcomputing.ieee.org/home/sitemap/14-lpirc/80-low-power-image-recognition-challenge-lpirc-2018), you can verify it in two ways:
-* Move your submission to the testdata folder:
+#### Validate using randomly generated images
+
+You can call the validator binary below to verify that your model fits the format requirements. This often helps you to catch size mismatches (e.g. output should be [1, 1001] instead of [1,1,1,1001]). Let say the submission file is located at `/path/to/my_model.lite`, then call:
+
+```sh
+bazel build --cxxopt--std=c++11 //tensorflow/contrib/lite/java/ovic:ovic_validator --cxxopt=-Wno-all
+bazel-bin/tensorflow/contrib/lite/java/ovic/ovic_validator /path/to/my_model.lite
+```
+
+Successful validation should print the following message to terminal:
+
+```
+Successfully validated /path/to/my_model.lite.
+
+```
+
+#### Test that the model produces sensible outcomes
-Let say the submission file is located at `/tmp/my_model.lite`, then
+You can go a step further to verify that the model produces results as expected. This helps you catch bugs during TOCO conversion (e.g. using the wrong mean and std values).
+
+* Move your submission to the testdata folder:
```sh
-cp /tmp/my_model.lite tensorflow/contrib/lite/java/ovic/src/testdata/
+cp /path/to/my_model.lite tensorflow/contrib/lite/java/ovic/src/testdata/
```
* Resize the test image to the resolutions that are expected by your submission:
@@ -136,3 +154,5 @@ Note: the benchmarking results can be quite different depending on the backgroun
| quantized_model.lite | 85 | 74 |
| low_res_model.lite | 4.2 | 4.0 |
+Since Pixel 2 has excellent support for 8-bit quantized models, we strongly recommend you to check out the [quantization training tutorial](https://www.tensorflow.org/performance/quantization).
+
diff --git a/tensorflow/contrib/lite/java/ovic/demo/app/BUILD b/tensorflow/contrib/lite/java/ovic/demo/app/BUILD
index 47101ff574..83974f4b33 100644
--- a/tensorflow/contrib/lite/java/ovic/demo/app/BUILD
+++ b/tensorflow/contrib/lite/java/ovic/demo/app/BUILD
@@ -21,8 +21,8 @@ android_binary(
resource_files = glob(["res/**"]),
tags = ["manual"],
deps = [
- "//tensorflow/contrib/lite/java:ovicbenchmarkerlib",
"//tensorflow/contrib/lite/java:tensorflowlite",
+ "//tensorflow/contrib/lite/java/ovic:ovicbenchmarkerlib",
"@androidsdk//com.android.support:support-v13-25.2.0",
"@androidsdk//com.android.support:support-v4-25.2.0",
],
diff --git a/tensorflow/contrib/lite/java/ovic/src/main/java/org/tensorflow/ovic/OvicValidator.java b/tensorflow/contrib/lite/java/ovic/src/main/java/org/tensorflow/ovic/OvicValidator.java
new file mode 100644
index 0000000000..a504ec74a9
--- /dev/null
+++ b/tensorflow/contrib/lite/java/ovic/src/main/java/org/tensorflow/ovic/OvicValidator.java
@@ -0,0 +1,94 @@
+/*Copyright 2018 Google LLC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+package org.tensorflow.ovic;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.util.Random;
+
+/** Validate a submission model. */
+public class OvicValidator {
+ private static void printUsage(PrintStream s) {
+ s.println("Java program that validates a submission model.");
+ s.println();
+ s.println("Usage: ovic_validator <submission file>");
+ s.println();
+ s.println("Where:");
+ s.println("<submission file> is the model in TfLite format;");
+ }
+
+ public static void main(String[] args) {
+ if (args.length != 1) {
+ printUsage(System.err);
+ System.exit(1);
+ }
+ final String labelPath =
+ "tensorflow/contrib/lite/java/ovic/src/testdata/labels.txt";
+
+ final String modelFile = args[0];
+ try {
+ File labelsfile = new File(labelPath);
+ InputStream labelsInputStream = new FileInputStream(labelsfile);
+ MappedByteBuffer model = loadModelFile(modelFile);
+ OvicClassifier classifier = new OvicClassifier(labelsInputStream, model);
+ ByteBuffer imgData = createByteBufferForClassifier(classifier);
+ OvicSingleImageResult testResult = classifier.classifyByteBuffer(imgData);
+ if (testResult.topKClasses.isEmpty()) {
+ throw new RuntimeException("Failed to return top K predictions.");
+ }
+ System.out.printf("Successfully validated %s.%n", modelFile);
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ System.out.printf("Failed to validate %s.%n", modelFile);
+ }
+ }
+
+ private static ByteBuffer createByteBufferForClassifier(OvicClassifier classifier) {
+ if (classifier == null) {
+ throw new RuntimeException("Cannot create image buffer with the classifier.");
+ }
+ int[] inputDims = classifier.getInputDims();
+ int imgHeight = inputDims[1];
+ int imgWidth = inputDims[2];
+ ByteBuffer imgData = ByteBuffer.allocateDirect(imgHeight * imgWidth * 3);
+ imgData.order(ByteOrder.nativeOrder());
+ Random rand = new Random();
+ for (int y = 0; y < imgHeight; y++) {
+ for (int x = 0; x < imgWidth; x++) {
+ int val = rand.nextInt();
+ imgData.put((byte) ((val >> 16) & 0xFF));
+ imgData.put((byte) ((val >> 8) & 0xFF));
+ imgData.put((byte) (val & 0xFF));
+ }
+ }
+ return imgData;
+ }
+
+ private static MappedByteBuffer loadModelFile(String modelFilePath) throws IOException {
+ File modelfile = new File(modelFilePath);
+ FileInputStream inputStream = new FileInputStream(modelfile);
+ FileChannel fileChannel = inputStream.getChannel();
+ long startOffset = 0L;
+ long declaredLength = fileChannel.size();
+ return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
+ }
+}