32 #pragma GCC diagnostic push
33 #pragma GCC diagnostic ignored "-Wunused-parameter"
35 #pragma GCC diagnostic pop
36 #include "utils/Utils.h"
46 std::pair<arm_compute::TensorShape, arm_compute::PermutationVector>
53 if (
shape.num_dimensions() > 2)
64 return std::make_pair(permuted_shape, perm);
75 preprocess_typed<float>(
tensor);
79 preprocess_typed<half>(
tensor);
93 const float range = _max_range - _min_range;
97 const T value = *
reinterpret_cast<T *
>(
tensor.ptr_to_element(
id));
98 float res = value / 255.f;
99 res = res *
range + _min_range;
100 *
reinterpret_cast<T *
>(
tensor.ptr_to_element(
id)) = res;
105 : _mean(mean), _bgr(bgr), _scale(
scale)
117 preprocess_typed<float>(
tensor);
121 preprocess_typed<half>(
tensor);
129 template <
typename T>
141 *
reinterpret_cast<T *
>(
tensor.ptr_to_element(
id)) = value * T(_scale);
151 std::stringstream
ss;
152 ss << _name << _iterator <<
".ppm";
161 return _iterator < _maximum;
176 bool ret = _maximum == 0 || _iterator < _maximum;
177 if (_iterator == _maximum)
190 : _npy_tensor(), _filename(std::move(npy_path)), _output_stream(output_stream)
203 template <
typename T>
204 void NumPyAccessor::access_numpy_tensor(
ITensor &
tensor, T tolerance)
206 const int num_elements =
tensor.info()->tensor_shape().total_size();
207 int num_mismatches = utils::compare_tensor<T>(
tensor, _npy_tensor, tolerance);
208 float percentage_mismatches =
static_cast<float>(num_mismatches) / num_elements;
210 _output_stream <<
"Results: " << 100.f - (percentage_mismatches * 100) <<
" % matches with the provided output["
211 << _filename <<
"]." << std::endl;
212 _output_stream <<
" " << num_elements - num_mismatches <<
" out of " << num_elements
213 <<
" matches with the provided output[" << _filename <<
"]." << std::endl
222 switch (
tensor.info()->data_type())
225 access_numpy_tensor<qasymm8_t>(
tensor, 0);
228 access_numpy_tensor<float>(
tensor, 0.0001f);
237 #ifdef ARM_COMPUTE_ASSERTS_ENABLED
239 : _output_stream(output_stream), _io_fmt(io_fmt)
245 tensor.print(_output_stream, _io_fmt);
251 : _npy_name(std::move(npy_name)), _is_fortran(is_fortran)
265 : _already_loaded(false), _filename(std::move(filename)), _bgr(bgr), _preprocessor(std::move(preprocessor))
271 if (!_already_loaded)
277 image_loader->open(_filename);
284 std::tie(permuted_shape, perm) =
285 compute_permutation_parameters(
tensor.info()->tensor_shape(),
tensor.info()->data_layout());
290 image_loader->width() != permuted_shape.
x() || image_loader->height() != permuted_shape.
y(),
291 "Failed to load image file: dimensions [%d,%d] not correct, expected [%" PRIu32
",%" PRIu32
"].",
292 image_loader->width(), image_loader->height(), permuted_shape.
x(), permuted_shape.
y());
295 image_loader->width() != permuted_shape.
x() || image_loader->height() != permuted_shape.
y(),
296 "Failed to load image file: dimensions [%d,%d] not correct, expected [%" PRIu64
",%" PRIu64
"].",
297 image_loader->width(), image_loader->height(),
static_cast<uint64_t
>(permuted_shape.
x()),
298 static_cast<uint64_t
>(permuted_shape.
y()));
302 image_loader->fill_planar_tensor(
tensor, _bgr);
307 _preprocessor->preprocess(
tensor);
311 _already_loaded = !_already_loaded;
312 return _already_loaded;
316 std::string images_path,
317 std::unique_ptr<IPreprocessor> preprocessor,
321 std::ostream &output_stream)
322 : _path(std::move(images_path)),
324 _preprocessor(std::move(preprocessor)),
327 _output_stream(output_stream)
334 ifs.exceptions(std::ifstream::badbit);
335 ifs.open(image_list, std::ios::in | std::ios::binary);
338 unsigned int counter = 0;
339 for (std::string line; !std::getline(ifs, line).fail() && counter <=
end; ++counter)
342 if (counter >= start)
344 std::stringstream linestream(line);
345 std::string image_name;
347 linestream >> image_name;
348 _images.emplace_back(std::move(image_name));
352 catch (
const std::ifstream::failure &e)
360 bool ret = _offset < _images.size();
366 std::string image_name = _path + _images[_offset++];
367 jpeg.
open(image_name);
368 _output_stream <<
"[" << _offset <<
"/" << _images.size() <<
"] Validating " << image_name << std::endl;
375 std::tie(permuted_shape, perm) =
376 compute_permutation_parameters(
tensor.info()->tensor_shape(),
tensor.info()->data_layout());
381 "Failed to load image file: dimensions [%d,%d] not correct, expected [%" PRIu32
383 jpeg.
width(), jpeg.
height(), permuted_shape.
x(), permuted_shape.
y());
386 "Failed to load image file: dimensions [%d,%d] not correct, expected [%" PRIu64
388 jpeg.
width(), jpeg.
height(),
static_cast<uint64_t
>(permuted_shape.
x()),
389 static_cast<uint64_t
>(permuted_shape.
y()));
398 _preprocessor->preprocess(
tensor);
406 std::ostream &output_stream,
409 : _results(), _output_stream(output_stream), _offset(0), _positive_samples_top1(0), _positive_samples_top5(0)
416 ifs.exceptions(std::ifstream::badbit);
417 ifs.open(image_list, std::ios::in | std::ios::binary);
420 unsigned int counter = 0;
421 for (std::string line; !std::getline(ifs, line).fail() && counter <=
end; ++counter)
424 if (counter >= start)
426 std::stringstream linestream(line);
427 std::string image_name;
430 linestream >> image_name >> result;
431 _results.emplace_back(result);
435 catch (
const std::ifstream::failure &e)
444 _positive_samples_top1 = 0;
445 _positive_samples_top5 = 0;
450 bool ret = _offset < _results.size();
454 std::vector<size_t> tensor_results;
455 switch (
tensor.info()->data_type())
458 tensor_results = access_predictions_tensor<uint8_t>(
tensor);
461 tensor_results = access_predictions_tensor<half>(
tensor);
464 tensor_results = access_predictions_tensor<float>(
tensor);
471 size_t correct_label = _results[_offset++];
473 aggregate_sample(tensor_results, _positive_samples_top1, 1, correct_label);
474 aggregate_sample(tensor_results, _positive_samples_top5, 5, correct_label);
478 if (_offset >= _results.size())
480 report_top_n(1, _results.size(), _positive_samples_top1);
481 report_top_n(5, _results.size(), _positive_samples_top5);
487 template <
typename T>
491 std::vector<size_t> index;
493 const auto output_net =
reinterpret_cast<T *
>(
tensor.buffer() +
tensor.info()->offset_first_element_in_bytes());
494 const size_t num_classes =
tensor.info()->dimension(0);
496 index.resize(num_classes);
499 std::iota(std::begin(index),
std::end(index),
static_cast<size_t>(0));
500 std::sort(std::begin(index),
std::end(index), [&](
size_t a,
size_t b) {
return output_net[a] > output_net[
b]; });
505 void ValidationOutputAccessor::aggregate_sample(
const std::vector<size_t> &res,
506 size_t &positive_samples,
508 size_t correct_label)
510 auto is_valid_label = [correct_label](
size_t label) {
return label == correct_label; };
512 if (std::any_of(std::begin(res), std::begin(res) + top_n, is_valid_label))
518 void ValidationOutputAccessor::report_top_n(
size_t top_n,
size_t total_samples,
size_t positive_samples)
520 size_t negative_samples = total_samples - positive_samples;
521 float accuracy = positive_samples /
static_cast<float>(total_samples);
523 _output_stream <<
"----------Top " << top_n <<
" accuracy ----------" << std::endl << std::endl;
524 _output_stream <<
"Positive samples : " << positive_samples << std::endl;
525 _output_stream <<
"Negative samples : " << negative_samples << std::endl;
526 _output_stream <<
"Accuracy : " << accuracy << std::endl;
530 std::vector<TensorShape> &imgs_tensor_shapes,
531 std::ostream &output_stream)
532 : _labels(), _tensor_shapes(std::move(imgs_tensor_shapes)), _output_stream(output_stream)
540 ifs.exceptions(std::ifstream::badbit);
541 ifs.open(labels_path, std::ios::in | std::ios::binary);
543 for (std::string line; !std::getline(ifs, line).fail();)
545 _labels.emplace_back(line);
548 catch (
const std::ifstream::failure &e)
554 template <
typename T>
555 void DetectionOutputAccessor::access_predictions_tensor(
ITensor &
tensor)
557 const size_t num_detection =
tensor.info()->valid_region().shape.y();
558 const auto output_prt =
reinterpret_cast<T *
>(
tensor.buffer() +
tensor.info()->offset_first_element_in_bytes());
560 if (num_detection > 0)
562 _output_stream <<
"---------------------- Detections ----------------------" << std::endl << std::endl;
564 _output_stream << std::left << std::setprecision(4) << std::setw(8) <<
"Image | " << std::setw(8) <<
"Label | "
565 << std::setw(12) <<
"Confidence | "
566 <<
"[ xmin, ymin, xmax, ymax ]" << std::endl;
568 for (
size_t i = 0; i < num_detection; ++i)
570 auto im =
static_cast<const int>(output_prt[i * 7]);
571 _output_stream << std::setw(8) << im << std::setw(8) << _labels[output_prt[i * 7 + 1]] << std::setw(12)
572 << output_prt[i * 7 + 2] <<
" [" << (output_prt[i * 7 + 3] * _tensor_shapes[im].x()) <<
", "
573 << (output_prt[i * 7 + 4] * _tensor_shapes[im].y()) <<
", "
574 << (output_prt[i * 7 + 5] * _tensor_shapes[im].x()) <<
", "
575 << (output_prt[i * 7 + 6] * _tensor_shapes[im].y()) <<
"]" << std::endl;
580 _output_stream <<
"No detection found." << std::endl;
588 switch (
tensor.info()->data_type())
591 access_predictions_tensor<float>(
tensor);
602 std::ostream &output_stream)
603 : _labels(), _output_stream(output_stream), _top_n(top_n)
611 ifs.exceptions(std::ifstream::badbit);
612 ifs.open(labels_path, std::ios::in | std::ios::binary);
614 for (std::string line; !std::getline(ifs, line).fail();)
616 _labels.emplace_back(line);
619 catch (
const std::ifstream::failure &e)
625 template <
typename T>
626 void TopNPredictionsAccessor::access_predictions_tensor(
ITensor &
tensor)
629 std::vector<T> classes_prob;
630 std::vector<size_t> index;
632 const auto output_net =
reinterpret_cast<T *
>(
tensor.buffer() +
tensor.info()->offset_first_element_in_bytes());
633 const size_t num_classes =
tensor.info()->dimension(0);
635 classes_prob.resize(num_classes);
636 index.resize(num_classes);
638 std::copy(output_net, output_net + num_classes, classes_prob.begin());
641 std::iota(std::begin(index),
std::end(index),
static_cast<size_t>(0));
642 std::sort(std::begin(index),
std::end(index),
643 [&](
size_t a,
size_t b) {
return classes_prob[a] > classes_prob[
b]; });
645 _output_stream <<
"---------- Top " << _top_n <<
" predictions ----------" << std::endl << std::endl;
646 for (
size_t i = 0; i < _top_n; ++i)
648 _output_stream << std::fixed << std::setprecision(4) << +classes_prob[index.at(i)] <<
" - [id = " << index.at(i)
650 <<
", " << _labels[index.at(i)] << std::endl;
659 switch (
tensor.info()->data_type())
662 access_predictions_tensor<uint8_t>(
tensor);
665 access_predictions_tensor<float>(
tensor);
675 : _lower(lower), _upper(upper), _seed(seed)
679 template <
typename T,
typename D>
682 std::mt19937 gen(_seed);
689 *
reinterpret_cast<T *
>(
tensor.buffer() +
offset) = value;
699 [&](
const Coordinates &
id)
702 *
reinterpret_cast<T *
>(
tensor.ptr_to_element(
id)) = value;
709 switch (
tensor.info()->data_type())
714 std::uniform_int_distribution<uint8_t> distribution_u8(_lower.
get<uint8_t>(), _upper.
get<uint8_t>());
715 fill<uint8_t>(
tensor, distribution_u8);
720 std::uniform_int_distribution<int8_t> distribution_s8(_lower.
get<int8_t>(), _upper.
get<int8_t>());
721 fill<int8_t>(
tensor, distribution_s8);
726 std::uniform_int_distribution<uint16_t> distribution_u16(_lower.
get<uint16_t>(), _upper.
get<uint16_t>());
727 fill<uint16_t>(
tensor, distribution_u16);
732 std::uniform_int_distribution<int16_t> distribution_s16(_lower.
get<int16_t>(), _upper.
get<int16_t>());
733 fill<int16_t>(
tensor, distribution_s16);
738 std::uniform_int_distribution<uint32_t> distribution_u32(_lower.
get<uint32_t>(), _upper.
get<uint32_t>());
739 fill<uint32_t>(
tensor, distribution_u32);
744 std::uniform_int_distribution<int32_t> distribution_s32(_lower.
get<int32_t>(), _upper.
get<int32_t>());
745 fill<int32_t>(
tensor, distribution_s32);
750 std::uniform_int_distribution<uint64_t> distribution_u64(_lower.
get<uint64_t>(), _upper.
get<uint64_t>());
751 fill<uint64_t>(
tensor, distribution_u64);
756 std::uniform_int_distribution<int64_t> distribution_s64(_lower.
get<int64_t>(), _upper.
get<int64_t>());
757 fill<int64_t>(
tensor, distribution_s64);
763 _upper.
get<
float>());
764 fill<half>(
tensor, distribution_f16);
769 std::uniform_real_distribution<float> distribution_f32(_lower.
get<
float>(), _upper.
get<
float>());
770 fill<float>(
tensor, distribution_f32);
775 std::uniform_real_distribution<double> distribution_f64(_lower.
get<
double>(), _upper.
get<
double>());
776 fill<double>(
tensor, distribution_f64);
786 : _already_loaded(false), _filename(std::move(filename)), _file_layout(file_layout)
792 if (!_already_loaded)
795 loader.
open(_filename, _file_layout);
799 _already_loaded = !_already_loaded;
800 return _already_loaded;