完成卷积功能
This commit is contained in:
193
cnn.c
193
cnn.c
@@ -0,0 +1,193 @@
|
||||
#include "cnn.h"
|
||||
|
||||
|
||||
|
||||
// 将原始矩阵复制到填充后的矩阵中央
|
||||
float* expand(const float* old_matrix, u8 old_matrix_num){
|
||||
float* new_matrix = (float *)malloc(sizeof(float)*(old_matrix_num+2)*(old_matrix_num+2));
|
||||
memset(new_matrix, 0, sizeof(float)*(old_matrix_num+2)*(old_matrix_num+2));
|
||||
for (u8 i = 0; i < old_matrix_num; i++) {
|
||||
for (u8 j = 0; j < old_matrix_num; j++) {
|
||||
new_matrix[(i + 1) * (old_matrix_num+2) + (j + 1)] = old_matrix[i * old_matrix_num + j];
|
||||
}
|
||||
}
|
||||
return new_matrix;
|
||||
}
|
||||
|
||||
//卷积核的个数:32
|
||||
//卷积的面积:3*3
|
||||
//输入图像
|
||||
//输入图像的边长: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);
|
||||
// 遍历30个卷积核(假设有30个通道)
|
||||
for(int n=0; n<32; n++)
|
||||
{
|
||||
// 遍历输出图像的每一行(卷积输出大小为24x24)
|
||||
for(int row=0; row<100; row++)
|
||||
{
|
||||
// 遍历输出图像的每一列
|
||||
for(int col=0; col<100; col++)
|
||||
{
|
||||
conv_temp = 0; // 每个输出像素初始化为0
|
||||
// 进行5x5的卷积操作
|
||||
for(int x=0; x<3; x++)
|
||||
{
|
||||
for(int y=0; y<3; y++)
|
||||
{
|
||||
// 将输入图像的对应像素与卷积核权重相乘,并累加到conv_temp
|
||||
conv_temp += input_matrix[row*102+col+x*102+y] * conv1_weight.array[x*3+y+n*(3*3)];
|
||||
}
|
||||
}
|
||||
// 加上对应卷积核的偏置
|
||||
conv_temp += conv1_bias.array[n];
|
||||
// 激活函数:ReLU(将小于0的值设为0)
|
||||
if(conv_temp > 0)
|
||||
conv_rlst[row*100+col+n*100*100] = conv_temp; // 如果卷积结果大于0,存入结果数组
|
||||
else
|
||||
conv_rlst[row*100+col+n*100*100] = 0; // 否则存入0
|
||||
}
|
||||
}
|
||||
}
|
||||
return conv_rlst;
|
||||
}
|
||||
|
||||
int main(){
|
||||
model_init();
|
||||
model_write("all");
|
||||
model_switchdata("data");
|
||||
|
||||
//填充102 * 102
|
||||
float* expand1_matrix = expand(data.array, 100);
|
||||
|
||||
float* conv_rlst = convolution(32,3,expand1_matrix,102);
|
||||
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
printf("%f ", conv_rlst[i]);
|
||||
if ((i + 1) % 102 == 0) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 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;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//// 隐藏层参数地址
|
||||
// float *affine1_w; // 指向第一个全连接层权重的内存地址的指针
|
||||
// float *affine1_b; // 指向第一个全连接层偏置的内存地址的指针
|
||||
// affine1_param_init(); // 初始化全连接层参数
|
||||
// float *affine1_rslt; // 指向存储隐藏层计算结果的内存地址的指针
|
||||
// float affine1_temp; // 临时变量,用于存储全连接层的中间结果
|
||||
//
|
||||
//// 遍历100个神经元(假设隐藏层有100个神经元)
|
||||
// for(int n=0; n<100; n++)
|
||||
// {
|
||||
// affine1_temp = 0; // 每个神经元的输出初始化为0
|
||||
//
|
||||
// // 进行矩阵乘法,将池化层输出展平为一维向量后,与全连接层权重进行点积
|
||||
// for(int i=0; i<4320; i++)
|
||||
// {
|
||||
// affine1_temp = affine1_temp + pool_rslt[i] * affine1_w[i+4320*n];
|
||||
// }
|
||||
//
|
||||
// // 加上对应神经元的偏置
|
||||
// affine1_temp = affine1_temp + affine1_b[n];
|
||||
//
|
||||
// // 激活函数:ReLU(将小于0的值设为0)
|
||||
// if(affine1_temp > 0)
|
||||
// affine1_rslt[n] = affine1_temp; // 如果结果大于0,存入结果数组
|
||||
// else
|
||||
// affine1_rslt[n] = 0; // 否则存入0
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// float *affine2_w; // 指向第二个全连接层(输出层)权重的内存地址的指针
|
||||
// float *affine2_b; // 指向第二个全连接层(输出层)偏置的内存地址的指针
|
||||
// float affine2_temp; // 临时变量,用于存储输出层的中间结果
|
||||
// affine2_param_init(); // 初始化输出层参数
|
||||
//
|
||||
// float affine2_rslt[10]; // 存储输出层的结果(假设输出层有10个神经元)
|
||||
//
|
||||
//// 比较输出层的最大值
|
||||
// float temp = -100; // 用于存储最大值的临时变量,初始化为一个非常小的值
|
||||
// int predict_num; // 用于存储预测的数字(对应最大值的索引)
|
||||
//
|
||||
//// 遍历10个输出神经元(假设有10个类别)
|
||||
// for(int n=0; n<10; n++)
|
||||
// {
|
||||
// affine2_temp = 0; // 当前神经元的输出初始化为0
|
||||
//
|
||||
// // 进行矩阵乘法,将隐藏层的输出与输出层权重进行点积
|
||||
// for(int i=0; i<100; i++)
|
||||
// {
|
||||
// affine2_temp = affine2_temp + affine2_w[i+100*n] * affine1_rslt[i];
|
||||
// }
|
||||
//
|
||||
// // 加上对应神经元的偏置
|
||||
// affine2_temp = affine2_temp + affine2_b[n];
|
||||
// affine2_rslt[n] = affine2_temp; // 存储输出层的结果
|
||||
//
|
||||
// // 寻找最大值
|
||||
// if(temp <= affine2_rslt[n])
|
||||
// {
|
||||
// temp = affine2_rslt[n]; // 更新最大值
|
||||
// predict_num = n; // 记录最大值对应的类别索引
|
||||
// }
|
||||
// }
|
||||
return 0;
|
||||
}
|
||||
|
||||
3
cnn.h
3
cnn.h
@@ -1,6 +1,7 @@
|
||||
#ifndef _CNN_H_
|
||||
#define _CNN_H_
|
||||
|
||||
#include "cnn_model.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ typedef struct {
|
||||
#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 DATA_ARRSIZE (100*100) //1250000
|
||||
|
||||
|
||||
|
||||
|
||||
36
main.c
36
main.c
@@ -1,20 +1,20 @@
|
||||
////
|
||||
//// Created by Qi on 2024/11/9.
|
||||
////
|
||||
//
|
||||
// Created by Qi on 2024/11/9.
|
||||
//#include "cnn_model.h"
|
||||
//
|
||||
|
||||
#include "cnn_model.h"
|
||||
|
||||
void main(){
|
||||
u8 res;
|
||||
model_init();
|
||||
model_write("all");
|
||||
model_switchdata("C1autosave00095_right_new_2");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
model_info("all");
|
||||
DEBUG_PRINTF("\r\nEnd结束");
|
||||
}
|
||||
//void main(){
|
||||
// u8 res;
|
||||
// model_init();
|
||||
// model_write("all");
|
||||
// model_switchdata("C1autosave00095_right_new_2");
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// model_info("all");
|
||||
// DEBUG_PRINTF("\r\nEnd结束");
|
||||
//}
|
||||
Reference in New Issue
Block a user