/*使用C语言实现全连接神经网络,实现一个异或的训练,算法部分都写了注释。*/
全连接神经网络 File: network.h
#ifndef _NETWORK_H_INCLUDED_
#define _NETWORK_H_INCLUDED_
/*
激活函数 和 对应的导数,
也就是向前传播和向后传播所用的函数,
写成如下形式是因为方便为每一层使用不同的激活函数
*/
typedef struct {
float (*forward)(float);
float (*backward)(float);
} st_activator;
/*
这个结构体表示连接层,按顺序下面的字段表示:
input_size 该层输入的节点数
output_size 该层输出的节点数
activator 该层的激活函数和导数函数
weight 该层的权重,size:output_size * input_size
bias 该层的偏置项,size:output_size
input 输入值,size:input_size
output 输出值,size:output_size
delta 上一层传递来的损失值经过激活函数的导数运算后的中间值
这个值非常重要,它乘以输入值得到该层的梯度。size:output_size
down_delta 这个是准备传输给上一层的损失值,这里的down是针对上一层来讲的
本层用不到,完全是为了传递给上一层使用的。size:input_size
w_grad 梯度通过delta * input 得到,用来更新权重
b_grad 梯度通过delta * 1 得到,就等于delta,用于更新偏置项
weight_T 用于权重的转置运算后的临时存放,反向传播中计算down_delta用
*/
typedef struct {
int input_size;
int output_size;
st_activator activator;
float *weight;
float *bias;
float *input;
float *output;
float *delta;
float *down_delta;
float *w_grad;
float *b_grad;
float *weight_T;
} st_connected_layer;
/*这个结构体表示整个神经网络
也是对外的结构体,N个连接层组合在一起组成一个神经网络
故而:
cl_num 表示神经网络的层数
cl 指向神经网络每一层地址的指针
delta 表示整个神经网络目标函数的损失值
input_size 表示整个神经网络的输入节点数,也就是第一层的input_size
output_size 表示整个神经网络的输出节点数,也就是最后一层的output_size
*/
typedef struct {
int cl_num;
st_connected_layer **cl;
float *delta;
int input_size;
int output_size;
} st_fc_network;
/*初始化网络*/
st_fc_network *init_network(int *layer, int layer_num, st_activator *fun);
/*神经网络的正向运算*/
float *predict(st_fc_network *fcn, float *input);
/*神经网络的训练*/
void train(st_fc_network *fcn, float *data_set, float *labels, int n, float rate, int epoch);
/*回收分配的所有资源*/
void free_network(st_fc_network *fcn);
/*打印神经网络的部分信息,用于调试*/
void dump_network(st_fc_network *fcn);
#endif
全连接神经网络 File: network.c
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "network.h"
#include <time.h>
/*
这些内部函数顾名思义
*/
static void forward(st_connected_layer *cl, float *input_array);
static void backward(st_connected_layer *cl, float *delta_array);
static void update_w(st_connected_layer *cl, float learning_rate);
static void init_weight(st_connected_layer *cl);
static st_connected_layer *init_layer(int input_size, int output_size, st_activator *activator);
static void free_layer(st_con