| 184 | } |
| 185 | |
| 186 | TfLiteStatus CheckOutputs(tflite::Interpreter* interpreter, |
| 187 | const Example& example) { |
| 188 | constexpr double kRelativeThreshold = 1e-2f; |
| 189 | constexpr double kAbsoluteThreshold = 1e-4f; |
| 190 | |
| 191 | ErrorReporter* context = DefaultErrorReporter(); |
| 192 | int model_outputs = interpreter->outputs().size(); |
| 193 | TF_LITE_ENSURE_EQ(context, model_outputs, example.outputs.size()); |
| 194 | for (size_t i = 0; i < interpreter->outputs().size(); i++) { |
| 195 | bool tensors_differ = false; |
| 196 | int output_index = interpreter->outputs()[i]; |
| 197 | if (const float* data = interpreter->typed_tensor<float>(output_index)) { |
| 198 | for (size_t idx = 0; idx < example.outputs[i].flat_data.size(); idx++) { |
| 199 | float computed = data[idx]; |
| 200 | float reference = example.outputs[0].flat_data[idx]; |
| 201 | float diff = std::abs(computed - reference); |
| 202 | // For very small numbers, try absolute error, otherwise go with |
| 203 | // relative. |
| 204 | bool local_tensors_differ = |
| 205 | std::abs(reference) < kRelativeThreshold |
| 206 | ? diff > kAbsoluteThreshold |
| 207 | : diff > kRelativeThreshold * std::abs(reference); |
| 208 | if (local_tensors_differ) { |
| 209 | fprintf(stdout, "output[%zu][%zu] did not match %f vs reference %f\n", |
| 210 | i, idx, data[idx], reference); |
| 211 | tensors_differ = local_tensors_differ; |
| 212 | } |
| 213 | } |
| 214 | } else if (const int32_t* data = |
| 215 | interpreter->typed_tensor<int32_t>(output_index)) { |
| 216 | for (size_t idx = 0; idx < example.outputs[i].flat_data.size(); idx++) { |
| 217 | int32_t computed = data[idx]; |
| 218 | int32_t reference = example.outputs[0].flat_data[idx]; |
| 219 | if (std::abs(computed - reference) > 0) { |
| 220 | fprintf(stderr, "output[%zu][%zu] did not match %d vs reference %d\n", |
| 221 | i, idx, computed, reference); |
| 222 | tensors_differ = true; |
| 223 | } |
| 224 | } |
| 225 | } else if (const int64_t* data = |
| 226 | interpreter->typed_tensor<int64_t>(output_index)) { |
| 227 | for (size_t idx = 0; idx < example.outputs[i].flat_data.size(); idx++) { |
| 228 | int64_t computed = data[idx]; |
| 229 | int64_t reference = example.outputs[0].flat_data[idx]; |
| 230 | if (std::abs(computed - reference) > 0) { |
| 231 | fprintf(stderr, |
| 232 | "output[%zu][%zu] did not match %" PRId64 |
| 233 | " vs reference %" PRId64 "\n", |
| 234 | i, idx, computed, reference); |
| 235 | tensors_differ = true; |
| 236 | } |
| 237 | } |
| 238 | } else { |
| 239 | fprintf(stderr, "output[%zu] was not float or int data\n", i); |
| 240 | return kTfLiteError; |
| 241 | } |
| 242 | fprintf(stderr, "\n"); |
| 243 | if (tensors_differ) return kTfLiteError; |
no test coverage detected