cancel
Showing results for 
Search instead for 
Did you mean: 

I had some problems when i want to deploy a gas classification model from STM32cubemx with cube_ai

Sunjing
Associate II

My binary classification algorithm has one input (270 data) and one output, I refer to section 6.4 of the code(AI:How to perform motion sensing on STM32L4 IoTnode - stm32mcu (stmicroelectronics.cn))

Question 1:

but the output category is always wrong, I don't know if the input data is wrong or the output result function is wrong
I used a dummy dataset 【test_buf】 as my input data, and I know that the category of the current 【test_buf】 is class1 (H2), but it always output class0(CO)

 

Question 2:

How can I tell if the algorithm is doing calculations on the input data

Is the algorithm effective?

 

Attach my code, please check, I would appreciate your help!!!!!! thanks!

 

 

/**
  ******************************************************************************
  * @file    app_x-cube-ai.c
  * @author  X-CUBE-AI C code generator
  * @brief   AI program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */

/*
 * Description
 *   v1.0 - Minimum template to show how to use the Embedded Client API
 *          model. Only one input and one output is supported. All
 *          memory resources are allocated statically (AI_NETWORK_XX, defines
 *          are used).
 *          Re-target of the printf function is out-of-scope.
 *   v2.0 - add multiple IO and/or multiple heap support
 *
 *   For more information, see the embeded documentation:
 *
 *       [1] %X_CUBE_AI_DIR%/Documentation/index.html
 *
 *   X_CUBE_AI_DIR indicates the location where the X-CUBE-AI pack is installed
 *   typical : C:\Users\<user_name>\STM32Cube\Repository\STMicroelectronics\X-CUBE-AI\7.1.0
 */

