用C实现单隐层神经网络的训练和预测(手写BP算法)

实验要求:
?实现10以内的非负双精度浮点数加法,例如输入4.99和5.70,能够预测输出为10.69
?使用Gprof测试代码热度

代码框架
?随机初始化1000对数值在0~10之间的浮点数,保存在二维数组a[1000][2]中。
?计算各对浮点数的相加结果,保存在数组b[1000]中,即b[0] = a[0][0] + a[0][1],以此类推。数组a、b即可作为网络的训练样本。
?定义浮点数组w、v分别存放隐层和输出层的权值数据,并随机初始化w、v中元素为-1~1之间的浮点数。
?将1000组输入(a[1000][2])逐个进行前馈计算,并根据计算的输出结果与b[1000]中对应标签值的差值进行反馈权值更新,调整w、v中各元素的数值。
?1000组输入迭代完成后,随机输入两个浮点数,测试结果。若预测误差较大,则增大训练的迭代次数(训练样本数)。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
//归一化二维数组
void normalization(float num[1000][2]){
    float max1 = 0.0,max2 = 0.0;
    float min1 = 0.0,min2 = 0.0;
    for(int i = 0;i<1000;i++){
        if(num[i][0]>max1||num[i][0]<min1){
            if(num[i][0]>max1){
                max1 = num[i][0];
            }
            if(num[i][0]<min1){
                min1 = num[i][0];
            }
        }
        if(num[i][1]>max2||num[i][1]<min2){
            if(num[i][1]>max2){
                max2 = num[i][1];
            }
            if(num[i][1]<min2){
                min2 = num[i][1];
            }
        }
    }
    for(int i = 0;i<1000;i++){
        num[i][0] = (num[i][0]-min1+1)/(max1-min1+1);
        num[i][1] = (num[i][1]-min2+1)/(max2-min1+1);
    }
    printf("a[][0]的最大值和最小值分别为:%f\t%f",max1,min1);
    printf("\na[][1]的最大值和最小值分别为:%f\t%f",max2,min2);
    printf("\n");
}
//归一化一维数组
void normalization_b(float num[1000]){
    float max = 0.0,min = 0.0;
    for(int i = 0;i<1000;i++){
        if(num[i]>max||num[i]<min){
            if(num[i]>max){
                max = num[i];
            }else{
                min = num[i];
            }
        }
    }
    for(int i = 0;i<1000;i++){
        num[i] = (num[i]-min+1)/(max-min+1);
    }
    printf("b数组归一化的最大值和最小值为:%f,%f",max,min);
}
//后向隐藏层公式计算
float compute_hidden(float a,float b,float *w_a,float *w_b,float *bias_c){
    float value = 0.0;
    value = a*(*w_a)+b*(*w_b)+(*bias_c);
    value = 1/(1+exp(-value));
    return value;
}
//后向输出层公式计算
float compute_output(float c,float *w_c,float *bias_d){
    float value = 0.0;
    value = c*(*w_c)+(*bias_d);
    value = 1/(1+exp(-value));
    return value;
}
//前向输出层公式计算
float pro_output(float predict_num,float real_num){
    float error = 0.0;
    error = predict_num*(1-predict_num)*(real_num-predict_num);
    return error;
}
//bp算法
void bp(float a,float b,float real_num,float *w_a,float *w_b,float *v,float *bias_c,float *bias_d){
    //前向计算
    //隐藏层
    float output = compute_hidden(a,b,w_a,w_b,bias_c);
    //输出层
    float output_final = compute_output(output,v,bias_d);
    //反向计算
    float error_output = 0.0;
    //输出层
    error_output = pro_output(output_final,real_num);
    //更新权重和偏向!
    //定义学习率
    double learning_rate = 0.01;
    *v = *v + learning_rate*error_output*output;
    *bias_d = *bias_d + learning_rate*error_output;
    //前向隐藏层
    float error_hidden = 0.0;
    error_hidden = output*(1-output)*(error_output*(*v));
    //更新权重和偏向
    *w_a = *w_a + learning_rate*(error_hidden*a);
    *w_b = *w_b + learning_rate*(error_hidden*b);
    *bias_c = *bias_c + learning_rate*error_hidden;
}
int main(int argc, const char * argv[]) {
    //随机初始化1000对数值在0-10之间的双精度浮点数,保存在二维数组a[1000][2]中
    srand((unsigned) (time(NULL)));
    float a[1000][2],b[1000];
    for(int i = 0;i<1000;i++){
        for(int j = 0;j<2;j++){
            int rd = rand()%1001;
            a[i][j] = rd/100.0;
        }
    }
    for(int i = 0;i<1000;i++){
        b[i] = a[i][0] +a[i][1];
    }
    //归一化处理
    normalization(a);
    normalization_b(b);
    //定义浮点数组w,v分别存放隐层和输出层的权值数据,并随机初始化w,v为(-1,1)之间的浮点数
    int w_a_rand = rand()%200001;
    int w_b_rand = rand()%200001;
    float w_a = w_a_rand/100000.0-1;
    float w_b = w_b_rand/100000.0-1;
    int v_rand = rand()%200001;
    float v = v_rand/100000.0-1;
    int bias_c_rand = rand()%200001;
    float bias_c = bias_c_rand/100000.0-1;
    int bias_d_rand = rand()%200001;
    float bias_d = bias_d_rand/100000.0-1;
    printf("w_a,w_b,v初始随机值分别是:%f    %f    %f\n",w_a,w_b,v);
    //将1000组输入(a[1000][2])逐个进行前馈计算,并根据计算的输出结果与b[1000]中对应标签值的差值进行反馈权值更新,调整w、v中各元素的数值。
    //对于每一个训练实例:执行bp算法
    float max1 ,max2 ,min1 ,min2,max,min;
    printf("x0的归一化参数(最大最小值):");
    scanf("%f,%f",&max1,&min1);
    printf("x1的归一化参数(最大最小值):");
    scanf("%f,%f",&max2,&min2);
    printf("b的归一化参数(最大最小值):");
    scanf("%f,%f",&max,&min);
    int mark = 0;
    float trainnig_data_a[800][2],trainnig_data_b[800],test_data_a[200][2],test_data_b[200];
    int i = 0;
    while (i<1000) {
        if(i == mark){
            //设置测试集
        for(int k = i;k<(i+200);k++){
                test_data_a[k][0] = a[k][0];
                test_data_a[k][1] = a[k][1];
                test_data_b[k] = b[k];
            }
            i +=200;
        }
        //设置训练集
        if(i<mark){
        trainnig_data_a[i][0] = a[i][0];
        trainnig_data_a[i][1] = a[i][1];
        trainnig_data_b[i] = b[i];
        i++;
        }
        if(i>mark){
            trainnig_data_a[i-200][0] = a[i][0];
            trainnig_data_a[i-200][1] = a[i][1];
            trainnig_data_b[i-200] = b[i];
            i++;
        }
    }
    for(int i = 0;i<800;i++){
        //迭代600次
        int times = 0;
        for(int i= 0;i<600;i++){
            bp(trainnig_data_a[i][0],trainnig_data_a[i][1],trainnig_data_b[i],&w_a,&w_b,&v,&bias_c,&bias_d);
            times++;
        }
    }
    //进行预测
    float pre_1,pre_2,predict_value,true_value;

    float MSE[200];
    for(int i = 0;i<200;i++){
        pre_1 = test_data_a[i][0];
        pre_2 = test_data_a[i][1];
        true_value = test_data_b[i];
        //进行计算
        float pre_hidden = compute_hidden(pre_1, pre_2, &w_a, &w_b, &bias_c);
        predict_value = compute_output(pre_hidden, &v, &bias_d);
        //求均方误差
        MSE[i] = (predict_value - true_value)*(predict_value-true_value);
        predict_value = (predict_value*(max-min+1))-1+min;
        true_value = (true_value*(max-min+1))-1+min;
        printf("预测值为:%f   真实值为:%f\n",predict_value,true_value);
    }
    float mean_square_error = 0;
    for(int i = 0;i<200;i++){
        mean_square_error += MSE[i];
    }
    mean_square_error = mean_square_error/200;
    printf("均方误差为:%lf",mean_square_error);
}

