Add int16->float dequantization support to TFLM.

PiperOrigin-RevId: 301898643
Change-Id: I5fd46955f5fd952f12f2db65e11028ef473fc945
This commit is contained in:
Robert David 2020-03-19 14:43:29 -07:00 committed by TensorFlower Gardener
parent b9e1252bcb
commit b51a23c95e
6 changed files with 62 additions and 30 deletions

View File

@ -65,6 +65,11 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
op_params, GetTensorShape(input), GetTensorData<int8_t>(input),
GetTensorShape(output), GetTensorData<float>(output));
break;
case kTfLiteInt16:
reference_ops::Dequantize(
op_params, GetTensorShape(input), GetTensorData<int16_t>(input),
GetTensorShape(output), GetTensorData<float>(output));
break;
default:
TF_LITE_KERNEL_LOG(context, "Input %s, output %s not supported.",
TfLiteTypeGetName(input->type),

View File

@ -158,6 +158,19 @@ TF_LITE_MICRO_TEST(DequantizeOpTestInt8) {
zero_point, dims, values, output);
}
TF_LITE_MICRO_TEST(DequantizeOpTestInt16) {
const int length = 10;
const int dims[] = {2, 5, 2};
const float values[] = {-63.5, -63, -62.5, -62, -61.5,
62, 62.5, 63, 63.5, 64};
const float scale = 0.5;
const int zero_point = -1;
int16_t input_quantized[length];
float output[length];
tflite::testing::TestDequantizeToFloat(dims, values, input_quantized, scale,
zero_point, dims, values, output);
}
TF_LITE_MICRO_TEST(DequantizeOpTestInt8ToInt32) {
const int length = 10;
const int dims[] = {2, 5, 2};

View File

@ -34,6 +34,7 @@ static const int8_t kAsymmetricInt8Min = INT8_MIN;
static const int8_t kAsymmetricInt8Max = INT8_MAX;
static const int kSymmetricInt8Scale = kAsymmetricInt8Max;
static const int16_t kAsymmetricInt16Min = INT16_MIN;
static const int16_t kAsymmetricInt16Max = INT16_MAX;
static const int kSymmetricInt16Scale = kAsymmetricInt16Max;
@ -76,9 +77,26 @@ uint8_t FloatToSymmetricQuantizedUInt8(const float value, const float scale) {
int8_t FloatToAsymmetricQuantizedInt8(const float value, const float scale,
const int zero_point) {
return FloatToAsymmetricQuantizedUInt8(value, scale,
zero_point - kAsymmetricInt8Min) +
kAsymmetricInt8Min;
int32_t result = round(value / scale) + zero_point;
if (result < kAsymmetricInt8Min) {
result = kAsymmetricInt8Min;
}
if (result > kAsymmetricInt8Max) {
result = kAsymmetricInt8Max;
}
return result;
}
int16_t FloatToAsymmetricQuantizedInt16(const float value, const float scale,
const int zero_point) {
int32_t result = round(value / scale) + zero_point;
if (result < kAsymmetricInt16Min) {
result = kAsymmetricInt16Min;
}
if (result > kAsymmetricInt16Max) {
result = kAsymmetricInt16Max;
}
return result;
}
int8_t FloatToSymmetricQuantizedInt8(const float value, const float scale) {
@ -110,6 +128,13 @@ void AsymmetricQuantize(const float* input, uint8_t* output, int num_elements,
}
}
void AsymmetricQuantize(const float* input, int16_t* output, int num_elements,
float scale, int zero_point) {
for (int i = 0; i < num_elements; i++) {
output[i] = FloatToAsymmetricQuantizedInt16(input[i], scale, zero_point);
}
}
void SymmetricQuantize(const float* input, int32_t* output, int num_elements,
float scale) {
for (int i = 0; i < num_elements; i++) {

View File

@ -34,6 +34,9 @@ uint8_t FloatToSymmetricQuantizedUInt8(const float value, const float scale);
int8_t FloatToAsymmetricQuantizedInt8(const float value, const float scale,
const int zero_point);
int16_t FloatToAsymmetricQuantizedInt16(const float value, const float scale,
const int zero_point);
int8_t FloatToSymmetricQuantizedInt8(const float value, const float scale);
// Converts a float value into a signed thirty-two-bit quantized value. Note
@ -47,6 +50,7 @@ int32_t FloatToSymmetricQuantizedInt32(const float value, const float scale);
// asymmetric symmetric per channel
// int8 | X | X | X |
// uint8 | X | X | |
// int16 | X | | |
// int32 | | X | X |
//
// The per-op quantization spec can be found here:
@ -58,6 +62,9 @@ void AsymmetricQuantize(const float* input, int8_t* output, int num_elements,
void AsymmetricQuantize(const float* input, uint8_t* output, int num_elements,
float scale, int zero_point = 128);
void AsymmetricQuantize(const float* input, int16_t* output, int num_elements,
float scale, int zero_point = 0);
void SymmetricQuantize(const float* input, int32_t* output, int num_elements,
float scale);

View File

@ -676,17 +676,6 @@ TfLiteTensor CreateQuantizedTensor(const uint8_t* data, TfLiteIntArray* dims,
return result;
}
// Create Quantized tensor which contains a quantized version of the supplied
// buffer.
TfLiteTensor CreateQuantizedTensor(const float* input, uint8_t* quantized,
TfLiteIntArray* dims, float scale,
int zero_point, const char* name,
bool is_variable) {
int input_size = ElementCount(*dims);
tflite::AsymmetricQuantize(input, quantized, input_size, scale, zero_point);
return CreateQuantizedTensor(quantized, dims, scale, zero_point, name);
}
TfLiteTensor CreateQuantizedTensor(const int8_t* data, TfLiteIntArray* dims,
float scale, int zero_point,
const char* name, bool is_variable) {
@ -711,15 +700,6 @@ TfLiteTensor CreateQuantizedTensor(const int16_t* data, TfLiteIntArray* dims,
return result;
}
TfLiteTensor CreateQuantizedTensor(const float* input, int8_t* quantized,
TfLiteIntArray* dims, float scale,
int zero_point, const char* name,
bool is_variable) {
int input_size = ElementCount(*dims);
tflite::AsymmetricQuantize(input, quantized, input_size, scale, zero_point);
return CreateQuantizedTensor(quantized, dims, scale, zero_point, name);
}
TfLiteTensor CreateQuantized32Tensor(const int32_t* data, TfLiteIntArray* dims,
float scale, const char* name,
bool is_variable) {

View File

@ -21,6 +21,7 @@ limitations under the License.
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/core/api/error_reporter.h"
#include "tensorflow/lite/kernels/internal/compatibility.h"
#include "tensorflow/lite/micro/micro_utils.h"
#include "tensorflow/lite/schema/schema_generated.h"
namespace tflite {
@ -83,11 +84,6 @@ TfLiteTensor CreateQuantizedTensor(const uint8_t* data, TfLiteIntArray* dims,
float scale, int zero_point,
const char* name, bool is_variable = false);
TfLiteTensor CreateQuantizedTensor(const float* input, uint8_t* quantized,
TfLiteIntArray* dims, float scale,
int zero_point, const char* name,
bool is_variable = false);
TfLiteTensor CreateQuantizedTensor(const int8_t* data, TfLiteIntArray* dims,
float scale, int zero_point,
const char* name, bool is_variable = false);
@ -96,10 +92,16 @@ TfLiteTensor CreateQuantizedTensor(const int16_t* data, TfLiteIntArray* dims,
float scale, int zero_point,
const char* name, bool is_variable = false);
TfLiteTensor CreateQuantizedTensor(const float* input, int8_t* quantized,
template <typename T>
TfLiteTensor CreateQuantizedTensor(const float* input, T* quantized,
TfLiteIntArray* dims, float scale,
int zero_point, const char* name,
bool is_variable = false);
bool is_variable = false) {
int input_size = ElementCount(*dims);
tflite::AsymmetricQuantize(input, quantized, input_size, scale, zero_point);
return CreateQuantizedTensor(quantized, dims, scale, zero_point, name,
is_variable);
}
TfLiteTensor CreateQuantizedBiasTensor(const float* data, int32_t* quantized,
TfLiteIntArray* dims, float input_scale,