From 8d49d67929efa0a52d5be0721b309fbe6ad47192 Mon Sep 17 00:00:00 2001 From: Qiea <1310371422@qq.com> Date: Mon, 11 Nov 2024 18:17:48 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E6=A4=8Dc=5Fcnn=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PORTING/CNN/cnn.c | 784 ++++++++++++---------------------------- PORTING/CNN/cnn.h | 33 +- PORTING/CNN/cnn_model.c | 40 +- PORTING/CNN/cnn_model.h | 144 +------- 4 files changed, 292 insertions(+), 709 deletions(-) diff --git a/PORTING/CNN/cnn.c b/PORTING/CNN/cnn.c index fdcd1ad..0b268bf 100644 --- a/PORTING/CNN/cnn.c +++ b/PORTING/CNN/cnn.c @@ -6,319 +6,234 @@ void _cnn_run(){ isrun = 1; } -/*调试用打印函数*/ -/// @brief 打印图像矩阵 -/// @param array 输入的图像 -/// @param array_num 输入图像总的个数 -/// @param elements_per_line 每一行的个数,个数到了自动换行 -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"); +void print_rslt(float* rslt, u8 input_matrix_length, u32 length){ + int _tmp = 0; + printf("[0:0]"); + for (int i = 0; i < length; i++) { + printf("%f ",rslt[i]); + if ((i + 1) % input_matrix_length == 0) { + printf("\n[%d:%d]",++_tmp,i+1); } } - // 如果最后一行元素不足,手动换行 - if (array_num % elements_per_line != 0) - { - printf("\n"); - } + printf("\r\n"); } - - -void PrintfResArray(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("\t"); +// 将原始矩阵复制到填充后的矩阵中央 +float* expand(const float* old_matrix, int old_matrix_length, int layer){ + float* new_matrix = (float *)mymalloc(SRAMEX,sizeof(float)*layer*(old_matrix_length+2)*(old_matrix_length+2)); + memset(new_matrix, 0, sizeof(float)*layer*(old_matrix_length+2)*(old_matrix_length+2)); + for(int l=0; l < layer; l++){ + for (int i = 0; i < old_matrix_length; i++) { + for (int j = 0; j < old_matrix_length; j++) { + new_matrix[(i + 1) * (old_matrix_length+2) + (j + 1) + + l * (old_matrix_length+2) * (old_matrix_length+2)] + = old_matrix[i * old_matrix_length + j + + l * (old_matrix_length) * (old_matrix_length)]; + } } } + return new_matrix; } +//model 模型名字 +//input_matrix 输入图像 +//input_matrix_length 输入图像的边长:102 +//c_rl 输出图像的边长:100 +//返回卷积的结果 +float* convolution(Model model_w, Model model_b, const float* input_matrix, int input_matrix_length){ + // 初始化卷积层参数 + int im_l = input_matrix_length; + int cr_l = input_matrix_length - 2; + float conv_temp; // 临时变量,用于存储卷积计算的中间结果 + //用于合并前的数组,具有32*64*50*50(第二层)的大小 + float* _conv_rlst = (float *) mymalloc(SRAMEX,sizeof (float) * model_w.channel * model_w.num_kernels * (cr_l * cr_l)); + memset(_conv_rlst, 0, sizeof (float) * model_w.channel * model_w.num_kernels * (cr_l * cr_l)); + //子图合并后的数组 + float* conv_rlst = (float *) mymalloc(SRAMEX,sizeof (float) * model_w.num_kernels * (cr_l * cr_l)); + memset(conv_rlst, 0, sizeof (float) * model_w.num_kernels * (cr_l * cr_l)); -/*二维数组指针*/ -/// @brief 动态申请二维数组,类型为elementSize -/// @param depth 二维数组深度,即a[depth][] -/// @param num 长度,即a[][num] -/// @param elementSize 二维数组类型 -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; -} - -/// @brief 释放通过allocate2DArray申请的二维数组 -/// @param array 二维数组 -/// @param depth 深度 -void free2DArray(float **array, int depth) -{ - for (int d = 0; d < depth; d++) - { - myfree(SRAMEX, array[d]); - } - myfree(SRAMEX, array); -} - -/*卷积相关函数*/ -/// @brief 对输入的图像进行四周0填充 -/// @param inputArray 输入的图像 -/// @param input_size 输入的单行的元素个数,例如:100即一行有100个元素 -/// @param outputArray 保存输出的图像 -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]; + // 遍历30个卷积核(假设有30个通道) + for(int c=0; c < model_w.channel; c++){ + for(int k=0; k < model_w.num_kernels; k++){ + for(int row = 0; row < cr_l; row++) { + for (int col = 0; col < cr_l; col++) { + conv_temp = 0; // 每个输出像素初始化为0 + // 进行3x3的卷积操作 + for (int x = 0; x < 3; x++) { + for (int y = 0; y < 3; y++) { + // 将输入图像的对应像素与卷积核权重相乘,并累加到conv_temp + conv_temp += input_matrix[(c*im_l*im_l) + (row*(im_l)+col) + (x*(im_l)+y)] + * model_w.array[((c+k*model_w.channel)*3*3) + (x*3+y)]; + } + } + _conv_rlst[(c*model_w.num_kernels*cr_l*cr_l) + (k*cr_l*cr_l) + (row*cr_l+col)] = conv_temp; + } + } } } + //合并子图 + { + for(int k=0; k < model_w.num_kernels; k++) { + for (int row = 0; row < cr_l; row++) { + for (int col = 0; col < cr_l; col++) { + conv_temp = 0; // 每个输出像素初始化为0 + for (int c = 0; c < model_w.channel; c++) { + conv_temp += _conv_rlst[(c * model_w.num_kernels * cr_l * cr_l) + (k * cr_l * cr_l) + (row * cr_l + col)]; + } + // 加上对应卷积核的偏置 + conv_temp += model_b.array[k]; + // 激活函数:ReLU(将小于0的值设为0) + if (conv_temp > 0) + conv_rlst[(k * (cr_l * cr_l)) + (row * cr_l) + (col)] = conv_temp; // 如果卷积结果大于0,存入结果数组 + else + conv_rlst[(k * (cr_l * cr_l)) + (row * cr_l) + (col)] = 0; // 否则存入0 + } + } + } + } + myfree(SRAMEX,_conv_rlst); + return conv_rlst; } - -/// @brief 对输入的图像进行池化,选取kernel_size*kernel_size的范围的最大值,步长为step -/// @param inputArray 输入的图像 -/// @param input_size 输入图像的单行的元素个数 -/// @param kernel_size 池化核的单行的元素个数 -/// @param step 步进值 -/// @param outputArray 保存输出的图像 -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++) +//num_kernels 卷积核的个数:32 +//area 池化的面积:2*2 +//input_matrix 输入图像 +//input_matrix_length 输入图像的边长:100 +//输出图像的边长:50 +//返回池化的结果 +float* pooling(Model model_w, const float* input_matrix, u8 input_matrix_length){ + u8 im_l = input_matrix_length; + float pool_temp = 0; // 临时变量,用于存储池化操作的最大值 + float* pool_rslt = (float *) mymalloc(SRAMEX,sizeof (float)*model_w.num_kernels*im_l*im_l); + memset(pool_rslt, 0, sizeof (float)*model_w.num_kernels*im_l*im_l); + // 遍历30个通道(与卷积核数量相同) + for(u8 n=0; n max_value) + for(u8 y=0; y<2; y++) { - max_value = inputArray[input_idx]; + // 更新当前池化区域的最大值 + if(pool_temp <= input_matrix[row*im_l+col+x*im_l+y+n*(im_l*im_l)]) + pool_temp = input_matrix[row*im_l+col+x*im_l+y+n*(im_l*im_l)]; } } + // 将最大值存入池化结果数组 + pool_rslt[(row/2)*(im_l/2)+col/2+n*((im_l/2)*(im_l/2))] = pool_temp; } - - int output_idx = i * output_size + j; - outputArray[output_idx] = max_value; } } + return pool_rslt; } -/// @brief 对输入图像进行卷积,选取kernel_size*kernel_size的范围,这里步长为1 -/// @param inputArray 输入的图像 -/// @param input_size 输入图像的单行的元素个数 -/// @param kernel 输入的卷积核,即kernel_size * kernel_size的卷积核参数 -/// @param kernel_size 池化核的单行的元素个数 -/// @param outputArray 保存输出的图像 -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; +float* hidden(const float* input_matrix){ + float affine1_temp; // 临时变量,用于存储全连接层的中间结果 + float *affine1_rslt = (float *) mymalloc(SRAMEX,sizeof(float)*128); + memset(affine1_rslt, 0, sizeof(float)*128); - for (i = half_k; i < input_size - half_k; i++) + // 遍历128个神经元(假设隐藏层有128个神经元) + for(u8 n=0; n<128; n++) { - for (j = half_k; j < input_size - half_k; j++) + affine1_temp = 0; // 每个神经元的输出初始化为0 + + // 进行矩阵乘法,将池化层输出展平为一维向量后,与全连接层权重进行点积 + for(int i=0; i<(128*12*12); i++) { - 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; + affine1_temp = affine1_temp + input_matrix[i] * fc1_weight.array[i+(128*12*12)*n]; } + + // 加上对应神经元的偏置 + affine1_temp = affine1_temp + fc1_bias.array[n]; + + // 激活函数:ReLU(将小于0的值设为0) + if(affine1_temp > 0) + affine1_rslt[n] = affine1_temp; // 如果结果大于0,存入结果数组 + else + affine1_rslt[n] = 0; // 否则存入0 } + + // print_rslt(affine1_rslt,1,128); + + return affine1_rslt; } -/// @brief 对二维数组做合并处理,对应位相加 -/// @param inputArray 输入的图像 -/// @param input_depth 输入图像的深度,即a[input_depth][] -/// @param input_size 输入图像的单行的元素个数 -/// @param outputArray 保存输出的图像 -void Combine(float **inputArray, int input_depth, int input_size, float *outputArray) -{ - int i, j, k; - int input_idx; +float* output(const float* input_matrix){ + float affine2_temp; // 临时变量,用于存储输出层的中间结果 + float *affine2_rslt = (float *) mymalloc(SRAMEX,sizeof(float)*7); + memset(affine2_rslt, 0, sizeof(float)*7); - for (i = 0; i < input_size; i++) +// 比较输出层的最大值 + float temp = -100; // 用于存储最大值的临时变量,初始化为一个非常小的值 + int predict_num; // 用于存储预测的数字(对应最大值的索引) + +// 遍历10个输出神经元(假设有10个类别) + for(int n=0; n<7; n++) { - - for (j = 0; j < input_size; j++) + affine2_temp = 0; // 当前神经元的输出初始化为0 + + // 进行矩阵乘法,将隐藏层的输出与输出层权重进行点积 + for(int i=0; i<128; i++) { - 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; + affine2_temp = affine2_temp + fc2_weight.array[i+128*n] * input_matrix[i]; } - } -} -/// @brief 展开二维数组成一维数组 -/// @param inputArray 输入的图像 -/// @param input_depth 输入图像的深度,即a[input_depth][] -/// @param input_size 输入图像的单行的元素个数 -/// @param outputArray 保存输出的图像 -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++) + // 加上对应神经元的偏置 + affine2_temp = affine2_temp + fc2_weight.array[n]; + affine2_rslt[n] = affine2_temp; // 存储输出层的结果 + + // 寻找最大值 + if(temp <= affine2_rslt[n]) { - 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]; - } + temp = affine2_rslt[n]; // 更新最大值 + predict_num = n; // 记录最大值对应的类别索引 } } + + print_rslt(affine2_rslt,7,7); + printf("Label is:%d\r\n",predict_num+1); + + return affine2_rslt; } -/// @brief 对输入图像的每一位添加偏置 -/// @param inputArray 输入的图像 -/// @param input_num 输入图像总的元素个数 -/// @param bias 偏置核 -/// @param outputArray 保存输出的图像 -void AddBias(float *inputArray, int input_num, float bias, float *outputArray) -{ - for (int i = 0; i < input_num; i++) - { - outputArray[i] = inputArray[i] + bias; - } -} -/// @brief 全连接层操作:对一个神经元做全连接 -/// @param inputArray 输入的图像 -/// @param input_num 输入图像总的元素个数 -/// @param input_w 输入的权重核 -/// @param input_b 输入的偏置核 -/// @return 一个神经元的结果,类型为float -float ConnectedLayer(float *inputArray, int input_num, - float *input_w, float input_b) + +void calculate_statistics(Model model, float* value) { - int i; + value[0] = fabsf(model.array[0]); float sum = 0; - for (i = 0; i < input_num; i++) - { - sum += inputArray[i] * input_w[i]; - } - sum = sum + input_b; - return sum; -} + float sum_sq = 0; -/// @brief ReLU函数激活,此函数是对一整个数组做激活:若值大于等于0,则保留值,否则置0 -/// @param inputArray 输入的图像 -/// @param num 输入图像总的元素个数 -/// @param outputArray 保存输出的矩阵 -void ReLU1(float *inputArray, int num, float *outputArray) -{ - for (int i = 0; i < num; i++) { - outputArray[i] = (inputArray[i] > 0) ? inputArray[i] : 0; - } -} + for (int i = 0; i < model.maxlength; i++) { + float abs_val = fabsf(model.array[i]); -/// @brief ReLU函数激活,此函数是对一个数做激活:若值大于等于0,则保留值,否则置0 -/// @param data 输入的数 -/// @return 激活完的数,类型为float -float ReLU2(float data) -{ - if (data > 0) { - return data; - } - else { - return 0; - } -} - - -//求数值 - -/// @brief 对一个输入数组求平均值、最大值和标准差 -/// @param arr 输入的数组 -/// @param size 数组的长度 -/// @param max_val 最大值保存 -/// @param mean 平均值保存 -/// @param std_dev 标准差保存 -void calculate_statistics(float arr[], int size, float *max_val, float *mean, float *std_dev) -{ - *max_val = fabs(arr[0]); - float sum = 0.0; - float sum_sq = 0.0; - - for (int i = 0; i < size; i++) { - float abs_val = fabs(arr[i]); - - if (abs_val > *max_val) { - *max_val = abs_val; + if (abs_val > value[0]) { + value[0] = abs_val; } sum += abs_val; - sum_sq += abs_val * abs_val; + sum_sq += abs_val * abs_val; } - *mean = sum / size; + value[1] = sum / (float)model.maxlength; - float variance = (sum_sq / size) - (*mean * *mean); - *std_dev = sqrt(variance); + float variance = (sum_sq / (float)model.maxlength) - (value[1] * value[1]); + value[2] = sqrtf(variance); } -//判断放电 -/// @brief 判断是否放电 -/// @param arr 输入数组 -/// @param size 数组的长度 -/// @param mean 平均值 -/// @param std_dev 标准差 -/// @return 如果超过阈值则返回1,否则返回0 -int check_threshold(float arr[], int size, float *mean, float *std_dev) +u8 check_threshold(Model model, const float* value) { - const float threshold = 20.0; + const float threshold = 20; - for (int i = 0; i < size; i++) { - float K = (arr[i] - *mean) / *std_dev; + for (int i = 0; i < model.maxlength; i++) { + float K = (fabsf(model.array[i]) - value[1]) / value[2]; if (K > threshold) { return 1; } @@ -326,306 +241,85 @@ int check_threshold(float arr[], int size, float *mean, float *std_dev) return 0; } -/// @brief 生成100*100矩阵 -/// @param get_data 输入的数组 -/// @param Max_value 输入最大值 -/// @param totalPoints 总的数组元素个数 -/// @param CNN_data 输出的数组(二维) -void generateMatrix(float *get_data, float Max_value, int totalPoints, float CNN_data[100*100]) +float* generateMatrix(Model model, const float* value) { - for (int i = 0; i < 100; i++) { - for (int j = 0; j < 100; j++) { - CNN_data[i*100+j] = 0; - } - } + float* CNN_data = (float*) mymalloc(SRAMEX,sizeof(float)*100*100); + memset(CNN_data, 0, sizeof(float)*100*100); - int pointsPerInterval = totalPoints / 100; - float amplitudeStep = Max_value / 100; + u16 x = model.maxlength / 100; + float y = value[0] / 100; - for (int i = 0; i < totalPoints; i++) { - float amplitudeValue = fabsf(get_data[i]); + for (int i = 0; i < model.maxlength; i++) { + float absolutevalue = fabsf(model.array[i]); - if (amplitudeValue == 0.0f) { + if (!absolutevalue) { continue; } - int intervalIndex = i / pointsPerInterval; - if (intervalIndex >= 100) intervalIndex = 99; + int xIndex = i / x; + if (xIndex >= 100) xIndex = 99; - int amplitudeIndex = 99 - (int)(amplitudeValue / amplitudeStep); - if (amplitudeIndex < 0) amplitudeIndex = 0; + int yIndex = (int)(absolutevalue / y); + if (yIndex < 0) yIndex = 0; - CNN_data[amplitudeIndex*100+intervalIndex]++; + CNN_data[yIndex * 100 + xIndex]++; } + return CNN_data; } -/// @brief 计算概率 -/// @param input_array 输入数组 -/// @param output_array 保存输出的数组 -/// @param input_num 输入元素个数 -/// @return 返回概率中最大值的索引(默认+1,即如果是数组的a[0]最大,则返回1) -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]; +void cnn_run(){ + float value[3] = {0}; + calculate_statistics(data,&value[0]); + if (check_threshold(data,&value[0])){ + float* _data = generateMatrix(data,&value[0]); + + //第一层:填充102 * 102 + float* expand_matrix_1 = expand(_data, 100, 1); + float* conv_rlst_1 = convolution(conv1_weight,conv1_bias,expand_matrix_1, 102); + float* pool_rslt_1 = pooling(conv1_weight, conv_rlst_1, 100); + + myfree(SRAMEX,_data); + _data = NULL; + myfree(SRAMEX,expand_matrix_1); + expand_matrix_1 = NULL; + myfree(SRAMEX,conv_rlst_1); + conv_rlst_1 = NULL; + + //第二层:填充32 * 52 * 52 + float* expand_matrix_2 = expand(pool_rslt_1, 50, 32); + float* conv_rlst_2 = convolution(conv2_weight,conv2_bias,expand_matrix_2, 52); + float* pool_rslt_2 = pooling(conv2_weight, conv_rlst_2, 50); + + myfree(SRAMEX,pool_rslt_1); + pool_rslt_1 = NULL; + myfree(SRAMEX,expand_matrix_2); + expand_matrix_2 = NULL; + myfree(SRAMEX,conv_rlst_2); + conv_rlst_2 = NULL; + + //第三层:填充 64 * 27 * 27 + float* expand_matrix_3 = expand(pool_rslt_2, 25, 64); + float* conv_rlst_3 = convolution(conv3_weight,conv3_bias,expand_matrix_3, 27); + float* pool_rslt_3 = pooling(conv3_weight, conv_rlst_3, 25); + + myfree(SRAMEX,pool_rslt_2); + pool_rslt_2 = NULL; + myfree(SRAMEX,expand_matrix_3); + expand_matrix_3 = NULL; + myfree(SRAMEX,conv_rlst_3); + conv_rlst_3 = NULL; + + float* affine1_rslt = hidden(pool_rslt_3); + float* affine2_rslt = output(affine1_rslt); + + myfree(SRAMEX,pool_rslt_3); + pool_rslt_3 = NULL; + myfree(SRAMEX,affine1_rslt); + affine1_rslt = NULL; + myfree(SRAMEX,affine2_rslt); + affine2_rslt = NULL; + + } else{ + printf("未放电!最大值:%f 平均值:%f 标准差:%f\r\n",value[0],value[1],value[2]); } - 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; } - - -/*这个程序仅是基本验证程序能跑,还无优化*/ - -/*原始数据个数 -*目前不保证能否在数目不对的情况下计算,有可能程序出错。 -*目前没法再没有提前给出元素个数的情况下计算。 -*原始数据个数仅印象预处理的计算,后面的卷积程序用不到。 -*/ - -/// @brief 完整的程序 -/// @param data 输入的一维数组原始数据 --> data.array代替 -/// @param size 原始数据个数 --> data.maxlength代替 -void cnn_run() -{ - float maxvalue = 0.0; //最大值 - float meanvalue = 0.0; //平均值 - float std_devvalue = 0.0; //标准差 - int index = 0; //索引(忘了干啥的) - float *Matrix_data = (float*)mymalloc(SRAMEX, sizeof(float) * 100 * 100); //生成的100*100的矩阵保存在这 - - 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("data[%d]: %f\r\n",1249997,data.array[1249997]); - DEBUG_PRINTF("data[%d]: %f\r\n",1249998,data.array[1249998]); - DEBUG_PRINTF("data[%d]: %f\r\n",1249999,data.array[1249999]); - - /*计算数据*/ - calculate_statistics(data.array, data.maxlength, &maxvalue, &meanvalue,&std_devvalue); - - /*判断数据是否超过阈值*/ - int x = check_threshold(data.array, data.maxlength, &meanvalue, &std_devvalue); - if (x == 1) { - printf("Start\r\n"); - //pre 开始预处理 - /*生成矩阵*/ - generateMatrix(data.array, maxvalue, data.maxlength, Matrix_data); - float *CNN_data = (float*)mymalloc(SRAMEX, sizeof(float) * 100 * 100); - /*二维数组转一维数组,以便后续计算*/ - for (int i = 0; i < 100; i++) { - for (int j = 0; j < 100; j++) { - CNN_data[9999 - index++] = Matrix_data[i*100+j]; - } - } - DEBUG_PRINTF("开始第一层!\r\n"); - //1 第一层卷积 - /*数组资源申请*/ - float* Full_output1 = (float*)mymalloc(SRAMEX, sizeof(float) * 102 * 102); - /*填充矩阵*/ - Full(CNN_data, 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]); - } - /*做ReLU激活*/ - 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]); - } - /*数组ReLU激活*/ - 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 第三层卷积 - /*释放上一层的资源*/ - free2DArray(Full_output2,32); - 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]); - } - /*ReLU激活*/ - 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 第一连接层 - /*释放上一层的资源*/ - free2DArray(Full_output3,64); - 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}; - DEBUG_PRINTF("开始第四层!\r\n"); - 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[128*12*12]; - 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]); - /*单个数做ReLU激活*/ - yi[i] = ReLU2(sum); - myfree(SRAMEX, fc1_weight_new); - } - DEBUG_PRINTF("第四层完毕!\r\n"); - //5 最后连接层 - /*释放上一层的资源*/ - free2DArray(Pooling_result3,128); - /*连接层操作*/ - float zi[7] = {0}; -// float *zi = (float *)mymalloc(SRAMEX, 7 * sizeof(float)); -// memset(zi, 0, 7 * sizeof(float)); - for (int i = 0; i < 7; i++) { - //float fc2_weight_new[128]; - float* fc2_weight_new = (float*)mymalloc(SRAMEX, sizeof(float) * 128); - /*提取卷积核*/ - memcpy(fc2_weight_new,&fc2_weight.array[i*128],128 * sizeof(float)); - /*单个数做ReLU激活*/ - zi[i] = ConnectedLayer(yi, 128, fc2_weight_new, fc2_bias.array[i]); - myfree(SRAMEX, fc2_weight_new); - } - DEBUG_PRINTF("第五层完毕!\r\n"); - //end 输出处理层 - float result[7]; - int max_probability_idx = calculate_probabilities(zi,result,7); - PrintfResArray(zi,7,7); - PrintfResArray(result,7,7); - printf("%f, Label %d\t", result[max_probability_idx - 1] * 100, max_probability_idx); - myfree(SRAMEX, xi); - myfree(SRAMEX, yi); - myfree(SRAMEX, CNN_data); - myfree(SRAMEX, Full_output1); - } - else printf("No\r\n");/*如果没放电打印“No”*/ - printf("maxvalue is:%f\t",maxvalue); - printf("meanvalue is:%f\t",meanvalue); - printf("std_devvalue is:%f\r\n",std_devvalue); - myfree(SRAMEX, Matrix_data); - isrun = 0; -} - diff --git a/PORTING/CNN/cnn.h b/PORTING/CNN/cnn.h index d2aa3b9..255e0c9 100644 --- a/PORTING/CNN/cnn.h +++ b/PORTING/CNN/cnn.h @@ -1,34 +1,13 @@ #ifndef _CNN_H_ #define _CNN_H_ - -#include -#include -#include -#include #include "cnn_model.h" +#include "malloc.h" +#include +#include + +void cnn_run(void); +void _cnn_run(void); extern u8 isrun; -void PrintfArray(float *array, int array_num, int elements_per_line); -void **allocate2DArray(int depth, int num, size_t elementSize); -void free2DArray(float **array, int depth); -void Full(float *inputArray, int input_size, float *outputArray); -void Pooling(float *inputArray, int input_size, int kernel_size, unsigned int step, float *outputArray); -void Convolution(float *inputArray, int input_size, float *kernel, int kernel_size, float *outputArray); -void Combine(float **inputArray, int input_depth, int input_size, float *outputArray); -void Flatten2D(float **inputArray, int input_depth, int input_size, float *outputArray); -float ConnectedLayer(float *inputArray, int input_num, float *input_w, float input_b); -void ReLU1(float *inputArray, int num, float *outputArray); -float ReLU2(float data); -void AddBias(float *inputArray, int input_num, float bias, float *outputArray); - -int calculate_probabilities(float *input_array, float *output_array, int input_num); -void generateMatrix(float *get_data, float Max_value, int totalPoints, float CNN_data[100*100]); -void calculate_statistics(float arr[], int size, float *max_val, float *mean, float *std_dev); -int check_threshold(float arr[], int size, float *mean, float *std_dev); - -void _cnn_run(void); -void cnn_run(void); -void PrintfResArray(float *array, int array_num, int elements_per_line); - #endif diff --git a/PORTING/CNN/cnn_model.c b/PORTING/CNN/cnn_model.c index f3968e0..d749571 100644 --- a/PORTING/CNN/cnn_model.c +++ b/PORTING/CNN/cnn_model.c @@ -138,7 +138,7 @@ u8 modelmym_free(char* model_name){ modelmym_free("data"); return 2; } - return NULL; + return 0; } @@ -166,13 +166,14 @@ u8 model_write(char* model_name) u32 _larr = 0; u8 _len = strlen(model_name); char _path[_len+1+7+30]; + char _datapath[_len+1+7+30]; char _fstr[READLENGTH+1] = {0}; char _sstr[2]; int progress; Model *_model = model(model_name); if(_model == NULL || strcmp(model_name, "data") == 0){ - sprintf(_path, "0:/%s.txt", model_name); + sprintf(_path, "0:/dataset/_data/%s.txt", model_name); if(f_open(file, (const TCHAR *)_path, 1)){ DEBUG_PRINTF("\r\n输入了一个无效的模型或Data数据集的名字\r\n"); return 199; @@ -183,8 +184,8 @@ u8 model_write(char* model_name) } if(_model -> dname == NULL){ - sprintf(_path, "0:/%s.txt", _model -> name); - if(f_open(file, (TCHAR *)_path, 1)){ + sprintf(_path, "0:/dataset/%s.txt", _model -> name); + if(f_open(file, (const TCHAR *)_path, 1)){ DEBUG_PRINTF("预设里没有这个模型:[%s]\r\n", _path); return 4; } @@ -195,6 +196,13 @@ u8 model_write(char* model_name) return 200; } + if(_model -> dname)sprintf(_datapath, "_data/%s", _model -> dname); + sprintf(_path, "0:/dataset/%s.txt", _model -> dname ? _datapath : _model -> name); + if(f_open(file, (const TCHAR *)_path, 1)){ + DEBUG_PRINTF("文件[%s]无法打开\r\n", _model -> dname ? _model -> dname : _model -> name); + return 199; + } + DEBUG_PRINTF("写入的模型参数名字是:%s\r\n", _model -> name); if(_model -> dname)DEBUG_PRINTF("写入的Data数据集是:%s\r\n", _model -> dname); DEBUG_PRINTF("写入模型参数数组的最大长度为:%d\r\n", _model -> maxlength); @@ -239,9 +247,9 @@ u8 model_write(char* model_name) } } DEBUG_PRINTF("\r\n模型参数[%s]已写入到内存中! 模型长度为 %d\r\n",_model -> dname ? _model -> dname : _model -> name,_model -> realength); - return 1; + return 0; } - return NULL; + return 1; } @@ -269,7 +277,7 @@ u8 model_read(char* model_name, u32 start, u32 end, u32 gap){ return 1; } } - return NULL; + return 0; } @@ -278,17 +286,17 @@ u8 model_switchdata(char* data_name){ u8 _len = strlen(data_name); char _path[_len+1+7]; if(data.array != NULL)modelmym_free("data"); - sprintf(_path, "0:/%s.txt",data_name); + sprintf(_path, "0:/dataset/_data/%s.txt",data_name); if(f_open(file,(const TCHAR*)_path,1)){ DEBUG_PRINTF("\r\nData数据集[%s]不存在\r\n",data_name); - return NULL; + return 0; }else{ u8 _res = model_write(data_name); - if (_res == NULL) { + if (_res) { DEBUG_PRINTF("Data数据集[%s]切换失败!!\r\n",data_name); - return NULL; + return 0; } - else printf("Data数据集[%s]切换成功!\r\n",data_name); + else DEBUG_PRINTF("Data数据集[%s]切换成功!\r\n",data_name); DEBUG_PRINTF("data_name的长度为:%d\r\n_path的长度为:%d\r\n_path为:%s\r\n",_len,sizeof(_path),_path); return 1; } @@ -321,7 +329,7 @@ u8 model_info(char* model_name){ //if(strcmp(_model -> name, "data") == 0)printf("dataset is: %s\r\n",_model -> dname); 这函数有BUG,用model_dataset函数 return 1; } - return NULL; + return 0; } @@ -352,6 +360,8 @@ void model_init(){ conv1_weight.name = "conv1_weight"; conv1_weight.array = modelmym_init(conv1_weight.name); conv1_weight.maxlength = CONV1_WEIGHT_ARRSIZE; + conv1_weight.channel = 1; + conv1_weight.num_kernels = 32; conv2_bias.name = "conv2_bias"; conv2_bias.array = modelmym_init(conv2_bias.name); @@ -360,6 +370,8 @@ void model_init(){ conv2_weight.name = "conv2_weight"; conv2_weight.array = modelmym_init(conv2_weight.name); conv2_weight.maxlength = CONV2_WEIGHT_ARRSIZE; + conv2_weight.channel = 32; + conv2_weight.num_kernels = 64; conv3_bias.name = "conv3_bias"; conv3_bias.array = modelmym_init(conv3_bias.name); @@ -368,6 +380,8 @@ void model_init(){ conv3_weight.name = "conv3_weight"; conv3_weight.array = modelmym_init(conv3_weight.name); conv3_weight.maxlength = CONV3_WEIGHT_ARRSIZE; + conv3_weight.channel = 64; + conv3_weight.num_kernels = 128; fc1_bias.name = "fc1_bias"; fc1_bias.array = modelmym_init(fc1_bias.name); diff --git a/PORTING/CNN/cnn_model.h b/PORTING/CNN/cnn_model.h index 4daed87..3c7df91 100644 --- a/PORTING/CNN/cnn_model.h +++ b/PORTING/CNN/cnn_model.h @@ -19,22 +19,30 @@ typedef struct { float* array; u32 maxlength; u32 realength; + + u8 channel; + u8 num_kernels; + } Model; -#define READLENGTH 11*10 -#define CONV1_BIAS_ARRSIZE 32 -#define CONV1_WEIGHT_ARRSIZE 32*1*3*3 //288 -#define CONV2_BIAS_ARRSIZE 64 -#define CONV2_WEIGHT_ARRSIZE 64*32*3*3 //18432 -#define CONV3_BIAS_ARRSIZE 128 -#define CONV3_WEIGHT_ARRSIZE 128*64*3*3 //73728 -#define FC1_BIAS_ARRSIZE 128 -#define FC1_WEIGHT_ARRSIZE 128*18432 //2359296 -#define FC2_BIAS_ARRSIZE 7 -#define FC2_WEIGHT_ARRSIZE 7*128 //896 -#define DATA_ARRSIZE 1250000 //1250000 +#define READLENGTH (11*10) +#define CONV1_BIAS_ARRSIZE (32) +#define CONV1_WEIGHT_ARRSIZE (32*1*3*3) //288 +#define CONV2_BIAS_ARRSIZE (64) +#define CONV2_WEIGHT_ARRSIZE (64*32*3*3) //18432 +#define CONV3_BIAS_ARRSIZE (128) +#define CONV3_WEIGHT_ARRSIZE (128*64*3*3) //73728 +#define FC1_BIAS_ARRSIZE (128) +#define FC1_WEIGHT_ARRSIZE (128*18432) //2359296 +#define FC2_BIAS_ARRSIZE (7) +#define FC2_WEIGHT_ARRSIZE (7*128) //896 +#if 1 + #define DATA_ARRSIZE (1250000) +#else + #define DATA_ARRSIZE (100 * 100) +#endif @@ -75,116 +83,4 @@ u8 sd_read(u32 length, char* model_name,u32 gap); //fc1_weight[a*18432+b*1] a:0~127 b:0~18431 //fc2_bias[a*1] a:0~6 //fc2_weight[a*128+b*1] a:0~6 b:0~127 -/*-------------------------------- - -for(u8 a; a