diff --git a/main.c b/main.c deleted file mode 100644 index 677c6b9..0000000 --- a/main.c +++ /dev/null @@ -1,379 +0,0 @@ -#include -#include -#include -#include - - -#define INNODE 2 // 输入层神经元个数 -#define HIDENODE 10 // 隐藏层神经元个数 -#define OUTNODE 1 // 输出层神经元个数 - - -/** - * 步长(学习率) - */ -double StudyRate = 1.6; - -/** - * 允许最大误差 - */ -double threshold = 1e-4; - -/** - * 最大迭代次数 - */ -int mostTimes = 1e6; - -/** - * 训练集大小 - */ -int trainSize = 0; - -/** - * 测试集大小 - */ -int testSize = 0; - -/** - * 样本 - */ -typedef struct Sample{ - double out[30][OUTNODE]; // 输出 - double in[30][INNODE]; // 输入 -}Sample; - - -/** - * 神经元结点 - */ -typedef struct Node{ - double value; // 当前神经元结点输出的值 - double bias; // 当前神经元结点偏偏置值 - double bias_delta; // 当前神经元结点偏置值的修正值 - double *weight; // 当前神经元结点向下一层结点传播的权值 - double *weight_delta; // 当前神经元结点向下一层结点传播的权值的修正值 -}Node; - -/** - * 输入层 - */ -Node inputLayer[INNODE]; -/** - * 隐藏层 - */ -Node hideLayer[HIDENODE]; -/** - * 输出层 - */ -Node outLayer[OUTNODE]; - - - -double Max(double a, double b){ - return a > b ? a : b; -} - -double sigmoid(double x){ - return 1/(1+pow(2.71828,-x)); - //请补全sigmod函数的计算结果 - -} - - -/** - * 读取训练集 - * @param filename 文件名 - * @return 训练集 - */ -Sample * getTrainData(const char * filename){ - Sample * result = (Sample*)malloc(sizeof (Sample)); - FILE * file = fopen(filename, "r"); - if(file != NULL){ - int count = 0; - while (fscanf(file, "%lf %lf %lf", &result->in[count][0], &result->in[count][1], &result->out[count][0]) != EOF){ - ++count; - } - trainSize = count; - printf("%s The file has been successfully read!\n", filename); - fclose(file); - return result; - } else{ - fclose(file); - printf("%s Encountered an error while opening the file!\n\a", filename); - return NULL; - } -} - - -void printData(Sample * data, int size){ - int i; - if(data==NULL) - { - printf("Sample is empty!"); - return; - } - else - { - for(i=0;iin[i][0],data->in[i][1],data->out[i][0]); - } - } - /*请补全代码 - - - */ - - -} - -/** - * 初始化函数 - */ -void init(){ - // 设置时间戳为生成随机序列的种子 - srand(time(NULL)); - - // 输入层的初始化 - for (int i = 0; i < INNODE; ++i) { - inputLayer[i].weight = (double *)malloc(sizeof (double ) * HIDENODE); - inputLayer[i].weight_delta = (double *) malloc(sizeof (double ) * HIDENODE); - inputLayer[i].bias = 0.0; - inputLayer[i].bias_delta = 0.0; - } - - // 输出层权值初始化 - for (int i = 0; i < INNODE; ++i) { - for (int j = 0; j < HIDENODE; ++j) { - inputLayer[i].weight[j] = rand() % 10000 / (double )10000 * 2 - 1.0; - inputLayer[i].weight_delta[j] = 0.0; - } - } - - - // 初始化隐藏层结点 - for (int i = 0; i < HIDENODE; ++i) { - /*为隐藏层节点 i 分配了一个 double 类型的数组,用于存储该节点向下一层节点传播的权重。 - 使用malloc 函数在堆内存中分配足够的空间,以存储 OUTNODE 个 double 类型的权重值。 - */ - hideLayer[i].weight = - /*为隐藏层节点 i 分配了一个用于存储权重修正值的数组。这个数组将在神经网络的训练过程中用于存储权重的更新值。 - 使用malloc 函数在堆内存中分配足够的空间,以存储 OUTNODE 个 double 类型的权重值。 - */ - hideLayer[i].weight_delta = - /*为隐藏层节点 i 初始化了一个随机的偏置值。 - 这个值通常是一个在 -1.0 到 1.0 之间的随机数,用于调整该节点的激活函数的阈值。 - */ - hideLayer[i].bias = - /*初始化了隐藏层节点 i 的偏置值修正值,初始值为0.0。*/ - hideLayer[i].bias_delta = 0.0; - } - - // 初始化隐藏层权值 - for (int i = 0; i < HIDENODE; ++i) { - for (int j = 0; j < OUTNODE; ++j) { - hideLayer[i].weight[j] = rand() % 10000 / (double )10000 * 2 - 1.0; - hideLayer[i].weight_delta[j] = 0.0; - } - } - - for (int i = 0; i < OUTNODE; ++i) { - outLayer[i].bias = rand() % 10000 / (double )10000 * 2 - 1.0; - outLayer[i].bias_delta = 0.0; - } -} - -/** - * 重置修正值 - */ -void resetDelta(){ - for (int i = 0; i < INNODE; ++i) { - for (int j = 0; j < HIDENODE; ++j) { - inputLayer[i].weight_delta[j] = 0.0; - } - } - - for (int i = 0; i < HIDENODE; ++i) { - hideLayer[i].bias_delta = 0.0; - for (int j = 0; j < OUTNODE; ++j) { - hideLayer[i].weight_delta[j] = 0.0; - } - } - - for (int i = 0; i < OUTNODE; ++i) { - outLayer[i].bias_delta = 0.0; - } -} - - -int main() { - // 初始化 - init(); - // 获取训练集 - Sample * trainSample = getTrainData("TrainData.txt"); -// printData(trainSample, trainSize); - - - for (int trainTime = 0; trainTime < mostTimes; ++trainTime) { - // 重置梯度信息 - resetDelta(); - - // 当前训练最大误差 - double error_max = 0.0; - - // 开始训练(累计bp) - for (int currentTrainSample_Pos = 0; currentTrainSample_Pos < trainSize; ++currentTrainSample_Pos) { - - // 输入自变量 - for (int inputLayer_Pos = 0; inputLayer_Pos < INNODE; ++inputLayer_Pos) { - inputLayer[inputLayer_Pos].value = trainSample->in[currentTrainSample_Pos][inputLayer_Pos]; - } - - /** ----- 开始正向传播 ----- */ - for (int hideLayer_Pos = 0; hideLayer_Pos < HIDENODE; ++hideLayer_Pos) { - double sum = 0.0; - for (int inputLayer_Pos = 0; inputLayer_Pos < INNODE; ++inputLayer_Pos) { - sum += inputLayer[inputLayer_Pos].value * inputLayer[inputLayer_Pos].weight[hideLayer_Pos]; - } - - sum -= hideLayer[hideLayer_Pos].bias; - hideLayer[hideLayer_Pos].value = sigmoid(sum); - } - - for (int outLayer_Pos = 0; outLayer_Pos < OUTNODE ; ++outLayer_Pos) { - double sum = 0.0; - for (int hideLayer_Pos = 0; hideLayer_Pos < HIDENODE; ++hideLayer_Pos) { - /*计算每一个隐藏层节点的value和权值的乘积,相加得到sum - - */ - } - /*更新sum,使sum减去偏置值; - - */ - /*利用sigmod函数对得到的sum进行激活,把激活后的结果赋值给对应的输出层节点value(outLayer[outLayer_Pos].value)。 - - */ - } - - - /** ----- 计算误差 ----- */ - double error = 0.0; - for (int outLayer_Pos = 0; outLayer_Pos < OUTNODE; ++outLayer_Pos) { - double temp = fabs(outLayer[outLayer_Pos].value - trainSample->out[currentTrainSample_Pos][outLayer_Pos]); - // 损失函数 - error += temp * temp / 2.0; - } - - error_max = Max(error_max, error); - - - /** ----- 反向传播 ----- */ - for (int outLayer_Pos = 0; outLayer_Pos < OUTNODE; ++outLayer_Pos) { - double bias_delta = -(trainSample->out[currentTrainSample_Pos][outLayer_Pos] - outLayer[outLayer_Pos].value) - * outLayer[outLayer_Pos].value * (1.0 - outLayer[outLayer_Pos].value); - outLayer[outLayer_Pos].bias_delta += bias_delta; - } - - for (int hideLayer_Pos = 0; hideLayer_Pos < HIDENODE; ++hideLayer_Pos) { - for (int outLayer_Pos = 0; outLayer_Pos < OUTNODE; ++outLayer_Pos) { - double weight_delta = (trainSample->out[currentTrainSample_Pos][outLayer_Pos] - outLayer[outLayer_Pos].value) - * outLayer[outLayer_Pos].value * (1.0 - outLayer[outLayer_Pos].value) - * hideLayer[hideLayer_Pos].value; - hideLayer[hideLayer_Pos].weight_delta[outLayer_Pos] += weight_delta; - } - } - - // - for (int hideLayer_Pos = 0; hideLayer_Pos < HIDENODE; ++hideLayer_Pos) { - double sum = 0.0; - for (int outLayer_Pos = 0; outLayer_Pos < OUTNODE; ++outLayer_Pos) { - sum += -(trainSample->out[currentTrainSample_Pos][outLayer_Pos] - outLayer[outLayer_Pos].value) - * outLayer[outLayer_Pos].value * (1.0 - outLayer[outLayer_Pos].value) - * hideLayer[hideLayer_Pos].weight[outLayer_Pos]; - } - hideLayer[hideLayer_Pos].bias_delta += sum * hideLayer[hideLayer_Pos].value * (1.0 - hideLayer[hideLayer_Pos].value); - } - - - for (int inputLayer_Pos = 0; inputLayer_Pos < INNODE; ++inputLayer_Pos) { - for (int hideLayer_Pos = 0; hideLayer_Pos < HIDENODE; ++hideLayer_Pos) { - double sum = 0.0; - for (int outLayer_Pos = 0; outLayer_Pos < OUTNODE; ++outLayer_Pos) { - sum += (trainSample->out[currentTrainSample_Pos][outLayer_Pos] - outLayer[outLayer_Pos].value) - * outLayer[outLayer_Pos].value * (1.0 - outLayer[outLayer_Pos].value) - * hideLayer[hideLayer_Pos].weight[outLayer_Pos]; - } - inputLayer[inputLayer_Pos].weight_delta[hideLayer_Pos] += sum * hideLayer[hideLayer_Pos].value * (1.0 - hideLayer[hideLayer_Pos].value) - * inputLayer[inputLayer_Pos].value; - } - } - - } - - - // 判断误差是否达到允许误差范围 - if(error_max < threshold){ - printf("\a Training completed!Total training count:%d, maximum error is:%f\n", trainTime + 1, error_max); - break; - } - - // 误差无法接受,开始修正 - - for (int inputLayer_Pos = 0; inputLayer_Pos < INNODE; ++inputLayer_Pos) { - for (int hideLayer_Pos = 0; hideLayer_Pos < HIDENODE; ++hideLayer_Pos) { - inputLayer[inputLayer_Pos].weight[hideLayer_Pos] += StudyRate - * inputLayer[inputLayer_Pos].weight_delta[hideLayer_Pos] / - (double) trainSize; - } - } - - for (int hideLayer_Pos = 0; hideLayer_Pos < HIDENODE; ++hideLayer_Pos) { - hideLayer[hideLayer_Pos].bias += StudyRate - * hideLayer[hideLayer_Pos].bias_delta / (double )trainSize; - for (int outLayer_Pos = 0; outLayer_Pos < OUTNODE; ++outLayer_Pos) { - hideLayer[hideLayer_Pos].weight[outLayer_Pos] += StudyRate - * hideLayer[hideLayer_Pos].weight_delta[outLayer_Pos] / (double )trainSize; - } - } - - for (int outLayer_Pos = 0; outLayer_Pos < OUTNODE; ++outLayer_Pos) { - outLayer[outLayer_Pos].bias += StudyRate - * outLayer[outLayer_Pos].bias_delta / (double )trainSize; - } - } - - // 训练完成,读取测试集 - Sample * testSample = getTestData("TestData.txt"); - printf("The predicted results are as follows:\n"); - for (int currentTestSample_Pos = 0; currentTestSample_Pos < testSize; ++currentTestSample_Pos) { - for (int inputLayer_Pos = 0; inputLayer_Pos < INNODE; ++inputLayer_Pos) { - inputLayer[inputLayer_Pos].value = testSample->in[currentTestSample_Pos][inputLayer_Pos]; - } - - for (int hideLayer_Pos = 0; hideLayer_Pos < HIDENODE; ++hideLayer_Pos) { - double sum = 0.0; - for (int inputLayer_Pos = 0; inputLayer_Pos < INNODE; ++inputLayer_Pos) { - sum += inputLayer[inputLayer_Pos].value * inputLayer[inputLayer_Pos].weight[hideLayer_Pos]; - } - sum -= hideLayer[hideLayer_Pos].bias; - hideLayer[hideLayer_Pos].value = sigmoid(sum); - } - - for (int outLayer_Pos = 0; outLayer_Pos < OUTNODE; ++outLayer_Pos) { - double sum = 0.0; - for (int hideLayer_Pos = 0; hideLayer_Pos < HIDENODE; ++hideLayer_Pos) { - sum += hideLayer[hideLayer_Pos].value * hideLayer[hideLayer_Pos].weight[outLayer_Pos]; - } - sum -= outLayer[outLayer_Pos].bias; - outLayer[outLayer_Pos].value = sigmoid(sum); - } - - for (int outLayer_Pos = 0; outLayer_Pos < OUTNODE; ++outLayer_Pos) { - testSample->out[currentTestSample_Pos][outLayer_Pos] = outLayer[outLayer_Pos].value; - } - } - - printData(testSample, testSize); - - return 0; -}