简体   繁体   English

Tensorflow C API - 输入张量问题

[英]Tensorflow C API - Problem with the Input Tensor

I'm working with the Tensorflow API for C to load a pre-trained model in python and run predictions in an embedded compiled program. I'm working with the Tensorflow API for C to load a pre-trained model in python and run predictions in an embedded compiled program. The model I'm using takes a string as input, which is converted to a tensor, and gives a single float as output.我正在使用的 model 将字符串作为输入,将其转换为张量,并将单个浮点数作为 output。

The API loads the model just fine and runs sessions without complaining. API 可以很好地加载 model 并运行会话而不会抱怨。

The issue I'm facing is that no matter what data I feed into the C API session, I always get the exact same output tensor. The issue I'm facing is that no matter what data I feed into the C API session, I always get the exact same output tensor. So I'm guessing that I'm doing something wrong and I just can't see what it is.所以我猜我做错了什么,我只是看不到它是什么。 But I'm assuming that I am not formatting the input data in the way the C API expects.但我假设我没有按照 C API 期望的方式格式化输入数据。

Here is the output of saved_model_cli :这是 saved_model_cli 的saved_model_cli

The given SavedModel SignatureDef contains the following input(s):
  inputs['lstm_input'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1, 64, 88)
      name: serving_default_lstm_input:0
The given SavedModel SignatureDef contains the following output(s):
  outputs['dense'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1, 1)
      name: StatefulPartitionedCall:0
Method name is: tensorflow/serving/predict

In python, here is how I transform the input strings to tensors: (The variables X and X_val hold the training strings and validation strings respectively)在 python 中,我将输入字符串转换为张量:(变量XX_val保存训练字符串和验证字符串)

from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.utils import to_categorical

alphabet_size = len(set(all_lines))

tokenizer = Tokenizer(char_level=True)
tokenizer.fit_on_texts(all_lines)
seq_X = tokenizer.texts_to_sequences(X)
seq_X_val = tokenizer.texts_to_sequences(X_val)

seq_X = pad_sequences(seq_X, maxlen=64, padding='post')
seq_X_val = pad_sequences(seq_X_val, maxlen=64, padding='post')

one_hot_X = [to_categorical(x, num_classes=alphabet_size) for x in seq_X]
one_hot_X_val = [to_categorical(x_val, num_classes=alphabet_size) for x_val in seq_X_val]
one_hot_X = np.array(one_hot_X)
one_hot_X_val = np.array(one_hot_X_val)

Which finally gives me the following tokenizer.word_index :这最终给了我以下tokenizer.word_index

{'%': 1, '2': 2, 'e': 3, 'l': 4, 'c': 5, 'n': 6, 'i': 7, 'a': 8, '0': 9, 's': 10, 'r': 11, 't': 12, '/': 13, '1': 14, 'o': 15, 'u': 16, ',': 17, 'd': 18, '7': 19, 'h': 20, '8': 21, ' ': 22, '6': 23, '9': 24, '=': 25, '\n': 26, '(': 27, ')': 28, 'p': 29, 'b': 30, '5': 31, 'm': 32, 'f': 33, 'w': 34, '3': 35, 'g': 36, 'v': 37, '?': 38, 'x': 39, "'": 40, '-': 41, '4': 42, '&': 43, '.': 44, '+': 45, '_': 46, 'y': 47, '|': 48, 'k': 49, 'j': 50, '@': 51, 'z': 52, '#': 53, '"': 54, 'q': 55, '>': 56, '*': 57, '~': 58, '!': 59, '^': 60, ':': 61, '<': 62}

So when I want to use this model in C, I load it using the method described here: https://github.com/AmirulOm/tensorflow_capi_sample所以当我想在C中使用这个model时,我使用这里描述的方法加载它: https://github.com/Amirul_sample/tensorflow

And here is how I setup the Session:以下是我设置 Session 的方法:

First, I have a C array that plays the same role as the tokenizer.word_index above:首先,我有一个 C 数组,它的作用与上面的tokenizer.word_index相同:

