Add int16->float dequantization support to TFLM.
PiperOrigin-RevId: 301898643 Change-Id: I5fd46955f5fd952f12f2db65e11028ef473fc945
This commit is contained in:
parent
b9e1252bcb
commit
b51a23c95e
@ -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),
|
||||
|
@ -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};
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user