MCPcopy Create free account
hub / github.com/DeepRec-AI/DeepRec / ApplyConstraints

Function ApplyConstraints

tensorflow/lite/tools/optimize/quantize_model.cc:263–333  ·  view source on GitHub ↗

Apply constraints to ops if they have any. We have made the restriction that for int8 quantized concat, the inputs and outpus must have the same scale and zero point. The other ones with constraints(averagepool, maxpool, gather, softmax, tanh etc) are handled in QuantizeWeightsAndInput.

Source from the content-addressed store, hash-verified

261// constraints(averagepool, maxpool, gather, softmax, tanh etc) are handled in
262// QuantizeWeightsAndInput.
263TfLiteStatus ApplyConstraints(ModelT* model, ErrorReporter* error_reporter) {
264 for (int subgraph_idx = 0; subgraph_idx < model->subgraphs.size();
265 subgraph_idx++) {
266 SubGraphT* subgraph = model->subgraphs.at(subgraph_idx).get();
267 // Iterate backward to avoid messing with index.
268 for (int op_idx = subgraph->operators.size() - 1; op_idx >= 0; op_idx--) {
269 OperatorT* op = subgraph->operators[op_idx].get();
270 const BuiltinOperator op_code =
271 model->operator_codes[op->opcode_index]->builtin_code;
272 operator_property::OperatorProperty property =
273 operator_property::GetOperatorProperty(op_code);
274 if (!property.quantizable) {
275 continue;
276 }
277 // Basically only Concat passes this check.
278 if (!property.restrict_same_input_output_scale ||
279 (property.inputs.size() == 1 && property.outputs.size() == 1 &&
280 property.biases.empty())) {
281 continue;
282 }
283 // If ApplyConstraints and requant is needed, use the min of min and max
284 // of max, which means using the scale and zero point of output.
285 TensorT* output_tensor = subgraph->tensors[op->outputs[0]].get();
286 if (!utils::QuantizationParametersExist(output_tensor)) {
287 error_reporter->Report(
288 "Unable to get scale or zero point from the tensor at %d, which "
289 "is the output tensor for concat.",
290 op->outputs[0]);
291 return kTfLiteError;
292 }
293 const float output_scale = output_tensor->quantization->scale[0];
294 const float output_zp = output_tensor->quantization->zero_point[0];
295 for (size_t input_idx = 0; input_idx < op->inputs.size(); ++input_idx) {
296 TensorT* input_tensor = subgraph->tensors[op->inputs[input_idx]].get();
297 if (!utils::QuantizationParametersExist(input_tensor)) {
298 error_reporter->Report(
299 "Unable to get scale or zero point from tensor at %d, which is "
300 "an input tensor of concat.",
301 op->inputs[input_idx]);
302 return kTfLiteError;
303 }
304 if (input_tensor->quantization->scale[0] == output_scale &&
305 input_tensor->quantization->zero_point[0] == output_zp) {
306 // This input does not need to be requantized.
307 continue;
308 }
309
310 std::unique_ptr<TensorT> additional_tensor;
311 const string requant_tensor_name = input_tensor->name + "_requantized";
312 utils::MakeTensorWithQuantParam(
313 requant_tensor_name, input_tensor->shape, TensorType_INT8,
314 output_scale, output_zp, &additional_tensor);
315 const int32_t additional_tensor_idx = subgraph->tensors.size();
316 subgraph->tensors.push_back(std::move(additional_tensor));
317
318 // Add requant op before this input.
319 // There are better ways to handle this, which is to try to push the
320 // rescale upwards recurrsively and hope all upstream ops can absort

Callers 1

QuantizeModelFunction · 0.85

Calls 12

GetOperatorPropertyFunction · 0.85
MakeTensorWithQuantParamFunction · 0.85
MakeQuantizeOperatorFunction · 0.85
sizeMethod · 0.45
getMethod · 0.45
atMethod · 0.45
emptyMethod · 0.45
ReportMethod · 0.45
push_backMethod · 0.45
insertMethod · 0.45
beginMethod · 0.45

Tested by

no test coverage detected