| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include "edge-impulse-sdk/tensorflow/lite/micro/micro_utils.h" |
|
|
| #include <cmath> |
| #include <cstdint> |
| #include <limits> |
|
|
| #include "edge-impulse-sdk/tensorflow/lite/c/common.h" |
| #include "edge-impulse-sdk/tensorflow/lite/kernels/internal/compatibility.h" |
| #include "edge-impulse-sdk/tensorflow/lite/kernels/op_macros.h" |
| #include "edge-impulse-sdk/tensorflow/lite/micro/memory_helpers.h" |
| #include "edge-impulse-sdk/tensorflow/lite/micro/micro_log.h" |
|
|
| namespace tflite { |
|
|
| int ElementCount(const TfLiteIntArray& dims) { |
| int result = 1; |
| for (int i = 0; i < dims.size; ++i) { |
| result *= dims.data[i]; |
| } |
| return result; |
| } |
|
|
| size_t EvalTensorBytes(const TfLiteEvalTensor* tensor) { |
| size_t bytes_per_element; |
| TFLITE_DCHECK(kTfLiteOk == |
| TfLiteTypeSizeOf(tensor->type, &bytes_per_element)); |
| return ElementCount(*tensor->dims) * bytes_per_element; |
| } |
|
|
| void SignedSymmetricPerChannelQuantize( |
| const float* values, TfLiteIntArray* dims, int quantized_dimension, |
| int8_t* quantized_values, float* scaling_factors, TfLiteType type) { |
| int input_size = ElementCount(*dims); |
| int channel_count = dims->data[quantized_dimension]; |
| int per_channel_size = input_size / channel_count; |
|
|
| int stride; |
| int channel_stride; |
|
|
| int qmin = QMinFromTfLiteType(type); |
| int qmax = QMaxFromTfLiteType(type); |
|
|
| if (quantized_dimension == 0) { |
| stride = 1; |
| channel_stride = per_channel_size; |
| } else if (quantized_dimension == 3) { |
| stride = channel_count; |
| channel_stride = 1; |
| } else { |
| MicroPrintf("quantized dimension must be 0 or 3"); |
| TFLITE_ABORT; |
| } |
|
|
| |
| for (int channel = 0; channel < channel_count; channel++) { |
| float min = 0; |
| float max = 0; |
|
|
| for (int i = 0; i < per_channel_size; i++) { |
| int idx = channel * channel_stride + i * stride; |
| min = fminf(min, values[idx]); |
| max = fmaxf(max, values[idx]); |
| } |
| scaling_factors[channel] = fmaxf(fabs(min), fabs(max)) / qmax; |
| for (int i = 0; i < per_channel_size; i++) { |
| int idx = channel * channel_stride + i * stride; |
| const int32_t quantized_value = |
| static_cast<int32_t>(roundf(values[idx] / scaling_factors[channel])); |
| |
| quantized_values[idx] = fminf(qmax, fmaxf(qmin + 1, quantized_value)); |
| } |
| } |
| } |
|
|
| } |
|
|