"Привет TensorFlow!" используя C API

Для целей обучения, как кодировать этот пример Python, используя TensorFlow C API?

import tensorflow as tf
hello = tf.constant("hello TensorFlow!")
sess=tf.Session()
print(sess.run(hello))

Я пробовал это так:

#include <string.h>
#include <iostream.h>
#include "c_api.h"

int main( int argc, char ** argv ) 
{
  TF_Graph * graph = TF_NewGraph();
  TF_SessionOptions * options = TF_NewSessionOptions();
  TF_Status * status = TF_NewStatus();
  TF_Session * session = TF_NewSession( graph, options, status );
  char hello[] = "Hello TensorFlow!";
  TF_Tensor * tensor = TF_AllocateTensor( TF_STRING, 0, 0, 8 + TF_StringEncodedSize( strlen( hello ) ) );
  TF_OperationDescription * operationDescription = TF_NewOperation( graph, "Const", "hello" );
  TF_Operation * operation; 
  struct TF_Output * output;

  TF_StringEncode( hello, strlen( hello ), 8 + ( char * ) TF_TensorData( tensor ), TF_StringEncodedSize( strlen( hello ) ), status );
  TF_SetAttrTensor( operationDescription, "value", tensor, status );
  TF_SetAttrType( operationDescription, "dtype", TF_TensorType( tensor ) );
  operation = TF_FinishOperation( operationDescription, status );

  output->oper = operation;
  output->index = 0;

  TF_SessionRun( session, 0,
                 0, 0, 0,  // Inputs
                 output, &tensor, 1,  // Outputs
                 &operation, 1,  // Operations
                 0, status );

  printf( "%i", TF_GetCode( status ) );

  TF_CloseSession( session, status );
  TF_DeleteSession( session, status );
  TF_DeleteStatus( status );
  TF_DeleteSessionOptions( options );  

  return 0;
}

Я тестирую его на Windows, используя TensorFlow.dll от: http://ci.tensorflow.org/view/Nightly/job/nightly-libtensorflow-windows/lastSuccessfulBuild/artifact/lib_package/libtensorflow-cpu-windows-x86_64.zip

Приведенный выше код GPF на TF_SessionRun() вызов. Как только мы найдем решение для этого, как получить результат? Следует ли использовать другой тензор для вывода? Приведенный выше код повторно использует его как в выводе, так и в операции.

большое спасибо

2 ответа

Была ошибка, которую нужно решить, кроме инициализации смещения. Эта версия работает нормально:

#include <iostream.h>
#include "c_api.h"

int main( int argc, char ** argv ) 
{
  TF_Graph * graph = TF_NewGraph();
  TF_SessionOptions * options = TF_NewSessionOptions();
  TF_Status * status = TF_NewStatus();
  TF_Session * session = TF_NewSession( graph, options, status );
  char hello[] = "Hello TensorFlow!";
  TF_Tensor * tensor = TF_AllocateTensor( TF_STRING, 0, 0, 8 + TF_StringEncodedSize( strlen( hello ) ) );
  TF_Tensor * tensorOutput;
  TF_OperationDescription * operationDescription = TF_NewOperation( graph, "Const", "hello" );
  TF_Operation * operation; 
  struct TF_Output output;

  TF_StringEncode( hello, strlen( hello ), 8 + ( char * ) TF_TensorData( tensor ), TF_StringEncodedSize( strlen( hello ) ), status );
  memset( TF_TensorData( tensor ), 0, 8 );
  TF_SetAttrTensor( operationDescription, "value", tensor, status );
  TF_SetAttrType( operationDescription, "dtype", TF_TensorType( tensor ) );
  operation = TF_FinishOperation( operationDescription, status );

  output.oper = operation;
  output.index = 0;

  TF_SessionRun( session, 0,
                 0, 0, 0,  // Inputs
                 &output, &tensorOutput, 1,  // Outputs
                 &operation, 1,  // Operations
                 0, status );

  printf( "status code: %i\n", TF_GetCode( status ) );
  printf( "%s\n", ( ( char * ) TF_TensorData( tensorOutput ) ) + 9 );

  TF_CloseSession( session, status );
  TF_DeleteSession( session, status );
  TF_DeleteStatus( status );
  TF_DeleteSessionOptions( options );  

  return 0;
}

Нужно ли удалять tenorOutput? Не уверен, почему мы должны добавить 9 (вместо 8), чтобы получить начало строки.

TF_STRING тензоры кодируются с использованием формата, описанного здесь. В вашем коде вы учли пространство (8 байт) для кодирования одного смещения, но фактически его не инициализировали. Чтобы сделать это, вы хотите добавить что-то вроде:

memset (TF_TensorData (тензор), 0, 8);

Перед звонком в TF_SetAttrTensor, так как это установит "смещение" строкового элемента в 0 (где вы кодируете одно строковое значение).

На ваш второй вопрос: вы на самом деле не используете повторно tensor указатель. Комментарии дляTF_SessionRun предположить, что TF_SessionRun выделяет новый TF_Tensor объект, которым звонящий становится владельцем. Итак, в вашем фрагменте кода tensor переменная перезаписывается, чтобы указывать на вновь выделенный тензор.

Надеюсь, это поможет.

Пример будет работать в Linux с установленным TensorFlow, как описано здесь https://www.tensorflow.org/install/lang_c с измененнымinclude директивы:

#include <stdio.h>
#include <string.h>
#include <tensorflow/c/c_api.h>

Для построения достаточно выполнить

gcc hello_tf.c -ltensorflow -o hello_tf

как было сказано в документации TensorFlow.

Другие вопросы по тегам