1.前言
深度学习框架给我们带来了很多方便,但是过于依赖框架反而会让我们不知所以然。本篇博客中,我使用C和C++语言实现了一个神经网络。由于时间关系,仅实现BP神经网络(BP是一种反向传播更新梯度算法,但一开始用于MLP,习惯称MLP为BP神经网络),对于卷积神经网络,由于时间问题以后再编写。Github网址:GitHub - xuzhifanGithub/Neural-Network: C/C++编写神经网络
2.原理
2.1前向传播

对于输入x1,x2,x3,权重w1,w2,w3,偏置b有output = =x1*w1+x2*w2+x3*w3+b
对于n个输入x1,x2,...,xn,权重w1,w2,...,wn,偏置b有output =
2.2反向传播
先以下图简单的例子来推。损失Loss采用SGD来计算,及下图中式子。代表第i层第j个输入。
这里只推了第0层w11,其他的朋友感觉不太明白的可以动手推推。对于偏置b理解的w应该很容易看出,只需把最后一个偏导替换成对b的,这部分结果为1.
接下来上难度,
3.代码实现
3.1定义实现tensor2D相关函数
struct Tensor2D {
int h;//高(行)
int w;//宽(列)
float** data;
};
std::mt19937& get_generator();//伪随机数生成器
Tensor2D Tensor2D_init(int h, int w);//初始化tensor,值默认正态分布均值0,方差1
Tensor2D Tensor2D_init(int h, int w, float value);//初始化tensor,值均为自定义value
void Tensor2D_display(Tensor2D tensor,bool printValue = true);//打印tensor大小和打印值(默认)
Tensor2D Tensor2D_copy(Tensor2D tensor);//复制
void Tensor2D_copy(Tensor2D des,Tensor2D src);//复制
void Tensor2D_setZero(Tensor2D tensor);//tensor值置0
void Tensor2D_freeTensor(Tensor2D tensor);//释放tensor内存
//伪随机数生成器
std::mt19937& get_generator() {
thread_local std::mt19937 gen(std::random_device{}());
return gen;
}
//tensor值置0
void Tensor2D_setZero(Tensor2D tensor) {
int m = tensor.h;
int n = tensor.w;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
tensor.data[i][j] = 0.0;
}
}
}
//初始化
Tensor2D Tensor2D_init(int h, int w) {
Tensor2D tensor;
tensor.h = h;
tensor.w = w;
tensor.data = (float**)malloc(sizeof(float*) * h);
std::mt19937& gen = get_generator();
// 生成标准正态分布的随机数,mean为均值,stddev为标准差
std::normal_distribution<> d(0.0, 1.0); // 标准正态分布,均值为0,标准差为1
for (int i = 0; i < h; ++i) {
tensor.data[i] = (float*)malloc(sizeof(float) * w);
}
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
tensor.data[i][j] = d(gen);
}
}
return tensor;
}
//初始化
Tensor2D Tensor2D_init(int h, int w, float value) {
Tensor2D tensor;
tensor.h = h;
tensor.w = w;
tensor.data = (float**)malloc(sizeof(float*) * h);
for (int i = 0; i < h; ++i) {
tensor.data[i] = (float*)malloc(sizeof(float) * w);
}
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
tensor.data[i][j] = value;
}
}
return tensor;
}
//显示tensor信息
void Tensor2D_display(Tensor2D tensor, bool printValue) {
int m = tensor.h;
int n = tensor.w;
printf("\nTensor size:[%d,%d]\n", m, n);
if (printValue) {
printf("[");
for (int i = 0; i < m; ++i) {
printf("[");
for (int j = 0; j < n; ++j) {
printf("%f", tensor.data[i][j]);
if (j != n - 1)printf(",");
}
if(i!=m-1)printf("]\n");
}
printf("]\n");
}
}
//复制tensor
Tensor2D Tensor2D_copy(Tensor2D tensor) {
Tensor2D temp = Tensor2D_init(tensor.h, tensor.w);
for (int i = 0; i < tensor.h; ++i) {
for (int j = 0; j < tensor.w; ++j) {
temp.data[i][j] = tensor.data[i][j];
}
}
return temp;
}