This commit is contained in:
Qiea
2024-11-11 00:45:13 +08:00
parent 63021d3c76
commit c948bd7c17

61
cnn.c
View File

@@ -3,12 +3,12 @@
// 将原始矩阵复制到填充后的矩阵中央 // 将原始矩阵复制到填充后的矩阵中央
float* expand(const float* old_matrix, u8 old_matrix_length, u8 layer){ 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)); 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)); memset(new_matrix, 0, sizeof(float)*layer*(old_matrix_length+2)*(old_matrix_length+2));
for(u8 l=0; l < layer; l++){ for(int l=0; l < layer; l++){
for (u8 i = 0; i < old_matrix_length; i++) { for (int i = 0; i < old_matrix_length; i++) {
for (u8 j = 0; j < old_matrix_length; j++) { for (int j = 0; j < old_matrix_length; j++) {
new_matrix[(i + 1) * (old_matrix_length+2) + (j + 1) + new_matrix[(i + 1) * (old_matrix_length+2) + (j + 1) +
l * (old_matrix_length+2) * (old_matrix_length+2)] l * (old_matrix_length+2) * (old_matrix_length+2)]
= old_matrix[i * old_matrix_length + j + = old_matrix[i * old_matrix_length + j +
@@ -24,28 +24,33 @@ float* expand(const float* old_matrix, u8 old_matrix_length, u8 layer){
//input_matrix_length 输入图像的边长102 //input_matrix_length 输入图像的边长102
//c_rl 输出图像的边长100 //c_rl 输出图像的边长100
//返回卷积的结果 //返回卷积的结果
float* convolution(Model model_w, Model model_b, const float* input_matrix, u8 input_matrix_length){ float* convolution(Model model_w, Model model_b, const float* input_matrix, int input_matrix_length){
// 初始化卷积层参数 // 初始化卷积层参数
u8 im_l = input_matrix_length; int _debug=0;
u8 cr_l = input_matrix_length - 2; int im_l = input_matrix_length;
int cr_l = input_matrix_length - 2;
float conv_temp; // 临时变量,用于存储卷积计算的中间结果 float conv_temp; // 临时变量,用于存储卷积计算的中间结果
float* conv_rlst = (float *) malloc(sizeof (float) * 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)); memset(conv_rlst, 0, sizeof (float) * model_w.num_kernels * (cr_l * cr_l));
// 遍历30个卷积核假设有30个通道 // 遍历30个卷积核假设有30个通道
for(u8 l=0;l<model_w.layer;l++){ for(int l=0;l<model_w.layer;l++){
for(u8 n=0; n<model_w.num_kernels; n++){ for(int n=0; n<model_w.num_kernels; n++){
for(u8 row = 0; row < cr_l; row++) { for(int row = 0; row < cr_l; row++) {
for (u8 col = 0; col < cr_l; col++) { for (int col = 0; col < cr_l; col++) {
conv_temp = 0; // 每个输出像素初始化为0 conv_temp = 0; // 每个输出像素初始化为0
// 进行3x3的卷积操作 // 进行3x3的卷积操作
for (u8 x = 0; x < 3; x++) { for (int x = 0; x < 3; x++) {
for (u8 y = 0; y < 3; y++) { for (int y = 0; y < 3; y++) {
// 将输入图像的对应像素与卷积核权重相乘并累加到conv_temp // 将输入图像的对应像素与卷积核权重相乘并累加到conv_temp
conv_temp += input_matrix[(l*(im_l*im_l)) + (row*im_l) + (col) + (x*im_l) + (y)] * conv_temp += input_matrix[(l*(im_l*im_l)) + (row*im_l+col) + (x*im_l+y)] *
model_w.array[(x*3) + y + (n*(3*3))]; model_w.array[(l+n*(model_w.layer))*(3*3) + (x*3) + y];
} }
} }
if(_debug < 10 && strcmp(model_w.name, "conv2_weight") == 0){
printf("[%d]%f\r\n",_debug,conv_temp);
}
_debug++;
// 加上对应卷积核的偏置 // 加上对应卷积核的偏置
conv_temp += model_b.array[n]; conv_temp += model_b.array[n];
// 激活函数ReLU将小于0的值设为0 // 激活函数ReLU将小于0的值设为0
@@ -127,15 +132,15 @@ int main(){
float* expand_matrix_1 = expand(data.array, 100, 1); float* expand_matrix_1 = expand(data.array, 100, 1);
// print_rslt(expand_matrix_1, 102, (1*102*102)); // print_rslt(expand_matrix_1, 102, (1*102*102));
float* conv_rlst_1 = convolution(conv1_weight,conv1_bias,expand_matrix_1, 102); float* conv_rlst_1 = convolution(conv1_weight,conv1_bias,expand_matrix_1, 102);
// print_rslt(conv_rlst_1, 100, (32*100*100)); // print_rslt(conv_rlst_1, 100*0.01, (0.01*10*100));
float* pool_rslt_1 = pooling(conv1_weight, conv_rlst_1, 100); float* pool_rslt_1 = pooling(conv1_weight, conv_rlst_1, 100);
// print_rslt(pool_rslt_1, 50, (32*50*50)); // print_rslt(pool_rslt_1, 50, (1*50*50));
//第二层填充32 * 52 * 52 //第二层填充32 * 52 * 52
float* expand_matrix_2 = expand(pool_rslt_1, 50, 32); float* expand_matrix_2 = expand(pool_rslt_1, 50, 32);
// print_rslt(expand_matrix_2, 52, (1*52*52)); // print_rslt(expand_matrix_2, 52, (1*52*52));
float* conv_rlst_2 = convolution(conv2_weight,conv2_bias,expand_matrix_2, 52); float* conv_rlst_2 = convolution(conv2_weight,conv2_bias,expand_matrix_2, 52);
// print_rslt(conv_rlst_2, 50, (1*50*50)); // print_rslt(conv_rlst_2, 50*0.02, (0.02*10*50));
float* pool_rslt_2 = pooling(conv2_weight, conv_rlst_2, 50); float* pool_rslt_2 = pooling(conv2_weight, conv_rlst_2, 50);
// print_rslt(pool_rslt_2, 25, (1*25*25)); // print_rslt(pool_rslt_2, 25, (1*25*25));
@@ -143,9 +148,9 @@ int main(){
float* expand_matrix_3 = expand(pool_rslt_2, 25, 64); float* expand_matrix_3 = expand(pool_rslt_2, 25, 64);
// print_rslt(expand_matrix_2, 52, (1*52*52)); // print_rslt(expand_matrix_2, 52, (1*52*52));
float* conv_rlst_3 = convolution(conv3_weight,conv3_bias,expand_matrix_3, 27); float* conv_rlst_3 = convolution(conv3_weight,conv3_bias,expand_matrix_3, 27);
print_rslt(conv_rlst_3, 25, (1*25*25)); // print_rslt(conv_rlst_3, 25, (1*25*25));
float* pool_rslt_3 = pooling(conv3_weight, conv_rlst_3, 25); float* pool_rslt_3 = pooling(conv3_weight, conv_rlst_3, 25);
print_rslt(pool_rslt_3, 12, (1*12*12)); // print_rslt(pool_rslt_3, 12, (1*12*12));
@@ -167,7 +172,7 @@ int main(){
float affine1_temp; // 临时变量,用于存储全连接层的中间结果 float affine1_temp; // 临时变量,用于存储全连接层的中间结果
// 遍历128个神经元假设隐藏层有128个神经元 // 遍历128个神经元假设隐藏层有128个神经元
for(int n=0; n<128; n++) for(u8 n=0; n<128; n++)
{ {
affine1_temp = 0; // 每个神经元的输出初始化为0 affine1_temp = 0; // 每个神经元的输出初始化为0
@@ -187,24 +192,25 @@ int main(){
affine1_rslt[n] = 0; // 否则存入0 affine1_rslt[n] = 0; // 否则存入0
} }
print_rslt(affine1_rslt,1,128); // print_rslt(affine1_rslt,1,128);
float affine2_temp; // 临时变量,用于存储输出层的中间结果 float affine2_temp; // 临时变量,用于存储输出层的中间结果
float affine2_rslt[7]; // 存储输出层的结果假设输出层有7个神经元 float* affine2_rslt = (float *) malloc(sizeof(float)*7);
memset(affine2_rslt, 0, 7);
// 比较输出层的最大值 // 比较输出层的最大值
float temp = -100; // 用于存储最大值的临时变量,初始化为一个非常小的值 float temp = -100; // 用于存储最大值的临时变量,初始化为一个非常小的值
int predict_num; // 用于存储预测的数字(对应最大值的索引) u8 predict_num; // 用于存储预测的数字(对应最大值的索引)
// 遍历7个输出神经元假设有7个类别 // 遍历7个输出神经元假设有7个类别
for(int n=0; n<7; n++) for(u8 n=0; n<7; n++)
{ {
affine2_temp = 0; // 当前神经元的输出初始化为0 affine2_temp = 0; // 当前神经元的输出初始化为0
// 进行矩阵乘法,将隐藏层的输出与输出层权重进行点积 // 进行矩阵乘法,将隐藏层的输出与输出层权重进行点积
for(int i=0; i<128; i++) for(u8 i=0; i<128; i++)
{ {
affine2_temp = affine2_temp + fc2_weight.array[i+100*n] * affine1_rslt[i]; affine2_temp = affine2_temp + fc2_weight.array[i+100*n] * affine1_rslt[i];
} }
@@ -221,8 +227,7 @@ int main(){
} }
} }
print_rslt(affine2_rslt,1,7); print_rslt(affine2_rslt,7,7);
printf("RES is:%d",predict_num+1); printf("RES is:%d",predict_num+1);
return 0; return 0;