413 lines
13 KiB
C
413 lines
13 KiB
C
#include "cnn.h"
|
||
|
||
|
||
|
||
/*调试用打印函数*/
|
||
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(){
|
||
printf("CNN模型正在运行!!!\r\n");
|
||
|
||
for(int i=0;i<10;i++)printf("data[%d]: %f\r\n",i,data.array[i]);
|
||
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]);
|
||
}
|
||
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]);
|
||
}
|
||
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);
|
||
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};
|
||
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);
|
||
}
|
||
PrintfArray(yi,128,128);
|
||
//printf("\n");
|
||
printf("第四层完毕!\r\n");
|
||
//5
|
||
free2DArray(Pooling_result3,128);
|
||
float zi[7] = { 0 };
|
||
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]);
|
||
}
|
||
PrintfArray(zi,7,7);
|
||
printf("第五层完毕!\r\n");
|
||
//end
|
||
float result[7];
|
||
int max_probability_idx = calculate_probabilities(zi,result,7);
|
||
PrintfArray(result,7,7);
|
||
printf("%f, Label %d", result[max_probability_idx - 1] * 100, max_probability_idx);
|
||
}
|