如何从 [c_api.h] 向 TF_SessionRun 提供训练数据
How to provide training data to TF_SessionRun from [c_api.h]
我正在尝试使用 TF 2.0beta C api(c_api.h).
实现 fashion-mnist 教程的训练部分
简而言之,模型是按照前面提到的教程使用 python 创建的。然后将模型保存为 .pb 文件,然后将其与训练数据(28*28 灰度图像)和训练标签(标量 运行ging from [0-9])一起加载到我的 C 程序中。
你们中的一些人可能知道,TF C api 的文档很差(插入 运行t 充满挫败感 here) and after much reading and searching on the internet here, here, here, and here 在许多其他地方,我仍然无法实现此任务(下面有更多详细信息)。
让我们开始吧:
我不想在代码中淹没这个问题,但我希望您能够访问我已经完成的工作。
生成模型的pythonscript通过以下方式保存:
keras.experimental.export_saved_model.
简单的执行代码:
python3 createModel.py.
保存的模型将存储在名为“saved_model”的新文件夹中。 这很重要,因为这个名称是硬编码在 C 代码中的
Data 用于训练模型也是通过 python TF 获得的。
再次:python getData.py.
将数据和相应的标签保存为 data.txt 和 labels.txt 同样,这些名称很重要,因为它们已硬编码在我的 C 代码中
现在我们可以进入 C 代码了!!
所有代码都驻留在一个 single 文件中,其中包含我想象的尽可能多的注释。只要你有 libtensorflow.so.2 和 libtensorflow_framework.so.2.0.0
编译就应该很简单
gcc -Wall -I /path/to/TFlib/include -L /path/to/TFlib/lib -o trainMnist trainMnist.c
在x86_64系统中应该没有警告(至少我试过的两台电脑是这样)
编译后执行:
LD_LIBRARY_PATH=/path/to/TFlib/lib ./trainMnist
如果 .so 文件已经可以访问,您可以跳过 LD_LIBRARY_PATH。
如果您没有 TF 共享对象文件,如果您敢于相信来自 运行dom 人的编译代码,我很乐意与任何人共享它们。您可以自己生成它:
git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow
git checkout r2.0
./configure
bazel build -c opt //tensorflow/tools/lib_package:libtensorflow
header 和 .so 文件将在 bazel-bin/tensorflow/tensorflow/tools/lib_package/libtensorflow.tar.gz
假设 saved_model
、data.txt
和 labels.txt
与 ./trainMnist 所在的目录相同 运行,应该只打印 TF 警告和一些冗长的警告来自代码本身的消息。
但感兴趣的函数是:
int Belly_ModelTrain(model_t *model,
float **train_data,
float **label_data,
int numPoints)
model
是一个包含重要成员以启动 TF 会话的结构
train_data
包含 28*28=784 个浮点数(图像的像素值)的 numPoints 数组
label_data
包含 10 个浮点数的 numPoints 数组(除该图像的真实标签外均为 0)。
numPoints
是加载的图像数量。 numPoints
的值在 main.
中硬编码
在此函数中,训练按以下方式进行:
// The actual tensors that will hold the data and be passed to TF_SessionRun
TF_Tensor *x, *y;
// Establish the dimentions of the input data
const int64_t dimTrain[] = {numPoints, 784}; //pixel values
const int64_t dimLabel[] = {numPoints, 10}; //labels
{
//Boilerplate allocation code happens here
size_t nbytesT = (numPoints*784) * sizeof(float);
x = TF_AllocateTensor(TF_FLOAT, dimTrain, 2, nbytesT);
size_t nbytesL = (numPoints*10) * sizeof(float);
y = TF_AllocateTensor(TF_FLOAT, dimLabel, 2, nbytesL);
}
//Copy the data in my arrays to the tensors
memcpy(TF_TensorData(x), train_data, nbytesT);
memcpy(TF_TensorData(y), label_data, nbytesL);
//TBH I really don't know what is going on in these two lines
//Establish model inputs and model targets(labels)
TF_Output inputs[2] = {model->input, model->target};
TF_Tensor* input_values[2] = {x, y};
//training operation defined in model
const TF_Operation* train_op[1] = {model->train_op};
//Run the model with the data
TF_SessionRun(model->session,
NULL,
inputs, input_values, 2,
NULL, NULL, 0,
train_op, 1,
NULL, model->status);
TF_DeleteTensor(x);
TF_DeleteTensor(y);
//Return 0 on success
return Belly_CheckStatus(model->status);
我希望这个函数 运行 很好并且 return 0 基于模型的状态应该是 TF_OK。这当然失败了,我得到:
错误:节点 'dense_2_target'(类型:'Placeholder',输出数量:1)没有输出 [一些疯狂的 batshit 数字]
根据错误消息,我了解到我的 target
输入格式错误。我已经尝试更改我通过 label_data
的方式以及更改 dimL
但没有任何成功。
原来我在使用 C api 时还在思考 python。
在trainMnist.c中,数据被读入数组数组(float **points):
int Belly_ReadData(float **points, int numSamples) {
...
...
...
for(int i = 0; i < numSamples; i++) {
//Allocate memory for datapoint
points[i] = (float *)malloc(784*sizeof(float));
...
...
...
//Read other 783 pixels
for(int j = 0; j < 783; j++) {
point = strtok(NULL,"\t");
points[i][j+1] = strtof(point,&err);
if(*err != 0) return -1;
}
...
}
}
之后这个数组数组被输入到输入张量"x"中:
int Belly_ModelTrain(model_t *model,
float **train_data,
float **label_data,
int numPoints) {
...
...
...
// Allocate data for tensors
x = TF_AllocateTensor(TF_FLOAT, dimTrain, 2, nbytesT);
if(x==NULL) {
printf("ERROR allocate x\n");
return -1;
}
y = TF_AllocateTensor(TF_FLOAT, dimLabel, 2, nbytesL);
if(y==NULL) {
printf("ERROR allocate y\n");
return -1;
}
// Copy data from arrays into tensors
memcpy(TF_TensorData(x), train_data, nbytesT); //<===== "train_data should be an array of floats"
memcpy(TF_TensorData(y), label_data, nbytesL); //<===== "label_data should be an array of floats"
...
...
...
按照我的理解,我将垃圾数据传递给了张量 x 和 y。
Will post 为任何想尝试的人更正代码。
我正在尝试使用 TF 2.0beta C api(c_api.h).
实现 fashion-mnist 教程的训练部分简而言之,模型是按照前面提到的教程使用 python 创建的。然后将模型保存为 .pb 文件,然后将其与训练数据(28*28 灰度图像)和训练标签(标量 运行ging from [0-9])一起加载到我的 C 程序中。
你们中的一些人可能知道,TF C api 的文档很差(插入 运行t 充满挫败感 here) and after much reading and searching on the internet here, here, here, and here 在许多其他地方,我仍然无法实现此任务(下面有更多详细信息)。
让我们开始吧:
我不想在代码中淹没这个问题,但我希望您能够访问我已经完成的工作。
生成模型的pythonscript通过以下方式保存: keras.experimental.export_saved_model.
简单的执行代码: python3 createModel.py.
保存的模型将存储在名为“saved_model”的新文件夹中。 这很重要,因为这个名称是硬编码在 C 代码中的
Data 用于训练模型也是通过 python TF 获得的。
再次:python getData.py.
将数据和相应的标签保存为 data.txt 和 labels.txt 同样,这些名称很重要,因为它们已硬编码在我的 C 代码中
现在我们可以进入 C 代码了!!
所有代码都驻留在一个 single 文件中,其中包含我想象的尽可能多的注释。只要你有 libtensorflow.so.2 和 libtensorflow_framework.so.2.0.0
编译就应该很简单gcc -Wall -I /path/to/TFlib/include -L /path/to/TFlib/lib -o trainMnist trainMnist.c
在x86_64系统中应该没有警告(至少我试过的两台电脑是这样)
编译后执行:
LD_LIBRARY_PATH=/path/to/TFlib/lib ./trainMnist
如果 .so 文件已经可以访问,您可以跳过 LD_LIBRARY_PATH。
如果您没有 TF 共享对象文件,如果您敢于相信来自 运行dom 人的编译代码,我很乐意与任何人共享它们。您可以自己生成它:
git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow
git checkout r2.0
./configure
bazel build -c opt //tensorflow/tools/lib_package:libtensorflow
header 和 .so 文件将在 bazel-bin/tensorflow/tensorflow/tools/lib_package/libtensorflow.tar.gz
假设 saved_model
、data.txt
和 labels.txt
与 ./trainMnist 所在的目录相同 运行,应该只打印 TF 警告和一些冗长的警告来自代码本身的消息。
但感兴趣的函数是:
int Belly_ModelTrain(model_t *model,
float **train_data,
float **label_data,
int numPoints)
model
是一个包含重要成员以启动 TF 会话的结构
train_data
包含 28*28=784 个浮点数(图像的像素值)的 numPoints 数组
label_data
包含 10 个浮点数的 numPoints 数组(除该图像的真实标签外均为 0)。
numPoints
是加载的图像数量。 numPoints
的值在 main.
在此函数中,训练按以下方式进行:
// The actual tensors that will hold the data and be passed to TF_SessionRun
TF_Tensor *x, *y;
// Establish the dimentions of the input data
const int64_t dimTrain[] = {numPoints, 784}; //pixel values
const int64_t dimLabel[] = {numPoints, 10}; //labels
{
//Boilerplate allocation code happens here
size_t nbytesT = (numPoints*784) * sizeof(float);
x = TF_AllocateTensor(TF_FLOAT, dimTrain, 2, nbytesT);
size_t nbytesL = (numPoints*10) * sizeof(float);
y = TF_AllocateTensor(TF_FLOAT, dimLabel, 2, nbytesL);
}
//Copy the data in my arrays to the tensors
memcpy(TF_TensorData(x), train_data, nbytesT);
memcpy(TF_TensorData(y), label_data, nbytesL);
//TBH I really don't know what is going on in these two lines
//Establish model inputs and model targets(labels)
TF_Output inputs[2] = {model->input, model->target};
TF_Tensor* input_values[2] = {x, y};
//training operation defined in model
const TF_Operation* train_op[1] = {model->train_op};
//Run the model with the data
TF_SessionRun(model->session,
NULL,
inputs, input_values, 2,
NULL, NULL, 0,
train_op, 1,
NULL, model->status);
TF_DeleteTensor(x);
TF_DeleteTensor(y);
//Return 0 on success
return Belly_CheckStatus(model->status);
我希望这个函数 运行 很好并且 return 0 基于模型的状态应该是 TF_OK。这当然失败了,我得到:
错误:节点 'dense_2_target'(类型:'Placeholder',输出数量:1)没有输出 [一些疯狂的 batshit 数字]
根据错误消息,我了解到我的 target
输入格式错误。我已经尝试更改我通过 label_data
的方式以及更改 dimL
但没有任何成功。
原来我在使用 C api 时还在思考 python。
在trainMnist.c中,数据被读入数组数组(float **points):
int Belly_ReadData(float **points, int numSamples) {
...
...
...
for(int i = 0; i < numSamples; i++) {
//Allocate memory for datapoint
points[i] = (float *)malloc(784*sizeof(float));
...
...
...
//Read other 783 pixels
for(int j = 0; j < 783; j++) {
point = strtok(NULL,"\t");
points[i][j+1] = strtof(point,&err);
if(*err != 0) return -1;
}
...
}
}
之后这个数组数组被输入到输入张量"x"中:
int Belly_ModelTrain(model_t *model,
float **train_data,
float **label_data,
int numPoints) {
...
...
...
// Allocate data for tensors
x = TF_AllocateTensor(TF_FLOAT, dimTrain, 2, nbytesT);
if(x==NULL) {
printf("ERROR allocate x\n");
return -1;
}
y = TF_AllocateTensor(TF_FLOAT, dimLabel, 2, nbytesL);
if(y==NULL) {
printf("ERROR allocate y\n");
return -1;
}
// Copy data from arrays into tensors
memcpy(TF_TensorData(x), train_data, nbytesT); //<===== "train_data should be an array of floats"
memcpy(TF_TensorData(y), label_data, nbytesL); //<===== "label_data should be an array of floats"
...
...
...
按照我的理解,我将垃圾数据传递给了张量 x 和 y。
Will post 为任何想尝试的人更正代码。