2023-05-15 08:43 AM
The approach described on the official XCUBE-AI documentation is not working for my case.
Solved! Go to Solution.
2023-05-17 09:38 AM
Hello,
According the shared code, I think that you have an issue when you initalize the ai_buffer handlers before to call the ai_network_run() function. The passed @ are not correct, "in_data" and "out_data" are the array of pointer, code should be modified as follow:
aiConvertInputFloat_2_Int8(input, in_data);
/* ai_inputs[0].data = AI_HANDLE_PTR(&in_data[0]); */
ai_inputs[0].data = AI_HANDLE_PTR(in_data[0]);
/* Update the AI output handlers */
for (int i=0; i < AI_NETWORK_OUT_NUM; i++) {
/* ai_outputs[i].data = AI_HANDLE_PTR(&out_data[i]); */
ai_outputs[i].data = AI_HANDLE_PTR(out_data[i]);
}
Note that is also recommended to align the IO buffer:
/* C-table to store the @ of the input buffer */
AI_ALIGNED(32)
static ai_i8 in_data[AI_NETWORK_IN_1_SIZE];
/* AI input/output handlers */
static ai_buffer *ai_inputs;
static ai_buffer *ai_outputs;
/* data buffer for the output buffers */
AI_ALIGNED(32)
static ai_i8 out_1_data[AI_NETWORK_OUT_1_SIZE];
AI_ALIGNED(32)
static ai_i8 out_2_data[AI_NETWORK_OUT_2_SIZE];
Best,
Jean-Michel
2023-05-15 09:04 AM
can you describe what is not working in your case ?
Regards
Daniel
2023-05-15 11:19 AM
I am not able to correctly initialize the output buffer. When I try to access its size or meta_info to dequantize the output, I get random values...
2023-05-16 07:45 AM
Now the code is working, but I always get 0 as output.
Here is my code:
/* Global handle to reference the instance of the NN */
static ai_handle network = AI_HANDLE_NULL;
static ai_u8 activations[AI_NETWORK_DATA_ACTIVATIONS_SIZE];
/* C-table to store the @ of the input buffer */
static ai_i8 in_data[AI_NETWORK_IN_1_SIZE];
/* AI input/output handlers */
static ai_buffer *ai_inputs;
static ai_buffer *ai_outputs;
/* data buffer for the output buffers */
static ai_i8 out_1_data[AI_NETWORK_OUT_1_SIZE];
static ai_i8 out_2_data[AI_NETWORK_OUT_2_SIZE];
/* C-table to store the @ of the output buffers */
static ai_i8* out_data[AI_NETWORK_OUT_NUM] = {
&out_1_data[0],
&out_2_data[0]
};
/*
* Init function to create and initialize a NN.
*/
void aiInit(void) {
/* 1 - Create and initialize network */
ai_error err;
const ai_handle act_addr[] = { activations };
err = ai_network_create_and_init(&network, act_addr, NULL);
if (err.type != AI_ERROR_NONE) {
printf("ai_network_create error - type=%d code=%d\r\n", err.type, err.code);
}
/* 2 - Retrieve IO network infos */
ai_inputs = ai_network_inputs_get(network, NULL);
ai_outputs = ai_network_outputs_get(network, NULL);
}
void aiConvertInputFloat_2_Int8(ai_float *in_f32, ai_i8 *out_int8)
{
ai_buffer_format format = ai_inputs->format;
ai_size size = ai_inputs->size;
ai_float scale = 0.0;
ai_float zero_point = 0;
if (AI_BUFFER_FMT_TYPE_Q != AI_BUFFER_FMT_GET_TYPE(format) &&\
! AI_BUFFER_FMT_GET_SIGN(format) && 8 != AI_BUFFER_FMT_GET_BITS(format))
{
printf("E: expected signed integer 8 bits\r\n");
return;
}
if (AI_BUFFER_META_INFO_INTQ(ai_inputs->meta_info))
{
scale = AI_BUFFER_META_INFO_INTQ_GET_SCALE(ai_inputs->meta_info, 0);
if (scale != 0.0F) {
scale= 1.0F/scale ;
}
else {
printf("E: division by zero\r\n");
return;
}
zero_point = AI_BUFFER_META_INFO_INTQ_GET_ZEROPOINT(ai_inputs->meta_info, 0);
}
else {
printf("E: no meta info\r\n");
return;
}
for (uint32_t i = 0; i < size ; i++) {
out_int8[i] = __SSAT((int32_t) roundf(zero_point + in_f32[i]*scale), 8);
}
}
void aiConvertOutputInt8_2_Float(ai_i8 *in_int8, ai_float *out_f32)
{
ai_buffer_format format = ai_outputs->format;
ai_size size = ai_outputs->size;
ai_float scale = 0.0;
ai_float zero_point = 0;
if (AI_BUFFER_FMT_TYPE_Q != AI_BUFFER_FMT_GET_TYPE(format) &&\
! AI_BUFFER_FMT_GET_SIGN(format) && 8 != AI_BUFFER_FMT_GET_BITS(format))
{
printf("E: expected signed integer 8 bits\r\n");
return;
}
if (AI_BUFFER_META_INFO_INTQ(ai_outputs->meta_info))
{
scale = AI_BUFFER_META_INFO_INTQ_GET_SCALE(ai_outputs->meta_info, 0);
zero_point = AI_BUFFER_META_INFO_INTQ_GET_ZEROPOINT(ai_outputs->meta_info, 0);
}
else {
printf("E: no meta info\r\n");
return;
}
for (uint32_t i = 0; i < size ; i++) {
out_f32[i] = scale * ((ai_float)(in_int8[i]) - zero_point);
}
}
uint8_t roundInt(float32_t cnnOutput)
{
if (cnnOutput > 0.5) {
return 1;
}
else {
return 0;
}
}
uint8_t aiArgmax(ai_i8 *cnnOutput)
{
/* ArgMax to associate NN output with the most likely classification label */
uint8_t prediction = 0;
ai_i8 max_out = cnnOutput[0];
for (uint8_t i = 1; i < AI_NETWORK_OUT_2_SIZE; i++) {
if (cnnOutput[i] > max_out) {
max_out = cnnOutput[i];
prediction = i;
}
}
return prediction;
}
void multi_task_network(float32_t *input, uint8_t *detectPrediction, uint8_t *classPrediction)
{
ai_i32 nbatch;
ai_error err;
float32_t detectProb = 0.0;
aiConvertInputFloat_2_Int8(input, in_data);
ai_inputs[0].data = AI_HANDLE_PTR(&in_data[0]);
/* Update the AI output handlers */
for (int i=0; i < AI_NETWORK_OUT_NUM; i++) {
ai_outputs[i].data = AI_HANDLE_PTR(&out_data[i]);
}
nbatch = ai_network_run(network, ai_inputs, ai_outputs);
if (nbatch != 1) {
err = ai_network_get_error(network);
printf("AI ai_network_run error - type=%d code=%d\r\n", err.type, err.code);
}
// Detection: convert back to float (probability)
aiConvertOutputInt8_2_Float(out_1_data, &detectProb);
*detectPrediction = roundInt(detectProb);
// Classification: take the argmax of the int8 output
*classPrediction = aiArgmax(out_2_data);
}
2023-05-17 02:44 AM
When you generated the network with X-Cube-AI or the stm32ai command line did you use the allocate input and output in the activation buffer option ?
I see in your case that you allocate the input / output outside, in that case you should not use the --allocate-inputs or --allocate-output options. This option is set by default in STM32CubeMX / X-Cube-AI and can be deselected in the advanced settings of the network (toothed wheel icon on the top right of the network parameters)
Regards
Daniel
2023-05-17 02:59 AM
Even trying without the allocate input and output in the activation buffer option does not solve the issue. I keep getting 0 outputs for both the output layers
2023-05-17 09:38 AM
Hello,
According the shared code, I think that you have an issue when you initalize the ai_buffer handlers before to call the ai_network_run() function. The passed @ are not correct, "in_data" and "out_data" are the array of pointer, code should be modified as follow:
aiConvertInputFloat_2_Int8(input, in_data);
/* ai_inputs[0].data = AI_HANDLE_PTR(&in_data[0]); */
ai_inputs[0].data = AI_HANDLE_PTR(in_data[0]);
/* Update the AI output handlers */
for (int i=0; i < AI_NETWORK_OUT_NUM; i++) {
/* ai_outputs[i].data = AI_HANDLE_PTR(&out_data[i]); */
ai_outputs[i].data = AI_HANDLE_PTR(out_data[i]);
}
Note that is also recommended to align the IO buffer:
/* C-table to store the @ of the input buffer */
AI_ALIGNED(32)
static ai_i8 in_data[AI_NETWORK_IN_1_SIZE];
/* AI input/output handlers */
static ai_buffer *ai_inputs;
static ai_buffer *ai_outputs;
/* data buffer for the output buffers */
AI_ALIGNED(32)
static ai_i8 out_1_data[AI_NETWORK_OUT_1_SIZE];
AI_ALIGNED(32)
static ai_i8 out_2_data[AI_NETWORK_OUT_2_SIZE];
Best,
Jean-Michel
2023-05-17 09:41 AM
Oops, for the ai_inputs, code was correct.
aiConvertInputFloat_2_Int8(input, in_data);
ai_inputs[0].data = AI_HANDLE_PTR(&in_data[0]);
2023-05-17 10:16 AM
Hello,
Thank you so much! This solved the issue!
I definitely got confused with pointers.