实验要求:
•实现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[][]){
float max1 = 0.0,max2 = 0.0;
float min1 = 0.0,min2 = 0.0;
for(int i = ;i<;i++){
if(num[i][]>max1||num[i][]<min1){
if(num[i][]>max1){
max1 = num[i][];
}
if(num[i][]<min1){
min1 = num[i][];
}
}
if(num[i][]>max2||num[i][]<min2){
if(num[i][]>max2){
max2 = num[i][];
}
if(num[i][]<min2){
min2 = num[i][];
}
}
}
for(int i = ;i<;i++){
num[i][] = (num[i][]-min1+)/(max1-min1+);
num[i][] = (num[i][]-min2+)/(max2-min1+);
}
printf("a[][0]的最大值和最小值分别为:%f\t%f",max1,min1);
printf("\na[][1]的最大值和最小值分别为:%f\t%f",max2,min2);
printf("\n");
}
//归一化一维数组
void normalization_b(float num[]){
float max = 0.0,min = 0.0;
for(int i = ;i<;i++){
if(num[i]>max||num[i]<min){
if(num[i]>max){
max = num[i];
}else{
min = num[i];
}
}
}
for(int i = ;i<;i++){
num[i] = (num[i]-min+)/(max-min+);
}
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 = /(+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 = /(+exp(-value));
return value;
}
//前向输出层公式计算
float pro_output(float predict_num,float real_num){
float error = 0.0;
error = predict_num*(-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*(-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[][],b[];
for(int i = ;i<;i++){
for(int j = ;j<;j++){
int rd = rand()%;
a[i][j] = rd/100.0;
}
}
for(int i = ;i<;i++){
b[i] = a[i][] +a[i][];
}
//归一化处理
normalization(a);
normalization_b(b);
//定义浮点数组w,v分别存放隐层和输出层的权值数据,并随机初始化w,v为(-1,1)之间的浮点数
int w_a_rand = rand()%;
int w_b_rand = rand()%;
float w_a = w_a_rand/100000.0-;
float w_b = w_b_rand/100000.0-;
int v_rand = rand()%;
float v = v_rand/100000.0-;
int bias_c_rand = rand()%;
float bias_c = bias_c_rand/100000.0-;
int bias_d_rand = rand()%;
float bias_d = bias_d_rand/100000.0-;
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 = ;
float trainnig_data_a[][],trainnig_data_b[],test_data_a[][],test_data_b[];
int i = ;
while (i<) {
if(i == mark){
//设置测试集
for(int k = i;k<(i+);k++){
test_data_a[k][] = a[k][];
test_data_a[k][] = a[k][];
test_data_b[k] = b[k];
}
i +=;
}
//设置训练集
if(i<mark){
trainnig_data_a[i][] = a[i][];
trainnig_data_a[i][] = a[i][];
trainnig_data_b[i] = b[i];
i++;
}
if(i>mark){
trainnig_data_a[i-][] = a[i][];
trainnig_data_a[i-][] = a[i][];
trainnig_data_b[i-] = b[i];
i++;
}
}
for(int i = ;i<;i++){
//迭代600次
int times = ;
for(int i= ;i<;i++){
bp(trainnig_data_a[i][],trainnig_data_a[i][],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[];
for(int i = ;i<;i++){
pre_1 = test_data_a[i][];
pre_2 = test_data_a[i][];
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+))-+min;
true_value = (true_value*(max-min+))-+min;
printf("预测值为:%f 真实值为:%f\n",predict_value,true_value);
}
float mean_square_error = ;
for(int i = ;i<;i++){
mean_square_error += MSE[i];
}
mean_square_error = mean_square_error/;
printf("均方误差为:%lf",mean_square_error);
}

运行结果截图:

将隐藏层改为5个神经元

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
struct tag{
float value[];
}x,y;
//归一化二维数组
void normalization(float num[][]){
float max1 = 0.0,max2 = 0.0;
float min1 = 0.0,min2 = 0.0;
for(int i = ;i<;i++){
if(num[i][]>max1||num[i][]<min1){
if(num[i][]>max1){
max1 = num[i][];
}
if(num[i][]<min1){
min1 = num[i][];
}
}
if(num[i][]>max2||num[i][]<min2){
if(num[i][]>max2){
max2 = num[i][];
}
if(num[i][]<min2){
min2 = num[i][];
}
}
}
for(int i = ;i<;i++){
num[i][] = (num[i][]-min1+)/(max1-min1+);
num[i][] = (num[i][]-min2+)/(max2-min1+);
}
printf("a[][0]的最大值和最小值分别为:%f\t%f",max1,min1);
printf("\na[][1]的最大值和最小值分别为:%f\t%f",max2,min2);
printf("\n");
}
//归一化一维数组
void normalization_b(float num[]){
float max = 0.0,min = 0.0;
for(int i = ;i<;i++){
if(num[i]>max||num[i]<min){
if(num[i]>max){
max = num[i];
}else{
min = num[i];
}
}
}
for(int i = ;i<;i++){
num[i] = (num[i]-min+)/(max-min+);
}
printf("b数组归一化的最大值和最小值为:%f,%f",max,min);
}
//后向隐藏层公式计算
struct tag compute_hidden(float a,float b,float *w_a,float *w_b,float *bias_c){
for(int i=;i<;i++){
x.value[i] = a*(w_a[i])+b*(w_b[i])+(bias_c[i]);
x.value[i] = /(+exp(-(x.value[i])));
}
return x;
}
//后向输出层公式计算
float compute_output(struct tag c,float *w_c,float *bias_d){
float value_output = ;
for(int i = ;i<;i++){
c.value[i] = c.value[i]*(w_c[i]);
value_output+=c.value[i];
}
value_output = (value_output+(*bias_d))/;
value_output = /(+exp(-(value_output)));
return value_output;
}
//前向输出层公式计算
float pro_output(float predict_num,float real_num){
float error = 0.0;
error = predict_num*(-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){
//前向计算
//隐藏层
struct tag 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.00003;
for(int i = ;i<;i++){
v[i] = v[i] + learning_rate*error_output*output.value[i];
}
*bias_d = *bias_d + learning_rate*error_output;
//前向隐藏层
float error_hidden[];
for(int i = ;i<;i++){
error_hidden[i] = output.value[i]*(-output.value[i])*(error_output*v[i]);
}
//更新权重和偏向
for(int i = ;i<;i++){
w_a[i] = w_a[i] + learning_rate*(error_hidden[i]*a);
w_b[i] = w_b[i] + learning_rate*(error_hidden[i]*b);
bias_c[i] = bias_c[i] + learning_rate*error_hidden[i];
}
}
int main(int argc, const char * argv[]) {
//随机初始化1000对数值在0-10之间的双精度浮点数,保存在二维数组a[1000][2]中
srand((unsigned) (time(NULL)));
float a[][],b[];
for(int i = ;i<;i++){
for(int j = ;j<;j++){
int rd = rand()%;
a[i][j] = rd/100.0;
}
}
for(int i = ;i<;i++){
b[i] = a[i][] +a[i][];
}
//归一化处理
normalization(a);
normalization_b(b);
//定义浮点数组w,v分别存放隐层和输出层的权值数据,并随机初始化w,v为(-1,1)之间的浮点数
int w_a_rand[];
int w_b_rand[];
for(int i = ;i<;i++){
w_a_rand[i] = rand()%;
}
for(int i = ;i<;i++){
w_b_rand[i] = rand()%;
}
float w_a[];
for(int i = ;i<;i++){
w_a[i] = w_a_rand[i]/100000.0-;
}
float w_b[];
for(int i = ;i<;i++){
w_b[i] = w_b_rand[i]/100000.0-;
}
int v_rand[];
for(int i = ;i<;i++){
v_rand[i] = rand()%;
}
float v[];
for(int i = ;i<;i++){
v[i] = v_rand[i]/100000.0-;
}
int bias_c_rand[];
for(int i = ;i<;i++){
bias_c_rand[i] = rand()%;
}
float bias_c[];
for(int i = ;i<;i++){
bias_c[i] = bias_c_rand[i]/100000.0-;
}
int bias_d_rand = rand()%;
float bias_d = bias_d_rand/100000.0-;
printf("w_a[1-5],w_b[1-5],v[1-5]初始随机值分别是:");
for(int i = ;i<;i++){
printf("w_a[%d]=%f,w_b[%d]=%f,v[%d]=%f\n",i,w_a[i],i,w_b[i],i,v[i]);
}
//将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 = ;
float trainnig_data_a[][],trainnig_data_b[],test_data_a[][],test_data_b[];
int i = ;
while (i<) {
if(i == mark){
//设置测试集
for(int k = i;k<(i+);k++){
test_data_a[k][] = a[k][];
test_data_a[k][] = a[k][];
test_data_b[k] = b[k];
}
i +=;
}
//设置训练集
if(i<mark){
trainnig_data_a[i][] = a[i][];
trainnig_data_a[i][] = a[i][];
trainnig_data_b[i] = b[i];
i++;
}
if(i>mark){
trainnig_data_a[i-][] = a[i][];
trainnig_data_a[i-][] = a[i][];
trainnig_data_b[i-] = b[i];
i++;
}
}
for(int i = ;i<;i++){
//迭代600次
int times = ;
for(int j= ;j<;j++){
bp(trainnig_data_a[i][],trainnig_data_a[i][],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[];
for(int i = ;i<;i++){
pre_1 = test_data_a[i][];
pre_2 = test_data_a[i][];
true_value = test_data_b[i];
//进行计算
struct tag 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+))-+min;
true_value = (true_value*(max-min+))-+min;
printf("预测值为:%f 真实值为:%f\n",predict_value,true_value);
}
float mean_square_error = ;
for(int i = ;i<;i++){
mean_square_error += MSE[i];
}
mean_square_error = mean_square_error/;
printf("均方误差为:%lf",mean_square_error);
}

但结果没什么优化,估计要批量训练可以将结果更优

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

  1. 实现一个单隐层神经网络python

    看过首席科学家NG的深度学习公开课很久了,一直没有时间做课后编程题,做完想把思路总结下来,仅仅记录编程主线. 一 引用工具包 import numpy as np import matplotlib. ...

  2. 吴裕雄 PYTHON 神经网络——TENSORFLOW 单隐藏层自编码器设计处理MNIST手写数字数据集并使用TensorBord描绘神经网络数据

    import os import numpy as np import tensorflow as tf import matplotlib.pyplot as plt from tensorflow ...

  3. Neural Networks and Deep Learning(week3)Planar data classification with one hidden layer(基于单隐藏层神经网络的平面数据分类)

    Planar data classification with one hidden layer 你会学习到如何: 用单隐层实现一个二分类神经网络 使用一个非线性激励函数,如 tanh 计算交叉熵的损 ...

  4. [纯C#实现]基于BP神经网络的中文手写识别算法

    效果展示 这不是OCR,有些人可能会觉得这东西会和OCR一样,直接进行整个字的识别就行,然而并不是. OCR是2维像素矩阵的像素数据.而手写识别不一样,手写可以把用户写字的笔画时间顺序,抽象成一个维度 ...

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

    说明:这是我对网上代码的改写版本,目的是使它跟前一篇提到的使用方法尽量一致,用起来更直观些. 此神经网络有两个特点: 1.灵活性 非常灵活,隐藏层的数目是可以设置的,隐藏层的激活函数也是可以设置的 2 ...

  6. python-积卷神经网络全面理解-tensorflow实现手写数字识别

    首先,关于神经网络,其实是一个结合很多知识点的一个算法,关于cnn(积卷神经网络)大家需要了解: 下面给出我之前总结的这两个知识点(基于吴恩达的机器学习) 代价函数: 代价函数 代价函数(Cost F ...

  7. python手写bp神经网络实现人脸性别识别1.0

    写在前面:本实验用到的图片均来自google图片,侵删! 实验介绍 用python手写一个简单bp神经网络,实现人脸的性别识别.由于本人的机器配置比较差,所以无法使用网上很红的人脸大数据数据集(如lf ...

  8. 使用TensorFlow的卷积神经网络识别自己的单个手写数字,填坑总结

    折腾了几天,爬了大大小小若干的坑,特记录如下.代码在最后面. 环境: Python3.6.4 + TensorFlow 1.5.1 + Win7 64位 + I5 3570 CPU 方法: 先用MNI ...

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

    这篇文章中,我们将使用CNN构建一个Tensorflow.js模型来分辨手写的数字.首先,我们通过使之“查看”数以千计的数字图片以及他们对应的标识来训练分辨器.然后我们再通过此模型从未“见到”过的测试 ...

随机推荐

  1. Linux 系统的磁盘分区_【all】

    磁盘的存储逻辑结构 1.主引导扇区(446+64+2) MBR(主引导记录)0磁头0磁道的第一扇区 446字节 -->存放系统的引导程序,同Windows 剩下的64字节,分区表(每个分区16字 ...

  2. Redis学习---Redis操作之Hash

    hash表现形式上有些像pyhton中的dict,可以存储一组关联性较强的数据[有点像嵌套字典] hset(name, key, value) --> 设置hash的操作 # 参数:     # ...

  3. Linux系统清除多余的账号

    清除多余的账号 注释掉/etc/passwd文件中nologin的行 grep 'nologin' /etc/passwd 注: 目前暂没想到用命令行替换,后面再想想

  4. Linux 隐藏系统信息

    Linux查看系统信息 [更多参考]https://www.cnblogs.com/ftl1012/p/uname.html Linux隐藏系统信息 查看: cat /etc/issue.net    ...

  5. 禁用休眠(删除休眠文件) 关掉此选项可节省C盘好几G空间:文章内容bat文件源码

    @ECHO offTITLE 关掉休眠 MACHENIKE set TempFile_Name=%SystemRoot%\System32\BatTestUACin_SysRt%Random%.bat ...

  6. 团队开发中,eclipse中安装jre

    团队合作中配置jre时,jre名称应该保持一致,否则不要提交.classpath文件 window-preferences     团队合作中,JRE name一定要一致!

  7. TeamViewer app案例分析

    产品 产品名 TeamViewer远程app 选择原因 远程连接软件是不时之需,当有时私人电脑没有在身边而又需要操作电脑时,远程控制TeamViewer这个软件能帮我们大忙. 调研与评测 1.第一次上 ...

  8. 手动安装 pygame

    在windows下 用pip 安装pygame,老是失败,下载了 wheel文件,用pip安装还是不行,查了一下资料,可以手动安装: 1.在 http://www.lfd.uci.edu/~gohlk ...

  9. 2018 ACM-ICPC 中国大学生程序设计竞赛线上赛 F题 Clever King(最小割)

    2018 ACM-ICPC 中国大学生程序设计竞赛线上赛:https://www.jisuanke.com/contest/1227 题目链接:https://nanti.jisuanke.com/t ...

  10. P1439 【模板】最长公共子序列

    题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子 ...