int     dictionary[] = {
...
    14,//1 - 49
    2,//2 - 50
    35,//3 - 51
    42,//4 - 52
    31,//5 - 53
    23,//6 - 54
    19,//7 - 55
    21,//8 - 56
    24,//9 - 57
    61,//: - 58
    0,//59
    62,//< - 60
    25,//= - 61
    56,//> - 62
    38,//? - 63
    51,//@ - 64
...
    5,//c - 99
    18,//d - 100
    3,//e - 101
    33,//f - 102
    36,//g - 103
    20,//h - 104
    7,//i - 105
    50,//j - 106
    49,//k - 107
    4,//l - 108
    32,//m - 109
    6,//n - 110
    15,//o - 111
    29,//p - 112
    55,//q - 113
    11,//r - 114
    10,//s - 115
    12,//t - 116
    16,//u - 117
    37,//v - 118
    34,//w - 119
...
};  

The following function is used to fill a C float array in the same fashion that I do in the python model:以下 function 用于填充 C 浮点数组,其方式与我在 python Z20F3CZ35E630DAF494DFA8 中所做的方式相同:

float   *get_input_tensor(char *text)
{
    int     i;
    float   *result;
    size_t  tensor_size;
    char    *current;

    i = 0;
    current = text;
    tensor_size = sizeof(float) * 1 * 64 * 88;
    result = (float*)malloc(sizeof(float) * tensor_size);
    memset(result, 0, tensor_size);
    while (*current)
    {
        *(result + 88 * i + dictionary[(int)*current]) = 1.00f;
        current++;
        i++;
    }
    return (result);
}

Finally, set up the Session:最后,设置 Session:

    int     ndims = 3;
    int64_t dims[] = {1, 64, 88};
    float   *data = get_input_tensor("test_string");
    int     ndata = sizeof(float) * 1 * 64 * 88;

    TF_Tensor   *float_tensor = TF_NewTensor(TF_FLOAT, dims, ndims, data, ndata, &NoOpDeallocator, 0);
    TF_SessionRun(Session, NULL, Input, InputValues, NumInputs, Output, OutputValues, NumOutputs, NULL, 0, NULL, Status);0);

Running the program always give the following output:运行程序总是给出以下 output:

[*] TF_NewTensor OK
[*] Starting session
[*] Session OK
[*] Result tensor: 0.999864
[*] Tensorflow Data memory cleared and freed

I'm quite lost here.我在这里很迷茫。 So here's my question: given the input tensor shape from the model, how is the data supposed to be formatted in the C API before being thrown into TF_NewTensor and then into TF_SessionRun?所以这是我的问题:给定来自 model 的输入张量形状,数据应该如何在 C API 中格式化,然后再放入 TF_RunSession 和 NewTensorSession? Or is there a documentation online that I didn't find?或者有没有我没有找到的在线文档? Or even a general approach when filling the input tensor?甚至是填充输入张量时的通用方法?

Data in API C of TF are stored in row-major order. TF的API C中的数据按行优先顺序存储。

If you have 3D data layout, like [dim1,dim2,dim3] ( 1/64/88 ), and you want to access (d1,d2,d3) item you should use formula:如果您有 3D 数据布局,例如[dim1,dim2,dim3] ( 1/64/88 ),并且您想要访问 (d1,d2,d3) 项目,您应该使用公式:

item = d1 * dim2 * dim3 + d2 * dim3 + d3

So you could write helper function like:所以你可以像这样编写助手 function :

float* AccessResult(float* result, 
    int x, 
    int dim1, // 1
    int y, 
    int dim2, // 64
    int z,
    int dim3)  // 88
{
    float* item = result + x * dim2 * dim3 + y * dim3 + z;
    return item;
}

and the code filling out your array could be:填写您的数组的代码可能是:

for (int i = 0; i < 64; ++i) {
    for (int j = 0; j < 88; ++j) {
        float* res = AccessResult(result,0,1,i,64,j,88);
        *res = 1.0f;
    }
}

i or j (when calling AccessResult ) should be replaced by dictionary[..] , but I could't infer which one should be replaced. ij (调用AccessResult时)应替换为dictionary[..] ,但我无法推断应该替换哪个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM