Files
stm32-cnn/MY/cnn.c
2024-11-01 22:41:26 +08:00

435 lines
14 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "cnn.h"
u8 isrun;
/*调试用打印函数*/
void PrintfArray(float *array, int array_num, int elements_per_line)
{
for (int i = 0; i < array_num; i++)
{
printf("%f ", array[i]); // 打印当前元素
// 每打印完指定数量的元素后换行
if ((i + 1) % elements_per_line == 0)
{
printf("\n");
}
}
// 如果最后一行元素不足,手动换行
if (array_num % elements_per_line != 0)
{
printf("\n");
}
}
/*二维数组指针*/
void **allocate2DArray(int depth, int num, size_t elementSize)
{
void **array = (void **)mymalloc(SRAMEX, depth * sizeof(void *));
for (int d = 0; d < depth; d++)
{
array[d] = mymalloc(SRAMEX, num * elementSize); // 每个通道的展平图像
}
return array;
}
void free2DArray(float **array, int depth)
{
for (int d = 0; d < depth; d++)
{
myfree(SRAMEX, array[d]);
}
myfree(SRAMEX, array);
}
/*卷积相关函数*/
void Full(float *inputArray, int input_size, float *outputArray)
{
int i, j;
for (i = 0; i < ((input_size + 2) * (input_size + 2)); i++)
{
// 初始化填充后的数组
outputArray[i] = 0;
}
for (i = 0; i < input_size; i++)
{
// 填入数据
for (j = 0; j < input_size; j++)
{
outputArray[(i + 1) * (input_size + 2) + (j + 1)] = inputArray[i * input_size + j];
}
}
}
void Pooling(float *inputArray, int input_size,
int kernel_size, unsigned int step,
float *outputArray)
{
int output_size = (input_size - kernel_size) / step + 1;
for (int i = 0; i < output_size; i++)
{
for (int j = 0; j < output_size; j++)
{
float max_value = 0;
for (int m = 0; m < kernel_size; m++)
{
for (int n = 0; n < kernel_size; n++)
{
int input_row = i * step + m;
int input_col = j * step + n;
int input_idx = input_row * input_size + input_col;
if (inputArray[input_idx] > max_value)
{
max_value = inputArray[input_idx];
}
}
}
int output_idx = i * output_size + j;
outputArray[output_idx] = max_value;
}
}
}
void Convolution(float *inputArray, int input_size,
float *kernel, int kernel_size,
float *outputArray)
{
int i, j, m, n;
int half_k = kernel_size / 2;
int output_size = input_size - 2 * half_k;
for (i = half_k; i < input_size - half_k; i++)
{
for (j = half_k; j < input_size - half_k; j++)
{
float sum = 0;
for (m = 0; m < kernel_size; m++)
{
for (n = 0; n < kernel_size; n++)
{
int input_row = i + m - half_k;
int input_col = j + n - half_k;
int input_idx = input_row * input_size + input_col;
int kernel_idx = m * kernel_size + n;
sum += inputArray[input_idx] * kernel[kernel_idx];
}
}
int output_idx = (i - half_k) * output_size + (j - half_k);
outputArray[output_idx] = sum;
}
}
}
void Combine(float **inputArray, int input_depth, int input_size, float *outputArray)
{
int i, j, k;
int input_idx;
for (i = 0; i < input_size; i++)
{
for (j = 0; j < input_size; j++)
{
float sum = 0;
input_idx = i * input_size + j;
for (k = 0; k < input_depth; k++)
{
sum += inputArray[k][input_idx];
}
outputArray[i * input_size + j] = sum;
}
}
}
void Flatten2D(float **inputArray, int input_depth, int input_size, float *outputArray)
{
int i, j, k;
for (k = 0; k < input_depth; k++)
{
for (i = 0; i < input_size; i++)
{
for (j = 0; j < input_size; j++)
{
int input_idx = i * input_size + j;
outputArray[k * input_size * input_size + input_idx] = inputArray[k][input_idx];
}
}
}
}
void AddBias(float *inputArray, int input_num, float bias, float *outputArray)
{
for (int i = 0; i < input_num; i++)
{
outputArray[i] = inputArray[i] + bias;
}
}
float ConnectedLayer(float *inputArray, int input_num,
float *input_w, float input_b)
{
int i;
float sum = 0;
for (i = 0; i < input_num; i++)
{
sum += inputArray[i] * input_w[i];
}
sum = sum + input_b;
return sum;
}
void ReLU1(float *inputArray, int num, float *outputArray)
{
for (int i = 0; i < num; i++) {
outputArray[i] = (inputArray[i] > 0) ? inputArray[i] : 0;
}
}
float ReLU2(float data)
{
if (data > 0) {
return data;
}
else {
return 0;
}
}
void generateMatrix(float *get_data, float Max_value, int totalPoints, float CNN_data[100][100])
{
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
CNN_data[i][j] = 0;
}
}
int pointsPerInterval = totalPoints / 100;
float amplitudeStep = Max_value / 100;
// long float amplitudeStep = Max_value / 100;
for (int i = 0; i < totalPoints; i++) {
float amplitudeValue = fabs(get_data[i]);//data[n][] = 0.000696*n ~ 0.000696*(n+1)
// long float amplitudeValue = fabs(get_data[i]);//data[n][] = 0.000696*n ~ 0.000696*(n+1)
if (amplitudeValue > Max_value) {
amplitudeValue = Max_value;
} else if (amplitudeValue < 0) {
amplitudeValue = 0;
}
int intervalIndex = i / pointsPerInterval;
if (intervalIndex >= 100) intervalIndex = 99;
int amplitudeIndex = (int)(amplitudeValue / amplitudeStep);
if (amplitudeIndex >= 100) amplitudeIndex = 99;
CNN_data[amplitudeIndex][intervalIndex]++;
}
}
int calculate_probabilities(float *input_array, float *output_array, int input_num)
{
float sum = 0.0;
float temp[input_num];
for (int i = 0; i < input_num; i++)
{
temp[i] = exp(input_array[i]);
sum = sum + temp[i];
}
for (int j = 0; j < input_num; j++)
{
output_array[j] = temp[j] / sum;
}
int max_index = 0;
float max_value = output_array[0];
for (int k = 1; k < input_num; k++)
{
if (output_array[k] > max_value)
{
max_value = output_array[k];
max_index = k;
}
}
return max_index + 1;
}
void _cnn_run(){
isrun = 1;
}
void cnn_run(){
printf("CNN模型正在运行\r\nData数据集为%s\r\n",data.dname);
DEBUG_PRINTF("data[%d]: %f\r\n",0,data.array[0]);
DEBUG_PRINTF("data[%d]: %f\r\n",1,data.array[1]);
DEBUG_PRINTF("data[%d]: %f\r\n",2,data.array[2]);
DEBUG_PRINTF("data[%d]: %f\r\n",299,data.array[299]);
DEBUG_PRINTF("data[%d]: %f\r\n",300,data.array[300]);
DEBUG_PRINTF("data[%d]: %f\r\n",301,data.array[301]);
DEBUG_PRINTF("开始第一层!\r\n");
//1
float* Full_output1 = (float*)mymalloc(SRAMEX, sizeof(float) * 102 * 102);
Full(data.array, 100, Full_output1);
float** Convolution_result1_before = (float**)allocate2DArray(32, 100 * 100, sizeof(float));
float** Convolution_result1_relu = (float**)allocate2DArray(32, 100 * 100, sizeof(float));
float** Convolution_result1 = (float**)allocate2DArray(32, 100 * 100, sizeof(float));
for (int i = 0; i < 32; i++) {
float conv1_weight_new[9] = {
conv1_weight.array[i*9+0],conv1_weight.array[i*9+1],
conv1_weight.array[i*9+2],conv1_weight.array[i*9+3],
conv1_weight.array[i*9+4],conv1_weight.array[i*9+5],
conv1_weight.array[i*9+6],conv1_weight.array[i*9+7],
conv1_weight.array[i*9+8] };
Convolution(Full_output1, 102, conv1_weight_new, 3, Convolution_result1_before[i]);
}
for (int i = 0; i < 32; i++) {
AddBias(Convolution_result1_before[i], 100 * 100, conv1_bias.array[i], Convolution_result1_relu[i]);
}
for (int i = 0; i < 32; i++) {
ReLU1(Convolution_result1_relu[i], 100 * 100, Convolution_result1[i]);
}
float ** Pooling_result1 = (float**)allocate2DArray(32, 50 * 50, sizeof(float));
for (int i = 0; i < 32; i++) {
Pooling(Convolution_result1[i], 100, 2, 2, Pooling_result1[i]);
}
DEBUG_PRINTF("第一层完毕!\r\n");
//2
myfree(SRAMEX, Full_output1);
free2DArray(Convolution_result1_relu,32);
free2DArray(Convolution_result1_before,32);
free2DArray(Convolution_result1,32);
float** Full_output2 = (float**)allocate2DArray(32, 52 * 52, sizeof(float));
for (int i = 0; i < 32; i++) {
Full(Pooling_result1[i], 50, Full_output2[i]);
}
float** Convolution_result_temp_2 = (float**)allocate2DArray(32, 50 * 50, sizeof(float));
float** Convolution_result2_before = (float**)allocate2DArray(64, 50 * 50, sizeof(float));
float** Convolution_result2_relu = (float**)allocate2DArray(64, 50 * 50, sizeof(float));
float** Convolution_result2 = (float**)allocate2DArray(64, 50 * 50, sizeof(float));
for (int i = 0; i < 64; i++) {
for (int j = 0; j < 32; j++) {
float conv2_weight_new[9] = {
conv2_weight.array[i*32*9+9*j+0],conv2_weight.array[i*32*9+9*j+1],
conv2_weight.array[i*32*9+9*j+2],conv2_weight.array[i*32*9+9*j+3],
conv2_weight.array[i*32*9+9*j+4],conv2_weight.array[i*32*9+9*j+5],
conv2_weight.array[i*32*9+9*j+6],conv2_weight.array[i*32*9+9*j+7],
conv2_weight.array[i*32*9+9*j+8]
};
Convolution(Full_output2[j], 52, conv2_weight_new, 3, Convolution_result_temp_2[j]);
}
Combine(Convolution_result_temp_2, 32, 50, Convolution_result2_before[i]);
}
for (int i = 0; i < 64; i++) {
AddBias(Convolution_result2_before[i], 50 * 50, conv2_bias.array[i], Convolution_result2_relu[i]);
}
for (int i = 0; i < 64; i++) {
ReLU1(Convolution_result2_relu[i], 50 * 50, Convolution_result2[i]);
}
float** Pooling_result2 = (float**)allocate2DArray(64, 25 * 25, sizeof(float));
for (int i = 0; i < 64; i++) {
Pooling(Convolution_result2[i], 50, 2, 2, Pooling_result2[i]);
}
DEBUG_PRINTF("第二层完毕!\r\n");
//3
myfree(SRAMEX, Full_output2);
free2DArray(Pooling_result1,32);
free2DArray(Convolution_result_temp_2,32);
free2DArray(Convolution_result2_relu,64);
free2DArray(Convolution_result2_before,64);
free2DArray(Convolution_result2,64);
float** Full_output3 = (float**)allocate2DArray(64, 27 * 27, sizeof(float));
for (int i = 0; i < 64; i++) {
Full(Pooling_result2[i], 25, Full_output3[i]);
}
float** Convolution_result_temp_3 = (float**)allocate2DArray(64, 25 * 25, sizeof(float));
float** Convolution_result3_before = (float**)allocate2DArray(128, 25 * 25, sizeof(float));
float** Convolution_result3_relu = (float**)allocate2DArray(128, 25 * 25, sizeof(float));
float** Convolution_result3 = (float**)allocate2DArray(128, 25 * 25, sizeof(float));
for (int i = 0; i < 128; i++) {
for (int j = 0; j < 64; j++) {
float conv3_weight_new[9] = {
conv3_weight.array[i*64*9+9*j+0],conv3_weight.array[i*64*9+9*j+1],
conv3_weight.array[i*64*9+9*j+2],conv3_weight.array[i*64*9+9*j+3],
conv3_weight.array[i*64*9+9*j+4],conv3_weight.array[i*64*9+9*j+5],
conv3_weight.array[i*64*9+9*j+6],conv3_weight.array[i*64*9+9*j+7],
conv3_weight.array[i*64*9+9*j+8]
};
Convolution(Full_output3[j], 27, conv3_weight_new, 3, Convolution_result_temp_3[j]);
}
Combine(Convolution_result_temp_3, 64, 25, Convolution_result3_before[i]);
}
for (int i = 0; i < 128; i++) {
AddBias(Convolution_result3_before[i], 25 * 25, conv3_bias.array[i], Convolution_result3_relu[i]);
}
for (int i = 0; i < 128; i++) {
ReLU1(Convolution_result3_relu[i], 25 * 25, Convolution_result3[i]);
}
float** Pooling_result3 = (float**)allocate2DArray(128, 12 * 12, sizeof(float));
for (int i = 0; i < 128; i++) {
Pooling(Convolution_result3_before[i], 25, 2, 2, Pooling_result3[i]);
}
float* xi = (float*)mymalloc(SRAMEX, sizeof(float) * 128 * 12 * 12);
Flatten2D(Pooling_result3, 128, 12, xi);
DEBUG_PRINTF("第三层完毕!\r\n");
//4
myfree(SRAMEX, Full_output3);
free2DArray(Pooling_result2,64);
free2DArray(Convolution_result_temp_3,64);
free2DArray(Convolution_result3_relu,128);
free2DArray(Convolution_result3_before,128);
free2DArray(Convolution_result3,128);
//float yi[128] = {0};
float *yi = (float *)mymalloc(SRAMEX, 128 * sizeof(float));
memset(yi, 0, 128 * sizeof(float));
for (int i = 0; i < 128; i++) {
float sum = 0;
float* fc1_weight_new = (float*)mymalloc(SRAMEX, sizeof(float) * 128 * 12 * 12);
memcpy(fc1_weight_new,&fc1_weight.array[i*128*12*12],128*12*12 * sizeof(float));
sum = ConnectedLayer(xi, 128 * 12 * 12, fc1_weight_new, fc1_bias.array[i]);
yi[i] = ReLU2(sum);
myfree(SRAMEX, fc1_weight_new);
}
//printf("\n");
DEBUG_PRINTF("第四层完毕!\r\n");
//PrintfArray(yi,128,128);
//5
free2DArray(Pooling_result3,128);
//float zi[7] = { 0 };
float *zi = (float *)mymalloc(SRAMEX, 7 * sizeof(float));
memset(yi, 0, 7 * sizeof(float));
for (int i = 0; i < 7; i++) {
float fc2_weight_new[128];
memcpy(fc2_weight_new,&fc2_weight.array[i*128],128 * sizeof(float));
zi[i] = ConnectedLayer(yi, 128, fc2_weight_new, fc2_bias.array[i]);
}
DEBUG_PRINTF("第五层完毕!\r\n");
PrintfArray(zi,7,7);
//end
float *result = (float *)mymalloc(SRAMEX, 7 * sizeof(float));
int max_probability_idx = calculate_probabilities(zi,result,7);
PrintfArray(result,7,7);
printf("%f, Label %d\r\n", result[max_probability_idx - 1] * 100, max_probability_idx);
myfree(SRAMEX, xi);
myfree(SRAMEX, yi);
myfree(SRAMEX, zi);
myfree(SRAMEX, result);
isrun = 0;
}