Я пытаюсь вывести обученную модель от keras до C. Мне нужна модель для работы на nrf52832. Результат предсказания C отличается от keras . Я сделал свою модель как можно меньше, чтобы облегчить отладку.
Вот модель:
функция построения модели (в python)
модель
Прогноз в python:
arr = np.loadtxt('model/input.txt')
arr = arr.reshape((-1, 40, 1))
model = load_model('weights/07-26_0.h5')
layer_name = 'lstm'
intermediate_layer_model = Model(
inputs=model.input, outputs=model.get_layer(layer_name).output)
intermediate_output = intermediate_layer_model.predict(arr)
print(intermediate_output[0][0])
intermediate_output [0] означает вывод каждого временного шага (ht), как указано в статье.
https://machinelearningmastery.com/return-sequences-and-return-states-for-lstms-in-keras/
вывод слоя lstm в python (ht)
Функция Lstm и функции, используемые в Lstm в C (Я публикую только часть кода, потому что он слишком большой)
float *LSTM_Conv(float *input, float *weight, uint8_t input_len, uint8_t output_len, int gate_index)
{
float *output = (float *)calloc(output_len, sizeof(float));
if (output == NULL)
{
printf("aver memory is not enough\n");
while (1)
;
}
// EXAMPLE:
// Input shape & Weight shape
// Xt (1,) (in a single time step)
// in_weight (1, 256)
// ht_1 (64,)
// re_weight (64, 256)
for (uint8_t output_i = 0; output_i < output_len; output_i++)
{
for (uint8_t input_i = 0; input_i < input_len; input_i++)
{
output[output_i] += input[input_i] * weight[input_i * output_len * 4 + output_i + gate_index];
}
}
return output;
}
void LSTM_bias(float *input, float *bias, uint8_t len, uint8_t gate_index)
{
for (uint8_t len_i = 0; len_i < len; len_i++)
{
input[len_i] += bias[len_i + gate_index];
}
return;
}
float *arr_copy(float *reference, uint8_t start, uint8_t len)
{
float *toBeCopied = (float *)calloc(len, sizeof(float));
for (uint8_t len_i = 0; len_i < len; len_i++)
{
toBeCopied[len_i] = reference[len_i + start];
}
return toBeCopied;
}
float *arr_plus(float *input1, float *input2, uint8_t len)
{
float *output = (float *)calloc(len, sizeof(float));
for (uint8_t len_i = 0; len_i < len; len_i++)
{
output[len_i] = input1[len_i] + input2[len_i];
}
free(input1);
free(input2);
return output;
}
float *arr_multi(float *input1, float *input2, uint8_t len)
{
float *output = (float *)calloc(len, sizeof(float));
for (uint8_t len_i = 0; len_i < len; len_i++)
{
output[len_i] = input1[len_i] * input2[len_i];
}
free(input1);
free(input2);
return output;
}
void sigmoid(float *input, uint8_t input_len)
{
uint8_t len_i;
for (len_i = 0; len_i < input_len; len_i++)
{
input[len_i] = 1 / (1 + exp(-1 * input[len_i]));
}
return;
}
void tanh_func(float *input, uint8_t input_len)
{
uint8_t len;
for (len = 0; len < input_len; len++)
{
input[len] = (float)tanh((double)input[len]);
}
return;
}
float *Lstm(float *input,
float *in_weight,
float *re_weight,
float *bias,
uint8_t time_step,
uint8_t input_len,
uint8_t output_len)
{
// I / O:
// current time input Xt
// current time output ht
// current time hidden state Ct
// last time output ht_1
// last time hidden state Ct_1
float *Xt = NULL;
float *ht = NULL;
float *Ct = NULL;
float *ht_1 = (float *)calloc(output_len, sizeof(float));
float *Ct_1 = (float *)calloc(output_len, sizeof(float));
// 4 Gates:
// input gate: it
// forget gate: ft
// new candidate cell state: Ct_bar
// output gate: Ot
float *it = NULL;
float *ft = NULL;
float *Ct_bar = NULL;
float *Ot = NULL;
float *temp = NULL;
for (uint8_t step = 0; step < time_step; step++)
{
if (DEBUG)
{
printf("++++++++++++++%d iteration+++++++++++++++\n", step);
}
Xt = arr_copy(input, input_len * step, input_len);
// input gate (it)
it = arr_plus(
LSTM_Conv(Xt, in_weight, input_len, output_len, 0 ),
LSTM_Conv(ht_1, re_weight, output_len, output_len, 0),
output_len);
LSTM_bias(it, bias, output_len, 0);
sigmoid(it, output_len);
if (DEBUG)
{
for (int i = 0; i < output_len; i++)
{
printf("%f ", it[i]);
}
printf("\nit end***************************\n");
}
// forget gate (ft)
ft = arr_plus(
LSTM_Conv(Xt, in_weight, input_len, output_len, output_len * 1),
LSTM_Conv(ht_1, re_weight, output_len, output_len, output_len * 1),
output_len * 1);
LSTM_bias(ft, bias, output_len, output_len * 1);
sigmoid(ft, output_len);
if (DEBUG)
{
for (int i = 0; i < output_len; i++)
{
printf("%f ", ft[i]);
}
printf("\nft end***************************\n");
}
// new candidate cell state (Ct_bar)
Ct_bar = arr_plus(
LSTM_Conv(Xt, in_weight, input_len, output_len, output_len * 2),
LSTM_Conv(ht_1, re_weight, output_len, output_len, output_len * 2),
output_len);
LSTM_bias(Ct_bar, bias, output_len, output_len * 2);
tanh_func(Ct_bar, output_len);
if (DEBUG)
{
for (int i = 0; i < output_len; i++)
{
printf("%f ", Ct_bar[i]);
}
printf("\nCt_bar end***************************\n");
}
// output gate (Ot)
Ot = arr_plus(
LSTM_Conv(Xt, in_weight, input_len, output_len, output_len * 3),
LSTM_Conv(ht_1, re_weight, output_len, output_len, output_len * 3),
output_len);
LSTM_bias(Ot, bias, output_len, output_len * 3);
sigmoid(Ot, output_len);
if (DEBUG)
{
for (int i = 0; i < output_len; i++)
{
printf("%f ", Ot[i]);
}
printf("\nOt end***************************\n");
}
//last time to use ht_1
if (ht_1 != NULL)
free(ht_1);
else
printf("ht_1 NULL\n\n");
//last time to use Xt
if (Xt != NULL)
free(Xt);
else
printf("Xt NULL\n\n");
Ct = arr_plus(
//it Ct_bar free here
arr_multi(it, Ct_bar, output_len),
//Ct_1 ft free here
arr_multi(ft, Ct_1, output_len),
output_len);
temp = arr_copy(Ct, 0, output_len);
tanh_func(temp, output_len);
ht = arr_multi(temp, Ot, output_len); //Ot free
Ct_1 = Ct;
ht_1 = ht;
if (1)
{
for (int i = 0; i < output_len; i++)
{
printf("%f ", ht[i]);
}
printf("\nht end***************************\n");
}
}
if (Ct != NULL)
free(Ct);
else
printf("Ct NULL\n\n");
return ht;
}
Аргумент функции Lstm: time_step = 40, input_len = 1, output_len = 64
output слоя lstm в C (ht)
LSTM вес и смещение
Я проверил вес и смещение. Они в порядке.
Пожалуйста, посмотрите на результат python и C. Они близки с самого начала.
Я не уверен, неправильно ли я понял механизм LSTM или сделал что-то не так.
Не стесняйтесь, дайте мне знать, если вам понадобится дополнительная информация.
Большое спасибо.