[英]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. 我正在使用的 model 將字符串作為輸入,將其轉換為張量,並將單個浮點數作為 output。
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. 所以我猜我做錯了什么,我只是看不到它是什么。 但我假設我沒有按照 C API 期望的方式格式化輸入數據。
這是 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
在 python 中,我將輸入字符串轉換為張量:(變量X
和X_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)
這最終給了我以下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}
所以當我想在C中使用這個model時,我使用這里描述的方法加載它: https://github.com/Amirul_sample/tensorflow
以下是我設置 Session 的方法:
首先,我有一個 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
...
};
以下 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);
}
最后,設置 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);
運行程序總是給出以下 output:
[*] TF_NewTensor OK
[*] Starting session
[*] Session OK
[*] Result tensor: 0.999864
[*] Tensorflow Data memory cleared and freed
我在這里很迷茫。 所以這是我的問題:給定來自 model 的輸入張量形狀,數據應該如何在 C API 中格式化,然后再放入 TF_RunSession 和 NewTensorSession? 或者有沒有我沒有找到的在線文檔? 甚至是填充輸入張量時的通用方法?
TF的API C中的數據按行優先順序存儲。
如果您有 3D 數據布局,例如[dim1,dim2,dim3]
( 1/64/88
),並且您想要訪問 (d1,d2,d3) 項目,您應該使用公式:
item = d1 * dim2 * dim3 + d2 * dim3 + d3
所以你可以像這樣編寫助手 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;
}
填寫您的數組的代碼可能是:
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
或j
(調用AccessResult
時)應替換為dictionary[..]
,但我無法推斷應該替換哪個。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.