完成池化功能
This commit is contained in:
118
cnn.c
118
cnn.c
@@ -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++)
|
||||
{
|
||||
// 遍历输入图像的每一行,步长为2(2x2的池化窗口)
|
||||
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++)
|
||||
// {
|
||||
// // 遍历输入图像的每一行,步长为2(2x2的池化窗口)
|
||||
// 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;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user