Introduce tf2tflite-value-pbtxt-test (#8736)
author박천교/On-Device Lab(SR)/Engineer/삼성전자 <ch.bahk@samsung.com>
Tue, 5 Nov 2019 00:18:28 +0000 (09:18 +0900)
committer박세희/On-Device Lab(SR)/Principal Engineer/삼성전자 <saehie.park@samsung.com>
Tue, 5 Nov 2019 00:18:28 +0000 (09:18 +0900)
This commit introduces tf2tflite value test for pbtxt input model. It copies
existing tf2tflite-integration-test only with renaming.

Signed-off-by: Cheongyo Bahk <ch.bahk@samsung.com>
compiler/tf2tflite-value-pbtxt-test/.gitignore [new file with mode: 0644]
compiler/tf2tflite-value-pbtxt-test/CMakeLists.txt [new file with mode: 0644]
compiler/tf2tflite-value-pbtxt-test/README.md [new file with mode: 0644]
compiler/tf2tflite-value-pbtxt-test/requires.cmake [new file with mode: 0644]
compiler/tf2tflite-value-pbtxt-test/test.lst [new file with mode: 0644]
compiler/tf2tflite-value-pbtxt-test/testall.sh [new file with mode: 0755]

diff --git a/compiler/tf2tflite-value-pbtxt-test/.gitignore b/compiler/tf2tflite-value-pbtxt-test/.gitignore
new file mode 100644 (file)
index 0000000..8dbfa90
--- /dev/null
@@ -0,0 +1 @@
+/test.local.lst
diff --git a/compiler/tf2tflite-value-pbtxt-test/CMakeLists.txt b/compiler/tf2tflite-value-pbtxt-test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2e76e21
--- /dev/null
@@ -0,0 +1,159 @@
+nnas_include(TargetRequire)
+
+unset(REQUIRED_TARGETS)
+list(APPEND REQUIRED_TARGETS tf2tflite)
+list(APPEND REQUIRED_TARGETS tfkit)
+list(APPEND REQUIRED_TARGETS nnkit-run)
+list(APPEND REQUIRED_TARGETS nnkit_tf_backend)
+list(APPEND REQUIRED_TARGETS nnkit_tflite_backend)
+list(APPEND REQUIRED_TARGETS nnkit_randomize_action)
+list(APPEND REQUIRED_TARGETS nnkit_HDF5_export_action)
+list(APPEND REQUIRED_TARGETS nnkit_HDF5_import_action)
+list(APPEND REQUIRED_TARGETS i5diff)
+TargetRequire_Return(${REQUIRED_TARGETS})
+
+message(STATUS "tf2tflite-value-pbtxt-test: run tests")
+
+nncc_find_resource(TensorFlowTests)
+
+#
+# Copy [PREFIX]/test.pbtxt to PREFIX.pbtxt in binary folder
+# Copy [PREFIX]/test.info to PREFIX.info in binary folder
+# Copy [PREFIX]/customop.conf to PREFIX_customop.conf in binary folder
+# Encode PREFIX.pbtxt to PREFIX.pb
+#
+set(TEST_REPO "${TensorFlowTests_DIR}")
+set(TEST_PBTXT_FILENAME "test.pbtxt")
+set(TEST_INFO_FILENAME "test.info")
+set(TEST_CUSTOMOP_CONF_FILENAME "customop.conf")
+
+unset(TESTCASES)
+
+macro(add NAME)
+  list(APPEND TESTCASES ${NAME})
+endmacro(add)
+
+# Read "test.lst"
+include("test.lst")
+# Read "test.local.lst" if exists
+include("test.local.lst" OPTIONAL)
+
+unset(TEST_DEPS)
+unset(TEST_NAMES)
+
+foreach(PREFIX IN ITEMS ${TESTCASES})
+  if(NOT IS_DIRECTORY "${TEST_REPO}/${PREFIX}")
+    message(FATAL_ERROR "Missing '${PREFIX}' test")
+  endif()
+
+  set(PBTXT_SOURCE_PATH "${TEST_REPO}/${PREFIX}/${TEST_PBTXT_FILENAME}")
+  set(INFO_SOURCE_PATH "${TEST_REPO}/${PREFIX}/${TEST_INFO_FILENAME}")
+  set(CUSTOMOP_CONF_SOURCE_PATH "${TEST_REPO}/${PREFIX}/${TEST_CUSTOMOP_CONF_FILENAME}")
+
+  set(PBTXT_FILE "${PREFIX}.pbtxt")
+  set(PBTXT_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PBTXT_FILE}")
+
+  set(INFO_FILE "${PREFIX}.info")
+  set(INFO_PATH "${CMAKE_CURRENT_BINARY_DIR}/${INFO_FILE}")
+
+  set(CUSTOMOP_CONF_FILE "${PREFIX}.${TEST_CUSTOMOP_CONF_FILENAME}") # ex) CustomOp_001.customop.conf
+  set(CUSTOMOP_CONF_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CUSTOMOP_CONF_FILE}")
+
+  set(PB_FILE "${PREFIX}.pb")
+  set(PB_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PB_FILE}")
+
+  # Copy .pbtxt
+  add_custom_command(OUTPUT ${PBTXT_PATH}
+    COMMAND ${CMAKE_COMMAND} -E copy "${PBTXT_SOURCE_PATH}" "${PBTXT_PATH}"
+    DEPENDS ${PBTXT_SOURCE_PATH}
+    COMMENT "Generate ${PBTXT_FILE}"
+  )
+
+  # Copy .info
+  add_custom_command(OUTPUT ${INFO_PATH}
+    COMMAND ${CMAKE_COMMAND} -E copy "${INFO_SOURCE_PATH}" "${INFO_PATH}"
+    DEPENDS ${INFO_SOURCE_PATH}
+    COMMENT "Generate ${INFO_FILE}"
+  )
+
+  # Generate .pb from .pbtxt
+  add_custom_command(OUTPUT ${PB_PATH}
+    COMMAND $<TARGET_FILE:tfkit> encode ${PBTXT_PATH} ${PB_PATH}
+    DEPENDS ${PBTXT_PATH}
+    COMMENT "Generate ${PB_FILE}"
+  )
+
+  list(APPEND TEST_DEPS ${INFO_PATH} ${PB_PATH})
+
+  if (EXISTS "${CUSTOMOP_CONF_SOURCE_PATH}")
+
+    # Copy customop.conf
+    add_custom_command(OUTPUT ${CUSTOMOP_CONF_PATH}
+      COMMAND ${CMAKE_COMMAND} -E copy "${CUSTOMOP_CONF_SOURCE_PATH}" "${CUSTOMOP_CONF_PATH}"
+      DEPENDS ${CUSTOMOP_CONF_SOURCE_PATH}
+      COMMENT "Generate ${CUSTOMOP_CONF_FILE}"
+    )
+
+    list(APPEND TEST_DEPS ${CUSTOMOP_CONF_PATH})
+
+  endif (EXISTS "${CUSTOMOP_CONF_SOURCE_PATH}")
+
+  list(APPEND TEST_NAMES ${PREFIX})
+endforeach(PREFIX)
+
+##
+## Copy testall
+##
+set(TEST_RUNNER "${CMAKE_CURRENT_BINARY_DIR}/testall.sh")
+set(TEST_RUNNER_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/testall.sh")
+
+add_custom_command(
+  OUTPUT ${TEST_RUNNER}
+  COMMAND ${CMAKE_COMMAND} -E copy "${TEST_RUNNER_SOURCE}" "${TEST_RUNNER}"
+  DEPENDS ${TEST_RUNNER_SOURCE}
+  COMMENT "Generate test runner"
+)
+
+list(APPEND TEST_DEPS "${TEST_RUNNER}")
+
+###
+### Generate test.config
+###
+set(TEST_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/test.config")
+
+add_custom_command(
+  OUTPUT ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E remove -f ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'NNKIT_RUN_PATH=\"$<TARGET_FILE:nnkit-run>\"' >> ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'TF_BACKEND_PATH=\"$<TARGET_FILE:nnkit_tf_backend>\"' >> ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'TFLITE_BACKEND_PATH=\"$<TARGET_FILE:nnkit_tflite_backend>\"' >> ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'TF2TFLITE_PATH=\"$<TARGET_FILE:tf2tflite>\"' >> ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'RANDOMIZE_ACTION_PATH=\"$<TARGET_FILE:nnkit_randomize_action>\"' >> ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'HDF5_EXPORT_ACTION_PATH=\"$<TARGET_FILE:nnkit_HDF5_export_action>\"' >> ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'HDF5_IMPORT_ACTION_PATH=\"$<TARGET_FILE:nnkit_HDF5_import_action>\"' >> ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'I5DIFF_PATH=\"$<TARGET_FILE:i5diff>\"' >> ${TEST_CONFIG}
+  DEPENDS
+    nnkit-run
+    nnkit_tf_backend
+    nnkit_tflite_backend
+    tf2tflite
+    nnkit_randomize_action
+    nnkit_HDF5_export_action
+    nnkit_HDF5_import_action
+    i5diff
+  COMMENT "Generate test configuration"
+)
+
+list(APPEND TEST_DEPS "${TEST_CONFIG}")
+
+# This "tf2tflite_value_pbtxt_test_deps" target enforces CMake to generate all the dependencies during "build" phase
+add_custom_target(tf2tflite_value_pbtxt_test_deps ALL DEPENDS ${TEST_DEPS})
+
+# Run tests
+add_test(
+  NAME tf2tflite_value_pbtxt_test
+  COMMAND "${TEST_RUNNER}"
+          "${TEST_CONFIG}"
+          "${CMAKE_CURRENT_BINARY_DIR}"
+          ${TEST_NAMES}
+)
diff --git a/compiler/tf2tflite-value-pbtxt-test/README.md b/compiler/tf2tflite-value-pbtxt-test/README.md
new file mode 100644 (file)
index 0000000..3042954
--- /dev/null
@@ -0,0 +1,3 @@
+# tf2tflite-value-pbtxt-test
+
+Run `tf2tflite` to `test.lst` and do random value test using `nnkit`. Write `test.local.lst` for local test list.
diff --git a/compiler/tf2tflite-value-pbtxt-test/requires.cmake b/compiler/tf2tflite-value-pbtxt-test/requires.cmake
new file mode 100644 (file)
index 0000000..bb783e2
--- /dev/null
@@ -0,0 +1,4 @@
+require("tf2tflite")
+require("nnkit")
+require("tfkit")
+require("i5diff")
diff --git a/compiler/tf2tflite-value-pbtxt-test/test.lst b/compiler/tf2tflite-value-pbtxt-test/test.lst
new file mode 100644 (file)
index 0000000..3d34a8b
--- /dev/null
@@ -0,0 +1,98 @@
+# TODO Enable skipped tests
+
+add(NET_0000)
+add(NET_0001)
+add(NET_0002)
+add(NET_0003)
+add(NET_0004)
+add(NET_0005)
+add(NET_0006)
+add(NET_0007)
+add(NET_0008)
+add(NET_0009)
+add(NET_0010)
+add(NET_0011)
+add(NET_0012)
+add(NET_0013)
+add(NET_0014)
+add(NET_0015)
+add(NET_0016)
+add(NET_0017)
+add(NET_0018)
+add(NET_0019)
+add(NET_0020)
+add(NET_0021)
+add(NET_0022)
+add(NET_0023)
+add(NET_0024)
+add(NET_0025)
+add(NET_0028)
+add(NET_0029)
+add(NET_0030)
+add(NET_0031)
+add(NET_0032)
+add(NET_0033)
+add(NET_0034)
+add(NET_0035)
+add(NET_0036)
+add(NET_0037)
+add(NET_0038)
+add(NET_0039)
+add(NET_0040)
+add(NET_0041)
+add(REGRESSION_0000)
+add(REGRESSION_0001)
+add(REGRESSION_0002)
+add(UNIT_Add_000)
+add(UNIT_Add_001)
+add(UNIT_Add_002)
+add(UNIT_Add_004)
+add(UNIT_Add_005)
+add(UNIT_AvgPool_000)
+add(UNIT_AvgPool_001)
+#add(UNIT_BiasAdd_000)
+#add(UNIT_BiasAdd_001)
+add(UNIT_BiasAdd_002)
+#add(UNIT_ConcatV2_000)
+#add(UNIT_ConcatV2_001)
+add(UNIT_ConcatV2_002)
+add(UNIT_Const_000)
+#add(UNIT_Const_001)
+add(UNIT_Conv2D_000)
+add(UNIT_Conv2DBackpropInput_000)
+add(UNIT_Conv2DBackpropInput_001)
+add(UNIT_DepthwiseConv2dNative_000)
+add(UNIT_DepthwiseConv2dNative_001)
+add(UNIT_MaxPool_000)
+add(UNIT_MaxPool_001)
+add(UNIT_Mean_000)
+add(UNIT_Mean_001)
+add(UNIT_Mean_002)
+add(UNIT_Mean_003)
+add(UNIT_Mul_000)
+add(UNIT_Mul_001)
+add(UNIT_Mul_002)
+add(UNIT_Pad_000)
+add(UNIT_Placeholder_000)
+add(UNIT_Placeholder_001)
+add(UNIT_Placeholder_002)
+add(UNIT_Placeholder_003)
+add(UNIT_RealDiv_000)
+add(UNIT_RealDiv_001)
+add(UNIT_Relu_000)
+add(UNIT_Relu6_000)
+add(UNIT_Reshape_000)
+add(UNIT_Rsqrt_000)
+add(UNIT_Softmax_001)
+add(UNIT_Sqrt_000)
+add(UNIT_SquaredDifference_000)
+add(UNIT_SquaredDifference_001)
+add(UNIT_Squeeze_000)
+add(UNIT_Squeeze_001)
+add(UNIT_Squeeze_002)
+add(UNIT_Squeeze_003)
+add(UNIT_StopGradient_000)
+add(UNIT_StopGradient_001)
+add(UNIT_Sub_000)
+add(UNIT_Sub_001)
+add(UNIT_Tanh_000)
diff --git a/compiler/tf2tflite-value-pbtxt-test/testall.sh b/compiler/tf2tflite-value-pbtxt-test/testall.sh
new file mode 100755 (executable)
index 0000000..ff18b60
--- /dev/null
@@ -0,0 +1,106 @@
+#!/bin/bash
+
+# Need at least 2 arguments
+if [[ $# -lt 2 ]]; then
+  echo "USAGE: $0 ..."
+  echo
+  echo "ARGUMENTS:"
+  echo "  [test.config path]"
+  echo "  [WORKDIR]"
+  echo "  [Prefix1]"
+  echo "  [Prefix2]"
+  echo "  ..."
+  exit 255
+fi
+
+CONFIG_PATH="$1"; shift
+WORKDIR="$1"; shift
+
+source "${CONFIG_PATH}"
+
+echo "-- Found nnkit-run: ${NNKIT_RUN_PATH}"
+echo "-- Found TF backend: ${TF_BACKEND_PATH}"
+echo "-- Found TFLITE backend: ${TFLITE_BACKEND_PATH}"
+echo "-- Found TF2TFLITE: ${TF2TFLITE_PATH}"
+echo "-- Found randomize action: ${RANDOMIZE_ACTION_PATH}"
+echo "-- Found HDF5 export action: ${HDF5_EXPORT_ACTION_PATH}"
+echo "-- Found HDF5 import action: ${HDF5_IMPORT_ACTION_PATH}"
+echo "-- Found i5diff: ${I5DIFF_PATH}"
+echo "-- Found workdir: ${WORKDIR}"
+
+TESTED=()
+PASSED=()
+FAILED=()
+
+pushd "${WORKDIR}"
+while [[ $# -ne 0 ]]; do
+  PREFIX="$1"; shift
+
+  TESTED+=("${PREFIX}")
+
+  PASSED_TAG="${PREFIX}.passed"
+
+  rm -f "${PASSED_TAG}"
+
+  cat > "${PREFIX}.log" <(
+    exec 2>&1
+
+    echo "-- Found pb: ${PREFIX}.pb"
+
+    # Exit immediately if any command fails
+    set -e
+    # Show commands
+    set -x
+
+    # Generate tflite
+    "${TF2TFLITE_PATH}" \
+      "${WORKDIR}/${PREFIX}.info" \
+      "${WORKDIR}/${PREFIX}.pb" \
+      "${WORKDIR}/${PREFIX}.tflite"
+
+    # Run TensorFlow
+    "${NNKIT_RUN_PATH}" \
+      --backend "${TF_BACKEND_PATH}" \
+      --backend-arg "${WORKDIR}/${PREFIX}.pb" \
+      --backend-arg "${WORKDIR}/${PREFIX}.info" \
+      --pre "${RANDOMIZE_ACTION_PATH}" \
+      --pre "${HDF5_EXPORT_ACTION_PATH}" \
+      --pre-arg "${WORKDIR}/${PREFIX}.input.h5" \
+      --post "${HDF5_EXPORT_ACTION_PATH}" \
+      --post-arg "${WORKDIR}/${PREFIX}.expected.h5"
+
+    # Run TensorFlow Lite
+    "${NNKIT_RUN_PATH}" \
+      --backend "${TFLITE_BACKEND_PATH}" \
+      --backend-arg "${WORKDIR}/${PREFIX}.tflite" \
+      --pre "${HDF5_IMPORT_ACTION_PATH}" \
+      --pre-arg "${WORKDIR}/${PREFIX}.input.h5" \
+      --post "${HDF5_EXPORT_ACTION_PATH}" \
+      --post-arg "${WORKDIR}/${PREFIX}.obtained.h5"
+
+    "${I5DIFF_PATH}" -d 0.001 "${PREFIX}.expected.h5" "${PREFIX}.obtained.h5"
+
+    if [[ $? -eq 0 ]]; then
+      touch "${PASSED_TAG}"
+    fi
+  )
+
+  if [[ -f "${PASSED_TAG}" ]]; then
+    PASSED+=("$PREFIX")
+  else
+    FAILED+=("$PREFIX")
+  fi
+done
+popd
+
+if [[ ${#TESTED[@]} -ne ${#PASSED[@]} ]]; then
+  echo "FAILED"
+  for TEST in "${FAILED[@]}"
+  do
+    echo "- ${TEST}"
+  done
+  exit 255
+fi
+
+echo "PASSED"
+exit 0