Add NNAPI 1.1 Div/Mul/Pad/Mean nodes.
authorA. Unique TensorFlower <gardener@tensorflow.org>
Fri, 11 May 2018 11:33:38 +0000 (04:33 -0700)
committerTensorFlower Gardener <gardener@tensorflow.org>
Fri, 11 May 2018 11:36:38 +0000 (04:36 -0700)
PiperOrigin-RevId: 196240584

tensorflow/contrib/lite/nnapi/NeuralNetworksShim.h
tensorflow/contrib/lite/nnapi_delegate.cc

index 4a648e4..becd1f6 100644 (file)
@@ -65,7 +65,8 @@ inline bool NNAPIExists() {
   return nnapi_is_available;
 }
 
-// nn api types
+// NN api types based on NNAPI header file
+// https://developer.android.com/ndk/reference/group/neural-networks
 
 /**
  * Operand types.
@@ -77,31 +78,11 @@ inline bool NNAPIExists() {
  * ANEURALNETWORKS_TENSOR_QUANT8_ASYMM, and ANEURALNETWORKS_INT32.
  */
 enum {
-  /** The following entries are used to declare scalars. */
-
-  /** A 32 bit floating point scalar value. */
   ANEURALNETWORKS_FLOAT32 = 0,
-  /** A signed 32 bit integer scalar value. */
   ANEURALNETWORKS_INT32 = 1,
-  /** An unsigned 32 bit integer scalar value. */
   ANEURALNETWORKS_UINT32 = 2,
-
-  /** The following entries are used to declare tensors. */
-
-  /** A tensor of 32 bit floating point values. */
   ANEURALNETWORKS_TENSOR_FLOAT32 = 3,
-  /** A tensor of 32 bit integer values. */
   ANEURALNETWORKS_TENSOR_INT32 = 4,
-  /** A tensor of 8 bit integers that represent real numbers.
-   *
-   * Attached to this tensor are two numbers that can be used to convert
-   * the 8 bit integer to the real value and vice versa.  These two numbers are:
-   * - scale: a 32 bit floating point value
-   * - zero_value: an 32 bit integer
-   *
-   * The formula is:
-   * real_value = (integer_value - zero_value) * scale.
-   */
   ANEURALNETWORKS_TENSOR_QUANT8_ASYMM = 5,
 };
 