运行结果截图:

原文地址:https://www.cnblogs.com/gejuncheng/p/8870914.html

时间: 2024-07-28 17:20:38

用C实现单隐层神经网络的训练和预测(手写BP算法)的相关文章

python实现单隐层神经网络基本模型

应朋友之请写了一份python实现单隐层BP Ann model的code,好久没写博客,就顺便发上来.这篇代码比较干净利落,比较纯粹的描述了Ann的基本原理,初学机器学习的同学可以参考. 模型中几个比较重要的参数: 1.学习率 学习率是影响模型收敛的重要因素,一般来说要根据具体场景灵活调整,过高的学习率会使得函数快速发散. 2.隐元数量 一般来说,增加隐层中神经元的数量比直接增加隐层更加有效,这也是单隐层神经网络的特点.对于复杂程度不算太高的问题而言,单隐层的效果优于多隐层. 3.随机种子位数

Neural Networks and Deep Learning(week3)Planar data classification with one hidden layer(基于单隐层的平面数据分类)

Planar data classification with one hidden layer 你会学习到如何: 用单隐层实现一个二分类神经网络 使用一个非线性激励函数,如 tanh 计算交叉熵的损失值 实现前向传播和后向传播 原文地址:https://www.cnblogs.com/douzujun/p/10289799.html

