完成池化功能

This commit is contained in:
Qiea
2024-11-10 17:25:51 +08:00
parent 266ad428f0
commit 643eca68a3

118
cnn.c
View File

@@ -14,49 +14,97 @@ float* expand(const float* old_matrix, u8 old_matrix_num){
return new_matrix;
}
//卷积核的个数32
//卷积的面积3*3
//输入图像
//输入图像的边长102
//num_kernels 卷积核的个数32
//area 卷积的面积3*3
//input_matrix 输入图像
//input_matrix_length 输入图像的边长102
//输出图像的边长100
//返回卷积的结果
float* convolution(u8 num_kernels, u8 area, const float* input_matrix, u8 input_matrix_length){
// 初始化卷积层参数
float conv_temp; // 临时变量,用于存储卷积计算的中间结果
float* conv_rlst = (float *) malloc(sizeof (float)*32*100*100);
memset(conv_rlst, 0, sizeof (float)*32*100*100);
float* conv_rlst = (float *) malloc(sizeof (float)*num_kernels*(input_matrix_length-2)*(input_matrix_length-2));
memset(conv_rlst, 0, sizeof (float)*num_kernels*(input_matrix_length-2)*(input_matrix_length-2));
// 遍历30个卷积核假设有30个通道
for(int n=0; n<32; n++)
for(u8 n=0; n<num_kernels; n++)
{
// 遍历输出图像的每一行卷积输出大小为24x24
for(int row=0; row<100; row++)
for(u8 row=0; row<(input_matrix_length-2); row++)
{
// 遍历输出图像的每一列
for(int col=0; col<100; col++)
for(u8 col=0; col<(input_matrix_length-2); col++)
{
conv_temp = 0; // 每个输出像素初始化为0
// 进行5x5的卷积操作
for(int x=0; x<3; x++)
for(u8 x=0; x<area; x++)
{
for(int y=0; y<3; y++)
for(u8 y=0; y<area; y++)
{
// 将输入图像的对应像素与卷积核权重相乘并累加到conv_temp
conv_temp += input_matrix[row*102+col+x*102+y] * conv1_weight.array[x*3+y+n*(3*3)];
conv_temp += input_matrix[row*102+col+x*102+y] * conv1_weight.array[x*area+y+n*(area*area)];
}
}
// 加上对应卷积核的偏置
conv_temp += conv1_bias.array[n];
// 激活函数ReLU将小于0的值设为0
if(conv_temp > 0)
conv_rlst[row*100+col+n*100*100] = conv_temp; // 如果卷积结果大于0存入结果数组
conv_rlst[row*(input_matrix_length-2)+col+n*(input_matrix_length-2)*(input_matrix_length-2)] = conv_temp; // 如果卷积结果大于0存入结果数组
else
conv_rlst[row*100+col+n*100*100] = 0; // 否则存入0
conv_rlst[row*(input_matrix_length-2)+col+n*(input_matrix_length-2)*(input_matrix_length-2)] = 0; // 否则存入0
}
}
}
return conv_rlst;
}
//num_kernels 卷积核的个数32
//area 池化的面积2*2
//input_matrix 输入图像
//input_matrix_length 输入图像的边长100
//输出图像的边长50
//返回池化的结果
float* pooling(u8 num_kernels, u8 area, const float* input_matrix, u8 input_matrix_length){
float pool_temp = 0; // 临时变量,用于存储池化操作的最大值
float* pool_rslt = (float *) malloc(sizeof (float)*num_kernels*input_matrix_length*input_matrix_length);
memset(pool_rslt, 0, sizeof (float)*num_kernels*input_matrix_length*input_matrix_length);
// 遍历30个通道与卷积核数量相同
for(u8 n=0; n<num_kernels; n++)
{
// 遍历输入图像的每一行步长为22x2的池化窗口
for(u8 row=0; row<input_matrix_length; row=row+2)
{
// 遍历输入图像的每一列步长为2
for(u8 col=0; col<input_matrix_length; col=col+2)
{
pool_temp = 0; // 每个池化区域的最大值初始化为0
// 进行2x2的最大池化操作
for(u8 x=0; x<area; x++)
{
for(u8 y=0; y<area; y++)
{
// 更新当前池化区域的最大值
if(pool_temp <= input_matrix[row*input_matrix_length+col+x*input_matrix_length+y+n*(input_matrix_length*input_matrix_length)])
pool_temp = input_matrix[row*input_matrix_length+col+x*input_matrix_length+y+n*(input_matrix_length*input_matrix_length)];
}
}
// 将最大值存入池化结果数组
pool_rslt[(row/2)*(input_matrix_length/2)+col/2+n*((input_matrix_length/2)*(input_matrix_length/2))] = pool_temp;
}
}
}
return pool_rslt;
}
int main(){
model_init();
model_write("all");
@@ -74,6 +122,17 @@ int main(){
printf("\n");
}
}
printf("\r\n\r\n");
float* pool_rslt = pooling(32,2,conv_rlst,100);
for (int i = 0; i < 1000; i++) {
printf("%f ", pool_rslt[i]);
if ((i + 1) % 102 == 0) {
printf("\n");
}
}
printf("\r\n\r\n");
@@ -87,37 +146,6 @@ int main(){
// float pool_temp = 0; // 临时变量,用于存储池化操作的最大值
// float pool_rslt[32*50*50] = {0};
// // 遍历30个通道与卷积核数量相同
// for(int n=0; n<32; n++)
// {
// // 遍历输入图像的每一行步长为22x2的池化窗口
// for(int row=0; row<100; row=row+2)
// {
// // 遍历输入图像的每一列步长为2
// for(int col=0; col<100; col=col+2)
// {
// pool_temp = 0; // 每个池化区域的最大值初始化为0
// // 进行2x2的最大池化操作
// for(int x=0; x<2; x++)
// {
// for(int y=0; y<2; y++)
// {
// // 更新当前池化区域的最大值
// if(pool_temp <= conv_rlst[row*100+col+x*100+y+n*(100*100)])
// pool_temp = conv_rlst[row*100+col+x*100+y+n*(100*100)];
// }
// }
// // 将最大值存入池化结果数组
// pool_rslt[(row/2)*50+col/2+n*(50*50)] = pool_temp;
// }
// }
// }
//