@@ -111,968 +92,44 @@ enum {
  * The type of operations that can be added to a model.
  */
 enum {
-  /** Adds two tensors, element-wise.
-   *
-   * Takes two input tensors of identical type and compatible dimensions. The
-   * output is the sum of both input tensors, optionally modified by an
-   * activation function.
-   *
-   * Two dimensions are compatible when:
-   *     1. they are equal, or
-   *     2. one of them is 1
-   *
-   * The size of the output is the maximum size along each dimension of the
-   * input operands. It starts with the trailing dimensions, and works its way
-   * forward.
-   *
-   * Example:
-   *
-   *     input1.dimension = {4, 1, 2}
-   *     input2.dimension = {5, 4, 3, 1}
-   *     output.dimension = {5, 4, 3, 2}
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   *
-   * Supported tensor rank: up to 4
-   *
-   * Inputs:
-   * * 0: A tensor.
-   * * 1: A tensor of the same type, and compatible dimensions as input0.
-   * * 2: An INT32 value, and has to be one of the {@link FuseCode} values.
-   *      Specifies the activation to invoke on the result of each addition.
-   *
-   * Outputs:
-   * * 0: The sum, a tensor of the same type as input0.
-   */
   ANEURALNETWORKS_ADD = 0,
-  /** Performs a 2-D average pooling operation.
-   *
-   * The output dimensions are functions of the filter dimensions, stride, and
-   * padding.
-   *
-   * The values in the output tensor are computed as:
-   *
-   *     output[batch, row, col, channel] =
-   *         sum_{i, j}(input[batch, row + i, col + j, channel]) / sum(1)
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: 4, with "NHWC" data layout.
-   *
-   * Inputs:
-   * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the
-   * input.
-   * * 1: An INT32 value, specifying the padding on the left, in the ‘width’
-   * dimension.
-   * * 2: An INT32 value, specifying the padding on the right,in the ‘width’
-   * dimension.
-   * * 3: An INT32 value, specifying the padding on the top, in the ‘height’
-   * dimension.
-   * * 4: An INT32 value, specifying the padding on the bottom, in the ‘height’
-   * dimension.
-   * * 5: An INT32 value, specifying the output stride in the ‘width’ dimension.
-   * * 6: An INT32 value, specifying the output stride in the ‘height’
-   * dimension.
-   * * 7: An INT32 value, specifying the filter width.
-   * * 8: An INT32 value, specifying the filter height.
-   * * 9: An INT32 value, and has to be one of the {@link FuseCode} values.
-   *      Specifies the activation to invoke on the result of each addition.
-   *
-   * Outputs:
-   * * 0: The output 4-D tensor, of shape [batches, out_height, out_width,
-   * depth].
-   */
   ANEURALNETWORKS_AVERAGE_POOL_2D = 1,
-  /** Concatenates the input tensors along the given dimension.
-   *
-   * The input tensors must have identical type and the same dimensions except
-   * the dimension along the concatenation axis.
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: up to 4
-   *
-   * Inputs:
-   * 0 ~ n: The list on n input tensors, of shape [D0, D1, ..., Daxis(i), ...,
-   * Dm] n+1: An INT32 value, specifying the concatenation axis. n+2: An INT32
-   * value, and has to be one of the {@link FuseCode} values. Specifies the
-   * activation to invoke on the result of each addition.
-   *
-   * Outputs:
-   * * 0: The output, a tensor of the same type as the input tensors.
-   *      The output shape is [D0, D1, ..., sum(Daxis(i)), ..., Dm].
-   */
   ANEURALNETWORKS_CONCATENATION = 2,
-  /** Performs an 2-D convolution operation.
-   *
-   * The CONV_2D op sweeps a 2-D filter that can mix channels together over a
-   * batch of images, applying the filter to each window of each image of the
-   * appropriate size.
-   *
-   * The output dimensions are functions of the filter dimensions, stride, and
-   * padding.
-   *
-   * The values in the output tensor are computed as:
-   *
-   *     output[batch, row, col, channel] =
-   *         sum_{i, j} (
-   *             input[batch, row + i, col + j, k] *
-   *             filter[channel, row + i, col + j, k] +
-   *             bias[channel]
-   *         )
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: 4, with "NHWC" data layout.
-   *
-   * Inputs:
-   * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], specifying
-   * the input.
-   * * 1: A 4-D tensor, of shape [depth_out, filter_height, filter_width,
-   * depth_in], specifying the filter.
-   * * 2: A 1-D tensor, of shape [depth_out], specifying the bias.
-   *      For input tensor of {@link ANEURALNETWORKS_TENSOR_FLOAT32} type, the
-   * bias should also be of {@link ANEURALNETWORKS_TENSOR_FLOAT32}. For input
-   * tensor of {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM} type, the bias should
-   * be of {@link ANEURALNETWORKS_TENSOR_INT32}.
-   * * 3: An INT32 value, specifying the padding on the left, in the ‘width’
-   * dimension.
-   * * 4: An INT32 value, specifying the padding on the right,in the ‘width’
-   * dimension.
-   * * 5: An INT32 value, specifying the padding on the top, in the ‘height’
-   * dimension.
-   * * 6: An INT32 value, specifying the padding on the bottom, in the ‘height’
-   * dimension.
-   * * 7: An INT32 value, specifying the output stride in the ‘width’ dimension.
-   * * 8: An INT32 value, specifying the output stride in the ‘height’
-   * dimension.
-   * * 9: An INT32 value, and has to be one of the {@link FuseCode} values.
-   *      Specifies the activation to invoke on the result of each addition.
-   *
-   * Outputs:
-   * * 0: The output 4-D tensor, of shape [batches, out_height, out_width,
-   * depth_out].
-   */
   ANEURALNETWORKS_CONV_2D = 3,
-  /** Performs a depthwise 2-D convolution operation.
-   *
-   * Given an input tensor of shape [batches, height, width, depth_in] and a
-   * filter tensor of shape [depth_out, filter_height, filter_width, depth_in]
-   * containing in_channels convolutional filters of depth 1, DEPTHWISE_CONV
-   * applies a different filter to each input channel (expanding from 1 channel
-   * to channel_multiplier channels for each), then concatenates the results
-   * together.
-   *
-   * The output has depth_out = depth_in * depth_multiplier channels.
-   * The output dimensions are functions of the filter dimensions, stride, and
-   * padding.
-   *
-   * The values in the output tensor are computed as:
-   *
-   *     output[b, i, j, k * channel_multiplier + q] =
-   *         sum_{di, dj} (
-   *             input[b, strides[1] * i + di, strides[2] * j + dj, k] *
-   *             filter[di, dj, k, q]
-   *         )
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: 4, with "NHWC" data layout.
-   *
-   * Inputs:
-   * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], specifying
-   * the input.
-   * * 1: A 4-D tensor, of shape [depth_out, filter_height, filter_width,
-   * depth_in], specifying the filter.
-   * * 2: A 1-D tensor, of shape [depth_out], specifying the bias.
-   *      For input tensor of {@link ANEURALNETWORKS_TENSOR_FLOAT32} type, the
-   * bias should also be of {@link ANEURALNETWORKS_TENSOR_FLOAT32}. For input
-   * tensor of {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM} type, the bias should
-   * be of {@link ANEURALNETWORKS_TENSOR_INT32}.
-   * * 3: An INT32 value, specifying the padding on the left, in the ‘width’
-   * dimension.
-   * * 4: An INT32 value, specifying the padding on the right,in the ‘width’
-   * dimension.
-   * * 5: An INT32 value, specifying the padding on the top, in the ‘height’
-   * dimension.
-   * * 6: An INT32 value, specifying the padding on the bottom, in the ‘height’
-   * dimension.
-   * * 7: An INT32 value, specifying the output stride in the ‘width’ dimension.
-   * * 8: An INT32 value, specifying the output stride in the ‘height’
-   * dimension.
-   * * 9: An INT32 value, specifying the depthwise multiplier.
-   * * 10: An INT32 value, and has to be one of the {@link FuseCode} values.
-   *       Specifies the activation to invoke on the result of each addition.
-   *
-   * Outputs:
-   * * 0: The output 4-D tensor, of shape [batches, out_height, out_width,
-   * depth_out].
-   */
   ANEURALNETWORKS_DEPTHWISE_CONV_2D = 4,
-  /** Rearranges data from depth into blocks of spatial data.
-   *
-   * More specifically, this op outputs a copy of the input tensor where values
-   * from the depth dimension are moved in spatial blocks to the height and
-   * width dimensions. The value block_size indicates the input block size and
-   * how the data is moved.
-   *
-   * Chunks of data of size block_size * block_size from depth are rearranged
-   * into non-overlapping blocks of size block_size x block_size.
-   *
-   * The width of the output tensor is input_depth * block_size, whereas the
-   * height is input_height * block_size. The depth of the input tensor must be
-   * divisible by block_size * block_size
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: 4, with "NHWC" data layout.
-   *
-   * Inputs:
-   * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], specifying
-   * the input.
-   * * 1: An INT32 value, specifying the block_size. block_size must be >=1 and
-   *      block_size * block_size must be a divisor of the input depth.
-   *
-   * Outputs:
-   * * 0: The output 4-D tensor, of shape [batch, height*block_size,
-   * width*block_size, depth/(block_size*block_size)].
-   */
   ANEURALNETWORKS_DEPTH_TO_SPACE = 5,
-  /** Dequantizes the input tensor.
-   *
-   * The formula is:
-   *
-   *     output = (input - zero_value) * scale.
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: up to 4
-   *
-   * Inputs:
-   * * 0: A tensor of type {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}.
-   *
-   * Outputs:
-   * * 0: The output tensor of same shape as input0, but with type
-   *      {@link ANEURALNETWORKS_TENSOR_FLOAT32}.
-   */
   ANEURALNETWORKS_DEQUANTIZE = 6,
-
-  /**
-   * Looks up items from a given tensor.
-   *
-   * Each item in the output is a raw copy of the corresponding item in
-   * the input “values”. If the given “lookup” indices are out of bounds,
-   * the op will fail and an error will be reported.
-   *
-   * Inputs:
-   * * 0: Values. An n-D tensor of any type X (where n >= 2). E.g., if n is 2,
-   *      then the shape would be [lookup_dimension, values_dimension], where
-   *      “lookup_dimension” corresponds to the indexing dimension in the lookup
-   *      table, and “values_dimension” to the contents.
-   * * 1: Lookups. An 1-D tensor of type T, of shape [lookup_size], where
-   *      “lookup_size” is the number of elements to look for, and each entry
-   *      corresponds to the first dimension of the “values” tensor.
-   *
-   * Output:
-   * * 0: A n-D tensor of type X and the same rank and shape as the “values”
-   *      tensor, except for the first dimension which has size “lookup_size”.
-   */
   ANEURALNETWORKS_EMBEDDING_LOOKUP = 7,
-
-  /** Computes element-wise floor() on the input tensor.
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   *
-   * Supported tensor rank: up to 4
-   *
-   * Inputs:
-   * * 0: A tensor.
-   *
-   * Outputs:
-   * * 0: The output, a tensor of the same type and dimensions as input0.
-   */
   ANEURALNETWORKS_FLOOR = 8,
-  /** Denotes a fully (densely) connected layer, which connects all elements in
-   * the input tensor with each element in the output tensor.
-   *
-   * This layer implements the operation:
-   *
-   *     outputs = activation(inputs * weights’ + bias)
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: up to 4.
-   *
-   * Inputs:
-   * * 0: A tensor, specifying the input. If rank is greater than 2, then it
-   * gets flattened to a 2-D Tensor. The 2-D Tensor is handled as if dimensions
-   * corresponded to shape [batch_size, input_size], where “batch_size”
-   * corresponds to the batching dimension, and “input_size” is the size of the
-   * input.
-   * * 1: A 2-D tensor, specifying the weights, of shape [num_units,
-   * input_size], where "num_units" corresponds to the number of output nodes.
-   * * 2: A 1-D tensor, of shape [num_units], specifying the bias.
-   *      For input tensor of {@link ANEURALNETWORKS_TENSOR_FLOAT32} type, the
-   * bias should also be of {@link ANEURALNETWORKS_TENSOR_FLOAT32}. For input
-   * tensor of {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM} type, the bias should
-   * be of {@link ANEURALNETWORKS_TENSOR_INT32}.
-   * * 3: An INT32 value, and has to be one of the {@link FuseCode} values.
-   *      Specifies the activation to invoke on the result of each addition.
-   *
-   * Outputs:
-   * * 0: The output tensor, of shape [batch_size, num_units].
-   */
   ANEURALNETWORKS_FULLY_CONNECTED = 9,
-
-  /**
-   * Looks up values of a hash table with given keys.
-   *
-   * Inputs:
-   * * 0: Lookups. A 1-D int32 tensor with shape [ k ].
-   * * 1: Keys. A 1-D int32 tensor with shape [ n ], *MUST* be sorted in
-   *      ascending order.
-   * * 2: Values. A tensor with shape [ n … ].
-   *
-   * Outputs:
-   * * 0: Output. A tensor with shape [ k …].
-   * * 1: Hits. A uint8 tensor with shape [ k ] indicates whether the lookup
-   *      hits or not.
-   */
   ANEURALNETWORKS_HASHTABLE_LOOKUP = 10,
-
-  /** Applies L2 normalization along the depth dimension.
-   *
-   * The values in the output tensor are computed as:
-   *
-   *     output[batch, row, col, channel] =
-   *         input[batch, row, col, channel] /
-   *         sqrt(sum_{c} pow(input[batch, row, col, c], 2))
-   *
-   * For x with more dimensions, independently normalizes each 1-D slice along
-   * dimension dim.
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   *
-   * Supported tensor rank: 4, with "NHWC" data layout.
-   *
-   * Inputs:
-   * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the
-   * input.
-   *
-   * Outputs:
-   * * 0: The output 4-D tensor, of shape [batches, out_height, out_width,
-   * depth].
-   */
   ANEURALNETWORKS_L2_NORMALIZATION = 11,
-
-  /** Performs an 2-D L2 pooling operation.
-   *
-   * The output dimensions are functions of the filter dimensions, stride, and
-   * padding.
-   *
-   * The values in the output tensor are computed as:
-   *
-   *     output[batch, row, col, channel] =
-   *         sqrt(sum_{i, j} pow(input[batch, row + i, col + j, channel], 2) /
-   * sum(1))
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   *
-   * Supported tensor rank: 4, with "NHWC" data layout.
-   *
-   * Inputs:
-   * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the
-   * input.
-   * * 1: An INT32 value, specifying the padding on the left, in the ‘width’
-   * dimension.
-   * * 2: An INT32 value, specifying the padding on the right,in the ‘width’
-   * dimension.
-   * * 3: An INT32 value, specifying the padding on the top, in the ‘height’
-   * dimension.
-   * * 4: An INT32 value, specifying the padding on the bottom, in the ‘height’
-   * dimension.
-   * * 5: An INT32 value, specifying the output stride in the ‘width’ dimension.
-   * * 6: An INT32 value, specifying the output stride in the ‘height’
-   * dimension.
-   * * 7: An INT32 value, specifying the filter width.
-   * * 8: An INT32 value, specifying the filter height.
-   * * 9: An INT32 value, and has to be one of the {@link FuseCode} values.
-   *      Specifies the activation to invoke on the result of each addition.
-   *
-   * Outputs:
-   * * 0: The output 4-D tensor, of shape [batches, out_height, out_width,
-   * depth].
-   */
   ANEURALNETWORKS_L2_POOL_2D = 12,
-  /** Applies Local Response Normalization along the depth dimension.
-   *
-   * The 4-D input tensor is treated as a 3-D array of 1-D vectors (along the
-   * last dimension), and each vector is normalized independently. Within a
-   * given vector, each component is divided by the weighted, squared sum of
-   * inputs within depth_radius.
-   *
-   * The output is calculated using this formula:
-   *
-   *     sqr_sum[a, b, c, d] =
-   *         sum(pow(input[a, b, c, d - depth_radius : d + depth_radius + 1], 2)
-   *     output = input / pow((bias + alpha * sqr_sum), beta)
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   *
-   * Supported tensor rank: 4, with "NHWC" data layout.
-   *
-   * Inputs:
-   * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the
-   * input.
-   * * 1: An INT32 value, specifying the radius of the normalization window.
-   * * 2: A FLOAT32 value, specifying the bias, must not be zero.
-   * * 3: A FLOAT32 value, specifying the scale factor, alpha.
-   * * 4: A FLOAT32 value, specifying the exponent, beta.
-   *
-   * Outputs:
-   * * 0: The output tensor of same shape as input0.
-   */
   ANEURALNETWORKS_LOCAL_RESPONSE_NORMALIZATION = 13,
-  /** Computes sigmoid activation on the input tensor element-wise.
-   *
-   * The output is calculated using this formula:
-   *
-   *     output = 1 / (1 + exp(-input))
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: up to 4.
-   *
-   * Inputs:
-   * * 0: A tensor, specifying the input.
-   *
-   * Outputs:
-   * * 0: The output tensor of same shape as input0.
-   */
   ANEURALNETWORKS_LOGISTIC = 14,
-
-  /**
-   * Projects an input to a bit vector via locality sensitive hashing.
-   *
-   * Inputs:
-   * * 0: Hash functions. Dim.size == 2, DataType: Float.
-   *            Tensor[0].Dim[0]: Number of hash functions.
-   *            Tensor[0].Dim[1]: Number of seeds per hash functions.
-   *            Tensor[0].Dim[1] <= 32 in sparse case.
-   *
-   * * 1: Input. Dim.size >= 1, no restriction on DataType.
-   * * 2: Weight. Optional. Dim.size == 1, DataType: Float.
-   *     If not set, each input element is considered to have the same weight of
-   *     1.0.
-   *     Tensor[1].Dim[0] == Tensor[2].Dim[0]
-   * * 3: Type:
-   *        Sparse: Value LSHProjectionType_SPARSE(=1).
-   *          Computed bit vector is considered to be sparse.
-   *          Each output element is an int32 made up of multiple bits computed
-   * from hash functions.
-   *
-   *        Dense: Value LSHProjectionType_DENSE(=2).
-   *          Computed bit vector is considered to be dense. Each output element
-   *          represents a bit and can take the value of either 0 or 1.
-   *
-   * Outputs:
-   * * 0: If the projection type is sparse:
-   *        Output.Dim == { Tensor[0].Dim[0] }
-   *        A tensor of int32 that represents hash signatures.
-   *      If the projection type is Dense:
-   *        Output.Dim == { Tensor[0].Dim[0] * Tensor[0].Dim[1] }
-   *        A flattened tensor that represents projected bit vectors.
-   */
   ANEURALNETWORKS_LSH_PROJECTION = 15,
-
-  /**
-   * Long short-term memory unit (LSTM) recurrent network layer.
-   *
-   * The default non-peephole implementation is based on:
-   * http://www.bioinf.jku.at/publications/older/2604.pdf
-   * S. Hochreiter and J. Schmidhuber. "Long Short-Term Memory". Neural
-   * Computation, 9(8):1735-1780, 1997.
-   *
-   * The peephole implementation is based on:
-   * https://research.google.com/pubs/archive/43905.pdf
-   * Hasim Sak, Andrew Senior, and Francoise Beaufays. "Long short-term memory
-   * recurrent neural network architectures for large scale acoustic modeling."
-   * INTERSPEECH, 2014.
-   *
-   * The coupling of input and forget gate (CIFG) is based on:
-   * http://arxiv.org/pdf/1503.04069.pdf
-   * Greff et al. "LSTM: A Search Space Odyssey"
-   *
-   * The class has the following independently optional inputs:
-   * * If input gate (if CIFG): “input_to_forget_weights”,
-   *   “recurrent_to_input_weights”, “cell_to_input_weights”, “input_gate_bias”.
-   * * If no peephole connections: “cell_to_input_weights”,
-   *   “cell_to_forget_weights”, “cell_to_output_weights”.
-   * * If no projection layer: “projection_weights” and “projection_bias”.
-   * * If no projection bias: “projection_bias”.
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   *
-   * Inputs:
-   * * 0: Input.
-   *      A 2-D tensor of type T, of shape [batch_size, input_size], where
-   *      “batch_size” corresponds to the batching dimension, and “input_size”
-   *      is the size of the input.
-   * * 1: input_to_input_weights.
-   *      A 2-D tensor of type T, of shape [num_units, input_size], where
-   *      “num_units” corresponds to the number of cell units.
-   * * 2: input_to_forget_weights.
-   *      A 2-D tensor of type T, of shape [num_units, input_size].
-   * * 3: input_to_cell_weights.
-   *      A 2-D tensor of type T, of shape [num_units, input_size].
-   * * 4: input_to_output_weights.
-   *      A 2-D tensor of type T, of shape [num_units, input_size].
-   * * 5: recurrent_to_input_weights.
-   *      A 2-D tensor of type T, of shape [num_units, output_size], where
-   *      “output_size” corresponds to either the number of cell units (i.e.,
-   *      “num_units”), or the second dimension of the “projection_weights”, if
-   *      defined.
-   * * 6: recurrent_to_forget_weights.
-   *      A 2-D tensor of type T, of shape [num_units, output_size].
-   * * 7: recurrent_to_cell_weights.
-   *      A 2-D tensor of type T, of shape [num_units, output_size].
-   * * 8: recurrent_to_output_weights.
-   *      A 2-D tensor of type T, of shape [num_units, output_size].
-   * * 9: cell_to_input_weights.
-   *      A 1-D tensor of type T, of shape [num_units].
-   * * 10:cell_to_forget_weights.
-   *      A 1-D tensor of type T, of shape [num_units].
-   * * 11:cell_to_output_weights.
-   *      A 1-D tensor of type T, of shape [num_units].
-   * * 12:input_gate_bias.
-   *      A 1-D tensor of type T, of shape [num_units].
-   * * 13:forget_gate_bias.
-   *      A 1-D tensor of type T, of shape [num_units].
-   * * 14:cell_bias.
-   *      A 1-D tensor of type T, of shape [num_units].
-   * * 15:output_gate_bias.
-   *      A 1-D tensor of type T, of shape [num_units].
-   * * 16:projection_weights.
-   *      A 2-D tensor of type T, of shape [output_size, num_units].
-   * * 17:projection_bias.
-   *      A 1-D tensor of type T, of shape [output_size].
-   *
-   * Parameters:
-   * * 18:fused_activation_function.
-   *      An (optional) ActivationFunctionType indicating the activation
-   *      function.
-   *      If “NONE” is specified then it results in a linear activation.
-   * * 19:cell_clip.
-   *      A clipping threshold for the cell state, such that values are bound
-   *      within [-cell_clip, cell_clip]. If set to 0.0 then clipping is
-   *      disabled.
-   * * 20:proj_clip.
-   *      A clipping threshold for the output from the projection layer, such
-   *      that values are bound within [-proj_clip, proj_clip]. If set to 0.0
-   *      then clipping is disabled.
-   *
-   * Outputs:
-   * * 0: scratch_buffer.
-   *      A 3-D tensor of type T, of shape [batch_size, num_cell, 4].
-   * * 1: output_state.
-   *      A 2-D tensor of type T, of shape [batch_size, output_size].
-   * * 2: cell_state.
-   *      A 2-D tensor of type T, of shape [batch_size, num_units].
-   * * 3: output.
-   *      A 2-D tensor of type T, of shape [batch_size, output_size]. This is
-   *      effectively the same as the current “output_state” value.
-   */
   ANEURALNETWORKS_LSTM = 16,
-
-  /** Performs an 2-D max pooling operation.
-   *
-   * The output dimensions are functions of the filter dimensions, stride, and
-   * padding.
-   *
-   * The values in the output tensor are computed as:
-   *
-   *     output[batch, row, col, channel] =
-   *         max_{i, j} (input[batch, row + i, col + j, channel])
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: 4, with "NHWC" data layout.
-   *
-   * Inputs:
-   * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the
-   * input.
-   * * 1: An INT32 value, specifying the padding on the left, in the ‘width’
-   * dimension.
-   * * 2: An INT32 value, specifying the padding on the right,in the ‘width’
-   * dimension.
-   * * 3: An INT32 value, specifying the padding on the top, in the ‘height’
-   * dimension.
-   * * 4: An INT32 value, specifying the padding on the bottom, in the ‘height’
-   * dimension.
-   * * 5: An INT32 value, specifying the output stride in the ‘width’ dimension.
-   * * 6: An INT32 value, specifying the output stride in the ‘height’
-   * dimension.
-   * * 7: An INT32 value, specifying the filter width.
-   * * 8: An INT32 value, specifying the filter height.
-   * * 9: An INT32 value, and has to be one of the {@link FuseCode} values.
-   *      Specifies the activation to invoke on the result of each addition.
-   *
-   * Outputs:
-   * * 0: The output 4-D tensor, of shape [batches, out_height, out_width,
-   * depth].
-   */
   ANEURALNETWORKS_MAX_POOL_2D = 17,
-
-  /** Multiplies two tensors, element-wise.
-   *
-   * Takes two input tensors of identical type and compatible dimensions. The
-   * output is the product of both input tensors, optionally modified by an
-   * activation function.
-   *
-   * Two dimensions are compatible when:
-   *     1. they are equal, or
-   *     2. one of them is 1
-   *
-   * The size of the resulting output is the maximum size along each dimension
-   * of the input operands. It starts with the trailing dimensions, and works
-   * its way forward.
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   *
-   * Supported tensor rank: up to 4
-   *
-   * Inputs:
-   * * 0: A tensor.
-   * * 1: A tensor of the same type, and compatible dimensions as input0.
-   * * 2: An INT32 value, and has to be one of the {@link FuseCode} values.
-   *      Specifies the activation to invoke on the result of each addition.
-   *
-   * Outputs:
-   * * 0: The product, a tensor of the same type as input0.
-   */
   ANEURALNETWORKS_MUL = 18,
-  /** Computes rectified linear activation on the input tensor element-wise.
-   *
-   * The output is calculated using this formula:
-   *
-   *     output = max(0, input)
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: up to 4.
-   *
-   * Inputs:
-   * * 0: A tensor, specifying the input.
-   *
-   * Outputs:
-   * * 0: The output tensor of same shape as input0.
-   */
   ANEURALNETWORKS_RELU = 19,
-  /** Computes rectified linear 1 activation on the input tensor element-wise.
-   *
-   * The output is calculated using this formula:
-   *
-   *     output = min(1.f, max(-1.f, input))
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: up to 4.
-   *
-   * Inputs:
-   * * 0: A tensor, specifying the input.
-   *
-   * Outputs:
-   * * 0: The output tensor of same shape as input0.
-   */
   ANEURALNETWORKS_RELU1 = 20,
-  /** Computes rectified linear 6 activation on the input tensor element-wise.
-   *
-   * The output is calculated using this formula:
-   *
-   *     output = min(6, max(0, input))
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: up to 4.
-   *
-   * Inputs:
-   * * 0: A tensor, specifying the input.
-   *
-   * Outputs:
-   * * 0: The output tensor of same shape as input0.
-   */
   ANEURALNETWORKS_RELU6 = 21,
-  /** Reshapes a tensor.
-   *
-   * Given tensor, this operation returns a tensor that has the same values as
-   * tensor, but with a newly specified shape.
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: up to 4.
-   *
-   * Inputs:
-   * * 0: A tensor, specifying the tensor to be reshaped.
-   * * 1: A 1-D tensor of type {@link ANEURALNETWORKS_TENSOR_INT32}, defining
-   * the shape of the output tensor. The number of elements implied by shape
-   * must be the same as the number of elements in the input tensor.
-   *
-   * Outputs:
-   * * 0: The output tensor, of shape specified by the input shape.
-   */
   ANEURALNETWORKS_RESHAPE = 22,
-  /** Resizes images to given size using the bilinear interpretation.
-   *
-   * Resized images will be distorted if their original aspect ratio is not the
-   * same as input.
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   *
-   * Supported tensor rank: 4, with "NHWC" data layout.
-   *
-   * Inputs:
-   * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the
-   * input.
-   * * 1: An INT32 value, specifying the output width of the output tensor.
-   * * 2: An INT32 value, specifying the output height of the output tensor.
-   *
-   * Outputs:
-   * * 0: The output 4-D tensor, of shape [batches, new_height, new_width,
-   * depth].
-   */
   ANEURALNETWORKS_RESIZE_BILINEAR = 23,
-
-  /**
-   * A basic recurrent neural network layer.
-   *
-   * This layer implements the operation:
-   * outputs = state = activation(inputs * input_weights + state *
-   * recurrent_weights + bias)
-   *
-   * Where:
-   * * “input_weights” is a weight matrix that multiplies the inputs;
-   * * “recurrent_weights” is a weight matrix that multiplies the current
-   *    “state” which itself is the output from the previous time step
-   *    computation;
-   * * “bias” is a bias vector (added to each output vector in the batch);
-   * * “activation” is the function passed as the “fused_activation_function”
-   *   argument (if not “NONE”).
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   *
-   * Inputs:
-   * * 0: input.
-   *      A 2-D tensor of type T, of shape [batch_size, input_size], where
-   *      “batch_size” corresponds to the batching dimension, and “input_size”
-   * is the size of the input.
-   * * 1: weights.
-   *      A 2-D tensor of type T, of shape [num_units, input_size], where
-   *      “num_units” corresponds to the number of units.
-   * * 2: recurrent_weights.
-   *      A 2-D tensor of type T, of shape [num_units, num_units], with columns
-   *      corresponding to the weights from each unit.
-   * * 3: bias.
-   *      A 1-D tensor of type T, of shape [num_units].
-   *
-   *    For FLOAT32 input tensor, bias must also be FLOAT32.
-   *    For UINT8 input tensor, bias must be INT32.
-   *
-   * Parameters
-   * * 4: fused_activation_function.
-   *      An (optional) ActivationFunctionType indicating the activation
-   *      function. If “NONE” is specified then it results in a linear
-   *      activation.
-   *
-   * * 5: Hidden state.
-   *      A 2-D tensor of type T, of shape [batch_size, num_units].
-   *
-   * Outputs:
-   * * 0: output.
-   *      A 2-D tensor of type T, of shape [batch_size, num_units]. This is
-   *      effectively the same as the current state value.
-   */
   ANEURALNETWORKS_RNN = 24,
-
-  /** Computes the softmax activation on the input tensor element-wise, per
-   * batch, by normalizing the input vector so the maximum coefficient is zero.
-   *
-   * The output is calculated using this formula:
-   *
-   *     output[batch, i] =
-   *         exp((input[batch, i] - max(input[batch, :])) * beta) /
-   *         sum_{k}{exp((input[batch, k] - max(input[batch, :])) * beta)}
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: 2 or 4.
-   *
-   * Inputs:
-   * * 0: A 2-D or 4-D tensor, specifying the tensor to be reshaped.
-   * * 1: A FLOAT32 value, specifying the scaling factor for the exponent, beta.
-   *
-   * Outputs:
-   * * 0: The output tensor of same shape as input0.
-   */
   ANEURALNETWORKS_SOFTMAX = 25,
-
-  /** Rearranges blocks of spatial data, into depth.
-   *
-   * More specifically, this op outputs a copy of the input tensor where values
-   * from the height and width dimensions are moved to the depth dimension. The
-   * value block_size indicates the input block size and how the data is moved.
-   *
-   * Chunks of data of size block_size * block_size from depth are rearranged
-   * into non-overlapping blocks of size block_size x block_size.
-   *
-   * The depth of the output tensor is input_depth * block_size * block_size.
-   * The input tensor's height and width must be divisible by block_size.
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-   *
-   * Supported tensor rank: 4, with "NHWC" data layout.
-   *
-   * Inputs:
-   * * 0: A 4-D tensor, of shape [batches, height, width, depth_in], specifying
-   * the input.
-   * * 1: An INT32 value, specifying the block_size. block_size must be >=1 and
-   *      block_size must be a divisor of both the input height and width.
-   *
-   * Outputs:
-   * * 0: The output 4-D tensor, of shape [batch, height/block_size,
-   * width/block_size, depth*block_size*block_size].
-   */
   ANEURALNETWORKS_SPACE_TO_DEPTH = 26,
-
-  /**
-   * SVDF op is a kind of stateful layer derived from the notion that a
-   * densely connected layer that's processing a sequence of input frames can
-   * be approximated by using a singular value decomposition of each of its
-   * nodes. The implementation is based on:
-   *
-   * https://research.google.com/pubs/archive/43813.pdf
-   *
-   * P. Nakkiran, R. Alvarez, R. Prabhavalkar, C. Parada.
-   * “Compressing Deep Neural Networks using a Rank-Constrained Topology”.
-   * INTERSPEECH, 2015.
-   *
-   * It processes the incoming input using a 2-stage filtering mechanism:
-   * * stage 1 performs filtering on the "features" dimension, whose outputs get
-   *   pushed into a memory of fixed-size memory_size.
-   * * stage 2 performs filtering on the "time" dimension of the memory_size
-   *   memoized outputs of stage 1.
-   *
-   * Specifically, for rank 1, this layer implements the operation:
-   *
-   *    memory = push(conv1d(inputs, weights_feature, feature_dim, "VALID"));
-   *    outputs = activation(memory * weights_time + bias);
-   *
-   * Where:
-   * * “weights_feature” is a weights matrix that processes the inputs (by
-   *   convolving the input with every “feature filter”), and whose outputs get
-   *   pushed, stacked in order, into the fixed-size “memory” (the oldest entry
-   *   gets dropped);
-   * * “weights_time” is a weights matrix that processes the “memory” (by a
-   *   batched matrix multiplication on the num_units);
-   * * “bias” is an optional bias vector (added to each output vector in the
-   *   batch); and
-   * * “activation” is the function passed as the “fused_activation_function”
-   *   argument (if not “NONE”).
-   *
-   * Each rank adds a dimension to the weights matrices by means of stacking
-   * the filters.
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   *
-   * Inputs:
-   * * 0: input.
-   *      A 2-D tensor of type T, of shape [batch_size, input_size], where
-   *      “batch_size” corresponds to the batching dimension, and “input_size”
-   * is the size of the input.
-   * * 1: weights_feature.
-   *      A 2-D tensor of type T, of shape [num_units, input_size], where
-   *      “num_units” corresponds to the number of units.
-   * * 2: weights_time.
-   *      A 2-D tensor of type T, of shape [num_units, memory_size], where
-   *      “memory_size” corresponds to the fixed-size of the memory.
-   * * 3: bias.
-   *      A optional 1-D tensor of type T, of shape [num_units].
-   *
-   *    For FLOAT32 input tensor, bias must also be FLOAT32.
-   *    For UINT8 input tensor, bias must be INT32.
-   *
-   * Parameters:
-   * * 4: rank.
-   *      The rank of the SVD approximation.
-   * * 5: fused_activation_function.
-   *      An (optional) ActivationFunctionType indicating the activation
-   * function. If “NONE” is specified then it results in a linear activation.
-   *
-   * Outputs:
-   * * 0: state.
-   *      A 2-D tensor of type T, of shape [batch_size, (memory_size - 1) *
-   * num_units * rank].
-   * * 1: output.
-   *      A 2-D tensor of type T, of shape [batch_size, num_units].
-   */
   ANEURALNETWORKS_SVDF = 27,
-
-  /** Computes hyperbolic tangent of input tensor element-wise.
-   *
-   * The output is calculated using this formula:
-   *
-   *     output = tanh(input)
-   *
-   * Supported tensor types:
-   * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
-   *
-   * Supported tensor rank: up to 4.
-   *
-   * Inputs:
-   * * 0: A tensor, specifying the input.
-   *
-   * Outputs:
-   * * 0: The output tensor of same shape as input0.
-   */
   ANEURALNETWORKS_TANH = 28,
+  ANEURALNETWORKS_BATCH_TO_SPACE_ND = 29,
+  ANEURALNETWORKS_DIV = 30,
+  ANEURALNETWORKS_MEAN = 31,
+  ANEURALNETWORKS_PAD = 32,
+  ANEURALNETWORKS_SPACE_TO_BATCH_ND = 33,
+  ANEURALNETWORKS_SQUEEZE = 34,
+  ANEURALNETWORKS_STRIDED_SLICE = 35,
+  ANEURALNETWORKS_SUB = 36,
+  ANEURALNETWORKS_TRANSPOSE = 37,
 };
 
 /**
@@ -1080,13 +137,9 @@ enum {
  *
  */
 enum {
-  /** NO fused activation function. */
   ANEURALNETWORKS_FUSED_NONE = 0,
-  /** Fused ReLU activation function. */
   ANEURALNETWORKS_FUSED_RELU = 1,
-  /** Fused ReLU1 activation function. */
   ANEURALNETWORKS_FUSED_RELU1 = 2,
-  /** Fused ReLU6 activation function. */
   ANEURALNETWORKS_FUSED_RELU6 = 3,
 };
 
@@ -1094,20 +147,8 @@ enum {
  * Execution preferences.
  */
 enum {
-  /**
-   * Prefer executing in a way that minimizes battery drain.
-   * This is desirable for compilations that will be executed often.
-   */
   ANEURALNETWORKS_PREFER_LOW_POWER = 0,
-  /**
-   * Prefer returning a single answer as fast as possible, even if this causes
-   * more power consumption.
-   */
   ANEURALNETWORKS_PREFER_FAST_SINGLE_ANSWER = 1,
-  /**
-   * Prefer maximizing the throughput of successive frames, for example when
-   * processing successive frames coming from the camera.
-   */
   ANEURALNETWORKS_PREFER_SUSTAINED_SPEED = 2,
 };
 
index 1810dfa..d99c88a 100644 (file)
@@ -23,6 +23,10 @@ limitations under the License.
 #include "tensorflow/contrib/lite/model.h"
 #include "tensorflow/contrib/lite/nnapi/NeuralNetworksShim.h"
 
+#ifdef __ANDROID__
+#include <sys/system_properties.h>
+#endif
+
 namespace tflite {
 
 // TODO(aselle): FATAL leaves resources hanging.
@@ -46,6 +50,32 @@ void FATAL(const char* format, ...) {
     FATAL("Aborting since tflite returned failure."); \
   }
 
+namespace {
+
+int32_t GetAndroidSdkVersion() {
+#ifdef __ANDROID__
+  const char* sdkProp = "ro.build.version.sdk";
+  char sdkVersion[PROP_VALUE_MAX];
+  int length = __system_property_get(sdkProp, sdkVersion);
+  if (length != 0) {
+    for (int i = 0; i < length; ++i) {
+      int digit = sdkVersion[i] - '0';
+      if (digit < 0 || digit > 9) {
+        // Non-numeric SDK version, assume it's higher then expected;
+        return 0xFFFF;
+      }
+    }
+    return atoi(sdkVersion);
+  }
+  FATAL("No %s prop", sdkProp);
+#endif  // __ANDROID__
+  return 0;
+}
+
+static const int32_t kAndroidSdkVersion = GetAndroidSdkVersion();
+
+}  // namespace
+
 NNAPIAllocation::NNAPIAllocation(const char* filename,
                                  ErrorReporter* error_reporter)
     : MMAPAllocation(filename, error_reporter) {
@@ -245,6 +275,11 @@ void AddOpsAndParams(tflite::Interpreter* interpreter,
       add_scalar_float32(builtin->proj_clip);
     };
 
+    auto add_mean_params = [&add_scalar_int32](void* data) {
+      auto builtin = reinterpret_cast<TfLiteMeanParams*>(data);
+      add_scalar_int32(builtin->keep_dims);
+    };
+
 #if 0
     auto add_reshape_params = [&](void* data) {
       auto builtin = reinterpret_cast<TfLiteReshapeParams*>(data);
@@ -262,8 +297,9 @@ void AddOpsAndParams(tflite::Interpreter* interpreter,
       augmented_inputs.push_back(next_id++);
     };
 #endif
-
+    int nnapi_version = 10;
     ANeuralNetworksOperationType nn_op_type;
+
     switch (builtin) {
       case tflite::BuiltinOperator_ADD:
         nn_op_type = ANEURALNETWORKS_ADD;
@@ -337,6 +373,23 @@ void AddOpsAndParams(tflite::Interpreter* interpreter,
         nn_op_type = ANEURALNETWORKS_LSTM;
         break;
       }
+      case tflite::BuiltinOperator_PAD:
+        nnapi_version = 11;  // require NNAPI 1.1
+        nn_op_type = ANEURALNETWORKS_PAD;
+        break;
+      case tflite::BuiltinOperator_MEAN:
+        nnapi_version = 11;  // require NNAPI 1.1
+        add_mean_params(node.builtin_data);
+        nn_op_type = ANEURALNETWORKS_MEAN;
+        break;
+      case tflite::BuiltinOperator_DIV:
+        nnapi_version = 11;  // require NNAPI 1.1
+        nn_op_type = ANEURALNETWORKS_DIV;
+        break;
+      case tflite::BuiltinOperator_SUB:
+        nnapi_version = 11;  // require NNAPI 1.1
+        nn_op_type = ANEURALNETWORKS_SUB;
+        break;
       case tflite::BuiltinOperator_CONCAT_EMBEDDINGS:
       case tflite::BuiltinOperator_LSH_PROJECTION:
       case tflite::BuiltinOperator_SVDF:
@@ -350,7 +403,6 @@ void AddOpsAndParams(tflite::Interpreter* interpreter,
       case tflite::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM:
       case tflite::BuiltinOperator_L2_NORMALIZATION:
       case tflite::BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION:
-      case tflite::BuiltinOperator_PAD:
       case tflite::BuiltinOperator_PADV2:
       case tflite::BuiltinOperator_RESIZE_BILINEAR:
       case tflite::BuiltinOperator_CALL:
@@ -361,9 +413,6 @@ void AddOpsAndParams(tflite::Interpreter* interpreter,
       case tflite::BuiltinOperator_BATCH_TO_SPACE_ND:
       case tflite::BuiltinOperator_TOPK_V2:
       case tflite::BuiltinOperator_TRANSPOSE:
-      case tflite::BuiltinOperator_MEAN:
-      case tflite::BuiltinOperator_DIV:
-      case tflite::BuiltinOperator_SUB:
       case tflite::BuiltinOperator_SPLIT:
       case tflite::BuiltinOperator_SQUEEZE:
       case tflite::BuiltinOperator_STRIDED_SLICE:
@@ -393,6 +442,10 @@ void AddOpsAndParams(tflite::Interpreter* interpreter,
         break;
     }
 
+    if (nnapi_version == 11 && kAndroidSdkVersion < 28) {
+      FATAL("Op %d needs NNAPI1.1", builtin);
+    }
+
     // Add the operation.
     CHECK_NN(ANeuralNetworksModel_addOperation(
         nn_model, nn_op_type, static_cast<uint32_t>(augmented_inputs.size()),