可变多隐层神经网络的python实现

说明:这是我对网上代码的改写版本(基于win7 + python34) 一.先说说改动的部分 1) 改写了NetStruct类初始化函数 原来: 1 class NetStruct: 2 '''神经网络结构''' 3 def __init__(self, x, y, hidden_layers, activ_fun_list, performance_function = 'mse'): 现在: 1 class NetStruct: 2 '''神经网络结构''' 3 def __init__(s

图片训练:使用卷积神经网络(CNN)识别手写数字

这篇文章中,我们将使用CNN构建一个Tensorflow.js模型来分辨手写的数字.首先,我们通过使之“查看”数以千计的数字图片以及他们对应的标识来训练分辨器.然后我们再通过此模型从未“见到”过的测试数据评估这个分辨器的精确度. 一.运行代码 这篇文章的全部代码可以在仓库TensorFlow.js examples中的tfjs-examples/mnist 下找到,你可以通过下面的方式clone下来然后运行这个demo: $ git clone https://github.com/tensor

CS224d 单隐层全连接网络处理英文命名实体识别tensorflow

什么是NER? 命名实体识别(NER)是指识别文本中具有特定意义的实体,主要包括人名.地名.机构名.专有名词等.命名实体识别是信息提取.问答系统.句法分析.机器翻译等应用领域的重要基础工具,作为结构化信息提取的重要步骤. NER具体任务 1.确定实体位置 2.确定实体类别 给一个单词,我们需要根据上下文判断,它属于下面四类的哪一个,如果都不属于,则类别为0,即不是实体,所以这是一个需要分成 5 类的问题: ? Person (PER) ? Organization (ORG) ? Locatio

TensorFlow基础入门(五)--单隐层与双隐层的神经网络结构

注意:本部分的ppt来源于中国大学mooc网站:https://www.icourse163.org/learn/ZUCC-1206146808?tid=1206445215&from=study#/learn/content?type=detail&id=1211168244&cid=1213754001 原文地址:https://www.cnblogs.com/byczyz/p/12079731.html

tensorflow学习之(十)使用卷积神经网络(CNN)分类手写数字0-9

#卷积神经网络cnn import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data #数据包,如果没有自动下载 number 1 to 10 data mnist = input_data.read_data_sets('MNIST_data',one_hot=True) #用测试集来评估神经网络的准确度 def computer_accuracy(v_xs,v_ys): global pre

tensorflow 卷积神经网络预测手写 数字

# coding=utf8 import tensorflow as tffrom tensorflow.examples.tutorials.mnist import input_datafrom PIL import Image def imageprepare(file_name): """ This function returns the pixel values. The imput is a png file location. ""&quo

C++使用matlab卷积神经网络库MatConvNet来进行手写数字识别

环境:WIN10(64 bit)+VS2010(64 bit)+Matlab2015b(64 bit) 关于MatConvNet的介绍参考:http://www.vlfeat.org/matconvnet/ Github下载地址为:https://github.com/vlfeat/matconvnet/ 我们的目的是将MatConvNet自带的手写数字识别DEMO移植到一个简单的WIN32 DEMO中使用,主要过程有以下几个步骤: (1)配置MatConvNet,然后将手写数字识别DEMO编译