Использование предварительно обученных моделей TensorFlow в C/C++ — косвенные вызовы реализации Python

искусственный интеллект TensorFlow Python C++
Использование предварительно обученных моделей TensorFlow в C/C++ — косвенные вызовы реализации Python

Текущие фреймворки глубокого обучения обычно реализуются на основе Python, а построение, обучение, сохранение и вызов моделей можно легко выполнить с помощью Python. Но иногда, когда мы действительно применяем эти модели, нам может потребоваться сделать это на других языках программирования.В этой статье предварительно обученная модель TensorFlow будет вызываться в программе C/C++ путем косвенного вызова Python из C/C++.

1. Конфигурация среды

  • Чтобы вызвать Python в C/C++, нам нужно настроить путь к заголовочным файлам и библиотекам.В этой статье в качестве примера используется Code::Blocks.

  • Добавить библиотеку ссылок в Build -> Project optionslibpython3.5m.soА путь, где находится заголовочный файл Python.h, разные версии Python можно корректировать по ситуации.

在这里插入图片描述

在这里插入图片描述

2. Инициализировать и импортировать модули Python и связанные с ними функции

void Initialize()
{
    Py_Initialize();
    if ( !Py_IsInitialized() )
    {
        printf("Initialize failed!");
    }

	// Path of the python file. 需要更改为 python 文件所在路径
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('/home/senius/python/c_python/test/')");

    const char* modulName = "forward";    // Module name of python file.
    pMod = PyImport_ImportModule(modulName);
    if(!pMod)
    {
        printf("Import Module failed!\n");
    }

    const char* funcName = "load_model";  // Function name in the  python file.
    load_model = PyObject_GetAttrString(pMod, funcName);
    if(!load_model)
    {
        printf("Import load_model Function failed!\n");
    }

    funcName = "predict";  // Function name in the python file.
    predict = PyObject_GetAttrString(pMod, funcName);
    if(!predict)
    {
        printf("Import predict Function failed!\n");
    }

    PyEval_CallObject(load_model, NULL); // 导入预训练的模型
    pParm = PyTuple_New(1); // 新建一个元组,参数只能通过元组传入 Python 程序
}

  • Через PyImport_ImportModule мы можем импортировать файл Python, который нужно вызвать, затем получить функции в модуле через PyObject_GetAttrString и, наконец, импортировать предварительно обученную модель и создать новый кортеж в качестве параметра.

3. Создание аргументов, передаваемых в Python из C

void Read_data()
{
    const char* txtdata_path = "/home/senius/python/c_python/test/04t30t00.npy";
    //Path of the TXT file. 需要更改为txt文件所在路径

    FILE *fp;
    fp = fopen(txtdata_path, "rb");
    if(fp == NULL)
    {
        printf("Unable to open the file!");
    }
    fread(data, num*SIZE, sizeof(float), fp);
    fclose(fp);

    // copying the data to the list
    int j = 0;
    pArgs = PyList_New(num * SIZE); // 新建一个列表,并填入数据
    while(j < num * SIZE)
    {
        PyList_SET_ITEM(pArgs, j, Py_BuildValue("f", data[j]));
        j++;
    }
}

  • Считайте тестовые данные и заполните список данными.

4. Передайте список в кортеж, затем передайте его в Python в качестве параметра и проанализируйте возвращаемое значение.

void Test()
{
    PyTuple_SetItem(pParm, 0, pArgs);
    pRetVal = PyEval_CallObject(predict, pParm);

    int list_len = PyList_Size(pRetVal);
    PyObject *list_item = NULL;
    PyObject *tuple_item = NULL;
    for (int i = 0; i < list_len; i++)
    {
        list_item = PyList_GetItem(pRetVal, i);
        tuple_item =  PyList_AsTuple(list_item);
        PyArg_ParseTuple(tuple_item, "f", &iRetVal[i]);
    }
}
  • Передайте кортеж в программу Python, вызовите функцию прогнозирования, чтобы получить возвращаемое значение, а затем проанализируйте его.

5. Некоторые параметры и основная функция

#include <Python.h>
#include <stdio.h>

#define SIZE 41*41*41*3
#define NUM 100

PyObject* pMod = NULL;
PyObject* load_model = NULL;
PyObject* predict = NULL;
PyObject* pParm = NULL;
PyObject* pArgs = NULL;
PyObject* pRetVal = NULL;

float iRetVal[NUM*3] = {0};
float data[NUM * SIZE] = {0};
int num = 1;  //实际的样本数100

void Initialize(); 
void Read_data(); 
void Test(); 

int main(int argc, char **argv)
{
    Initialize(); // 初始化
    Read_data(); // 读入数据
    Test(); // 调用预测函数并解析返回值
    
    int j = 0;
    while(j < num*3)
    {
        printf("%f\n", iRetVal[j]);
        j++;
    }
    printf("Done!\n");
    Py_Finalize();

    return 0;
}

Для более захватывающих, пожалуйста, обратите внимание на "seniusen"!

seniusen