#include "cnn.h" // 将原始矩阵复制到填充后的矩阵中央 float* expand(const float* old_matrix, int old_matrix_length, int layer){ float* new_matrix = (float *)malloc(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 _debug=0; int im_l = input_matrix_length; int cr_l = input_matrix_length - 2; float conv_temp; // 临时变量,用于存储卷积计算的中间结果 //用于合并前的数组,具有32*64*50*50(第二层)的大小 float* _conv_rlst = (float *) malloc(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 *) malloc(sizeof (float) * model_w.num_kernels * (cr_l * cr_l)); memset(conv_rlst, 0, sizeof (float) * model_w.num_kernels * (cr_l * cr_l)); // 遍历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 } } } } return conv_rlst; } //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 *) malloc(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 0) affine1_rslt[n] = affine1_temp; // 如果结果大于0,存入结果数组 else affine1_rslt[n] = 0; // 否则存入0 } // print_rslt(affine1_rslt,1,128); float affine2_temp; // 临时变量,用于存储输出层的中间结果 float affine2_rslt[7]; // 存储输出层的结果(假设输出层有7个神经元) // 比较输出层的最大值 float temp = -100; // 用于存储最大值的临时变量,初始化为一个非常小的值 int predict_num; // 用于存储预测的数字(对应最大值的索引) // 遍历10个输出神经元(假设有10个类别) for(int n=0; n<7; n++) { affine2_temp = 0; // 当前神经元的输出初始化为0 // 进行矩阵乘法,将隐藏层的输出与输出层权重进行点积 for(int i=0; i<128; i++) { affine2_temp = affine2_temp + fc2_weight.array[i+128*n] * affine1_rslt[i]; } // 加上对应神经元的偏置 affine2_temp = affine2_temp + fc2_weight.array[n]; affine2_rslt[n] = affine2_temp; // 存储输出层的结果 // 寻找最大值 if(temp <= affine2_rslt[n]) { temp = affine2_rslt[n]; // 更新最大值 predict_num = n; // 记录最大值对应的类别索引 } } print_rslt(affine2_rslt,7,7); printf("Label is:%d\r\n",predict_num+1); } }