# ifdef __cplusplus
extern "C" {
#endif

	/* Includes ------------------------------------------------------------------*/

#if defined ( __ICCARM__ )
#elif defined ( __CC_ARM ) || ( __GNUC__ )
#endif

	/* System headers */
# include <stdint.h>
# include <stdlib.h>
# include <stdio.h>
# include <inttypes.h>
# include <string.h>

# include "app_x-cube-ai.h"
# include "main.h"
# include "ai_datatypes_defines.h"
# include "network.h"
# include "network_data.h"


	extern uint16_t ai_process_buf[270];


	/* USER CODE BEGIN includes */
	/* USER CODE END includes */

	/* IO buffers ----------------------------------------------------------------*/

#if !defined(AI_NETWORK_INPUTS_IN_ACTIVATIONS)
	AI_ALIGNED(4) ai_i8 data_in_1[AI_NETWORK_IN_1_SIZE_BYTES];
	ai_i8* data_ins[AI_NETWORK_IN_NUM] = {
data_in_1
};
#else
ai_i8* data_ins[AI_NETWORK_IN_NUM] = {
NULL
};
#endif

#if !defined(AI_NETWORK_OUTPUTS_IN_ACTIVATIONS)
	AI_ALIGNED(4) ai_i8 data_out_1[AI_NETWORK_OUT_1_SIZE_BYTES];
	AI_ALIGNED(4) ai_i8 data_out_2[AI_NETWORK_OUT_2_SIZE_BYTES];
	ai_i8* data_outs[AI_NETWORK_OUT_NUM] = {
data_out_1,
data_out_2
};
#else
ai_i8* data_outs[AI_NETWORK_OUT_NUM] = {
NULL,
NULL
};
#endif

	/* Activations buffers -------------------------------------------------------*/

	AI_ALIGNED(32)
static uint8_t pool0[AI_NETWORK_DATA_ACTIVATION_1_SIZE];

	ai_handle data_activations0[] = { pool0 };

	/* AI objects ----------------------------------------------------------------*/

	static ai_handle network = AI_HANDLE_NULL;


	float aiInData[AI_NETWORK_IN_1_SIZE];
	float aiOutData[AI_NETWORK_OUT_1_SIZE];
	////ai_u8 activations[AI_NETWORK_DATA_ACTIVATIONS_SIZE];
	const char* activities[AI_NETWORK_OUT_1_SIZE] = {
	  "CO" , "H2"
	};

	//static ai_buffer* ai_input;
	//static ai_buffer* ai_output;

	ai_buffer* ai_input;
	ai_buffer* ai_output;

	static void ai_log_err(const ai_error err, const char* fct)
{
		/* USER CODE BEGIN log */
		if (fct)
			printf("TEMPLATE - Error (%s) - type=0x%02x code=0x%02x\r\n", fct,
				err.type, err.code);
		else
			printf("TEMPLATE - Error - type=0x%02x code=0x%02x\r\n", err.type, err.code);

		do { } while (1);
		/* USER CODE END log */
	}

	static int ai_boostrap(ai_handle* act_addr)
	{
		ai_error err;

		/* Create and initialize an instance of the model */
		err = ai_network_create_and_init(&network, act_addr, NULL);
		if (err.type != AI_ERROR_NONE)
		{
			ai_log_err(err, "ai_network_create_and_init");
			return -1;
		}

		ai_input = ai_network_inputs_get(network, NULL);
		ai_output = ai_network_outputs_get(network, NULL);

#if defined(AI_NETWORK_INPUTS_IN_ACTIVATIONS)
  /*  In the case where "--allocate-inputs" option is used, memory buffer can be
   *  used from the activations buffer. This is not mandatory.
   */
  for (int idx=0; idx < AI_NETWORK_IN_NUM; idx++) {
	data_ins[idx] = ai_input[idx].data;
  }
#else
		for (int idx = 0; idx < AI_NETWORK_IN_NUM; idx++)
		{
			ai_input[idx].data = data_ins[idx];
		}
#endif

#if defined(AI_NETWORK_OUTPUTS_IN_ACTIVATIONS)
  /*  In the case where "--allocate-outputs" option is used, memory buffer can be
   *  used from the activations buffer. This is no mandatory.
   */
  for (int idx=0; idx < AI_NETWORK_OUT_NUM; idx++) {
	data_outs[idx] = ai_output[idx].data;
  }
#else
		for (int idx = 0; idx < AI_NETWORK_OUT_NUM; idx++)
		{
			ai_output[idx].data = data_outs[idx];
		}
#endif

		return 0;
	}



	//ai_input = (ai_buffer*)malloc(sizeof(ai_buffer));
	float test_buf[270] = { 0.5, 0, 0, 0.5, 0, 0, 0.5, 0, 0, 0.5, 0, 0, 0.5, 2, 1, 0.5, 5, 2, 0.5, 7, 3, 0.5, 7, 3, 0.5, 7, 3, 0.5, 10, 4, 0.5, 10, 4, 0.5, 12, 5, 0.5, 12, 5, 0.5, 12, 5, 0.5, 12, 5, 0.5, 12, 5, 0.5, 12, 5, 0.5, 12, 5, 0.5, 12, 5, 0.5, 12, 5, 0.5, 10, 4, 0.5, 10, 4, 0.5, 10, 4, 0.5, 10, 4, 0.5, 10, 4, 0.5, 10, 4, 0.5, 10, 4, 0.5, 10, 4, 0.5, 10, 4, 0.5, 15, 6, 0.5, 15, 6, 0.5, 15, 6, 0.5, 25, 10, 0.5, 25, 10, 0.5, 42, 17, 0.5, 67, 27, 1.6, 67, 27, 1.6, 102, 41, 1.6, 145, 58, 1.6, 195, 78, 1.6, 195, 78, 3.5, 247, 99, 3.5, 247, 99, 3.5, 305, 122, 3.5, 362, 145, 3.5, 420, 168, 3.5, 420, 168, 3.5, 477, 191, 3.5, 477, 191, 7.4, 540, 216, 7.4, 602, 241, 7.4, 602, 241, 7.4, 670, 268, 14.0, 742, 297, 14.0, 820, 328, 14.0, 820, 328, 14.0, 907, 363, 14.0, 1000, 400, 24.3, 1000, 400, 24.3, 1105, 442, 24.3, 1105, 442, 24.3, 1212, 485, 24.3, 1327, 531, 24.3, 1327, 531, 39.7, 1442, 577, 39.7, 1557, 623, 39.7, 1665, 666, 39.7, 1665, 666, 39.7, 1767, 707, 61.6, 1767, 707, 61.6, 1767, 707, 61.6, 1857, 743, 61.6, 1857, 743, 61.6, 1937, 775, 61.6, 2005, 802, 61.6, 2005, 802, 91.5, 2065, 826, 91.5, 2130, 852, 91.5, 2202, 881, 91.5, 2202, 881, 91.5, 2290, 916, 130.0, 2392, 957, 130.0, 2392, 957, 130.0, 2497, 999, 130.0, 2595, 1038, 130.0, 2595, 1038, 177.2, 2672, 1069, 177.2, 2672, 1069, 177.2, 2725, 1090, 177.2, 2755, 1102 };
	//double out_data[2];
	int out_buf[2];


	int ai_run(const void* in_data, void* out_data)  
{

		ai_i32 batch;

		/* 1 - Update IO handlers with the @ of the data payload */


		/* 2 - Initialize input/output buffer handlers */
		ai_input[0].data = AI_HANDLE_PTR(in_data);
		ai_output[0].data = AI_HANDLE_PTR(out_data);

		/* 3 - Perform the inference */
		batch = ai_network_run(network, &ai_input[0], &ai_output[0]);
		if (batch != 1)
		{
			ai_log_err(ai_network_get_error(network),
			"ai_network_run");
			return -1;
		}

		return 0;
	}





	//****************************************************************************//




	/* USER CODE BEGIN 2 */
	int acquire_and_process_data(ai_i8* data[])
	{
		/* fill the inputs of the c-model
		for (int idx=0; idx < AI_NETWORK_IN_NUM; idx++ )
		{
			data[idx] = ....
		}

		*/


		/*
		for(int i=0;i<270;i++)
		{	
			data[i]=(ai_i8 *)&ai_process_buf[i];
			//ai_i8 my_buf = (ai_i8)ai_process_buf[i];

		}*/
		//printf("acquire_and_process_data\r\n");

		return 0;
	}

	int post_process(ai_i8* data[])
	{
		/* process the predictions
		for (int idx=0; idx < AI_NETWORK_OUT_NUM; idx++ )
		{
			data[idx] = ....
		}

		*/
		return 0;
	}

	/**/
	static uint32_t argmax(const float * values, uint32_t len)
	{
	  float max_value = values[0];
	  uint32_t max_index = 0;
	  for (uint32_t i = 1; i < len; i++) {
	    if (values[i] > max_value) {
	      max_value = values[i];
	      max_index = i;
	    }
	  }
	  return max_index;
	}

	/**/

	/* USER CODE END 2 */

	/* Entry points --------------------------------------------------------------*/
	extern uint16_t ai_process_buf[270];
	void MX_X_CUBE_AI_Init(void)
	{
		/* USER CODE BEGIN 5 */
		printf("\r\nTEMPLATE - initialization\r\n");

		ai_boostrap(data_activations0);
		/* USER CODE END 5 */
	}

	void MX_X_CUBE_AI_Process(void)
	{
		/* USER CODE BEGIN 6 */
		int res = -1;

		printf("TEMPLATE - run - main loop\r\n");

		if (network)
		{

			/* 1 - acquire and pre-process input data */
			res = acquire_and_process_data(data_ins);
			/* 2 - process the data - call inference engine */
			if (res == 0)
				res = ai_run((const void*)test_buf, (void*)out_buf);
	//res = ai_run((const void*)test_buf, aiOutData);
	/* 3- post-process the predictions */
	if (res == 0)
	{
		//res = post_process(data_outs);

		   for (uint32_t i = 0; i < AI_NETWORK_OUT_1_SIZE; i++) {
	          printf("%f ", aiOutData[i]);
	        }
	        uint32_t class = argmax(aiOutData, AI_NETWORK_OUT_1_SIZE);
	       printf(": %d - %s\r\n", (int) class, activities[class]);
	}


#if 0
    do {
      /* 1 - acquire and pre-process input data */
      res = acquire_and_process_data(data_ins);
      /* 2 - process the data - call inference engine */
      if (res == 0)
        res = ai_run();
      /* 3- post-process the predictions */
      if (res == 0)
        res = post_process(data_outs);
    } while (res==0);
#endif
}

if (res)
{
	ai_error err = { AI_ERROR_INVALID_STATE, AI_ERROR_CODE_NETWORK };
	ai_log_err(err, "Process has FAILED");
}
    /* USER CODE END 6 */
}
#ifdef __cplusplus
}
#endif

 

 

1 REPLY 1
jean-michel.d
ST Employee

Hi Sunjing,

Not easy to review your code, however, I think that in MX_X_CUBE_AI_Process() function, the second parameter to call ai_run() is not correct, you need to pass "aiOutData" instead "out_buf" to be able to read the generated results.

 

		if (network)
		{

			/* 1 - acquire and pre-process input data */
			res = acquire_and_process_data(data_ins);
			/* 2 - process the data - call inference engine */
			if (res == 0)
				res = ai_run((const void*)test_buf, (void*)aiOutData); <- fix here
	//res = ai_run((const void*)test_buf, aiOutData);
	/* 3- post-process the predictions */
	if (res == 0)
	{

 

br,

Jean-Michel