Класс tensorflow::Tensor
позволяет получить доступ к его содержимому несколькими способами.С .flat
вы получаете плоскую версию массива, .tensor
дает вам полный Собственный тензор , а затем есть несколько других, таких как .vec
/ .matrix
(например, .tensor
счисло измерений, зафиксированное в 1 или 2) и flat_inner_dims
/ flat_outer_dims
/ flat_inner_outer_dims
(дает тензор с некоторыми свернутыми размерами).Вы можете использовать тот, который подходит вам лучше всего.В этом случае, например, если вы хотите напечатать все значения в тензоре, вы можете использовать .flat
и вычислить соответствующее смещение или использовать .tensor
, если вы знаете, что число измерений равно 4:
std::vector<tf::Tensor> outputs;
auto start_inference = std::chrono::high_resolution_clock::now();
_status = _session->Run({inputs}, {"k2tfout_0", "k2tfout_1"}, {}, &outputs);
if (!_status.ok())
{
std::cerr << _status.ToString() << std::endl;
return 0;
}
unsigned int output_img_n0 = outputs[0].shape().dim_size(0);
unsigned int output_img_h0 = outputs[0].shape().dim_size(1);
unsigned int output_img_w0 = outputs[0].shape().dim_size(2);
unsigned int output_img_c0 = outputs[0].shape().dim_size(3);
for (unsigned int ni = 0; ni < output_img_n0; ni++)
{
for (unsigned int hi = 0; hi < output_img_h0; hi++)
{
for (unsigned int wi = 0; wi < output_img_w0; wi++)
{
for (unsigned int ci = 0; ci < output_img_c0; ci++)
{
float_t value;
// Get vaule through .flat()
unsigned int offset = ni * output_img_h0 * output_img_w0 * output_img_c0 +
hi * output_img_w0 * output_img_c0 +
wi * output_img_c0 +
ci;
value = outputs[0].flat<float_t>()(offset);
// Get value through .tensor()
value = outputs[0].tensor<float_t, 4>()(ni, hi, wi, ci);
std::cout << "output[0](" << ni << ", " << hi << ", " << wi << ", " << ci << ") = ";
std::cout << value << std::endl;
}
}
}
}
Обратите внимание, что, хотя эти методы создают Eigen::TensorMap
объекты, которые на самом деле не дороги, вы можете вызвать их только один раз, а затем запросить тензорный объект несколько раз.Например:
// Make tensor
tf::TTypes<float_t, 4>::Tensor outputTensor0 = outputs[0].tensor<float_t, 4>();
// Query tensor multiple times
for (...)
{
std::cout << outputTensor0(ni, hi, wi, ci) << std::endl;
}
РЕДАКТИРОВАТЬ:
Если вы хотите получить указатель на данные тензора (например, чтобы построить другой объект из того же буфера, избегая копий или итерации),Вы также можете сделать это.Одним из вариантов является использование метода .tensor_data
, который возвращает tensorflow::StringPiece
, который, в свою очередь, является absl::string_view
, который является просто полифилом для std::string_view
.Таким образом, метод .data
этого объекта даст вам указатель на базовый байтовый буфер для тензора (обратите внимание на предупреждение в документации по .tensor_data
: «базовый тензорный буфер пересчитан», поэтому не позволяйте возвращенному объектубыть уничтоженным, пока вы используете буфер).Таким образом, вы можете сделать:
tf::StringPiece output0Str = outputs[0].tensor_data();
const char* output0Ptr = output0Str.data();
Это, однако, дает вам указатель на char
, поэтому вам придется привести его в действие, чтобы использовать его как float.Это должно быть безопасно, но выглядит уродливо, так что вы можете позволить Эйгену сделать это за вас.Все объекты Eigen имеют метод .data
, который возвращает указатель своего типа на базовый буфер.Например:
const float_t* output0Ptr = outputs[0].flat<float_t>().data();