这次先上 运行“结果”:
```
训练次数 误差
0 16.519723
500 0.135468
1000 0.105337
1500 0.082751
2000 0.076986
2500 0.073428
3000 0.070383
3500 0.067702
4000 0.065119
4500 0.062573
5000 0.060117
5500 0.057829
6000 0.055517
6500 0.053316
7000 0.051277
6*3=:17.721119
检验 训练“BP网络”训练的 成果:
3.200000*6=:19.920839
4.300000*8=:35.636405
6.000000*8=:49.607321
2.100000*7=:15.587592
4.300000*8=:35.636405
```
结果说明:
“BP神经网络”学习乘法……成果是, TA学的是那个意思(精度一般般)……
但就像小动物,能猜个大概其……也是一种进步。
二、
再上 C的 程序代码 和 注释:
```
// 在微软VS-C++2017调试运行通过-ConA1neuron20200310a.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _CRT_SECURE_NO_WARNINGS
#include "pch.h"
#include <iostream>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#define Error001Precision 0.05 //误差允许精度
#define Display01Frequency 500 //显示训练次数的频次//频率
#define Data 820 //Data 用来表示已经知道的数据样本的数量,也就是训练样本的数量
#define In 2 //In 表示对于每个样本有多少个输入变量
#define Out 1
#define Neuron 45 //Neuron 表示神经元的数量
#define TrainC 20000 //TrainC 来表示训练的次数
#define A 0.2
//在具体实现对误差修改中,我们再加上学习率,并且对先前学习到的修正误差量进行继承,直白的说就是都乘上一个0到1之间的数,具体的见如下实现参考代码
#define B 0.4
#define a 0.2
#define b 0.3
double d_in[Data][In]; // ,d_in[Data][In] 存储 Data 个样本,每个样本的 In 个输入
double d_out[Data][Out]; //d_out[Data][Out] 存储 Data 个样本,每个样本的 Out 个输出。
double w[Neuron][In];//w[Neuron][In] 表示某个输入对某个神经元的权重
double o[Neuron]; //数组 o[Neuron] 记录的是神经元通过激活函数对外的输出, ,
double v[Out][Neuron];//v[Out][Neuron] 来表示某个神经元对某个输出的权重;
double Maxin[In], Minin[In], Maxout[Out], Minout[Out];
double OutputData[Out];//OutputData[Out] 存储BP神经网络的输出。
double dv[Out][Neuron], dw[Neuron][In]; //与之对应的保存它们两个修正量的数组 dw[Neuron][In] 和 dv[Out][Neuron]
double e01ErrorPrecision; //误差
void writeTest() {
FILE *fp1, *fp2;
double r1, r2;
int i;
srand((unsigned)time(NULL));
if ((fp1 = fopen("D:\\in.txt", "w")) == NULL) {
printf("can not open the in file\n");
exit(0);
}
if ((fp2 = fopen("D:\\out.txt", "w")) == NULL) {
printf("can not open the out file\n");
exit(0);
}
for (i = 0; i < Data; i++) {
r1 = rand() % 1000 / 100.0;
r2 = rand() % 1000 / 100.0;
fprintf(fp1, "%lf %lf\n", r1, r2);
fprintf(fp2, "%lf \n", r1*r2); //训练 bp网络学习乘法! r1 + r2);
}
fclose(fp1);
fclose(fp2);
}
void readData() {
FILE *fp1, *fp2;
int i, j;
if ((fp1 = fopen("D:\\in.txt", "r")) == NULL) {
printf("can not open the in file\n");
exit(0);
}
for (i = 0; i < Data; i++)
for (j = 0; j < In; j++)
fscanf(fp1, "%lf", &d_in[i][j]);
fclose(fp1);
if ((fp2 = fopen("D:\\out.txt", "r")) == NULL) {
printf("can not open the out file\n");
exit(0);
}
for (i = 0; i < Data; i++)
for (j = 0; j < Out; j++)
fscanf(fp1, "%lf", &d_out[i][j]);
fclose(fp2);
}
void initBPNework() {
int i, j;
//第01步,先:找到数据最小、最大值:
for (i = 0; i < In; i++) {
Minin[i] = Maxin[i] = d_in[0][i];
for (j = 0; j < Data; j++)
{
Maxin[i] = Maxin[i] > d_in[j][i] ? Maxin[i] : d_in[j][i];
Minin[i] = Minin[i] < d_in[j][i] ? Minin[i] : d_in[j][i];
}
}
//找输出数据的最小、最大值:
for (i = 0; i < Out; i++) {
Minout[i] = Maxout[i] = d_out[0][i];
for (j = 0; j < Data; j++)
{
Maxout[i] = Maxout[i] > d_out[j][i] ? Maxout[i] : d_out[j][i];
Minout[i] = Minout[i] < d_out[j][i] ? Minout[i] : d_out[j][i];
}
}
//第02:归一化处理
for (i = 0; i < In; i++)
for (j = 0; j < Data; j++)
d_in[j][i] = (d_in[j][i] - Minin[i] + 1) / (Maxin[i] - Minin[i] + 1);
for (i = 0; i < Out; i++)
for (j = 0; j < Data; j++)
d_out[j][i] = (d_out[j][i] - Minout[i] + 1) / (Maxout[i] - Minout[i] + 1);
//第03:初始化神经元
for (i = 0; i < Neuron; ++i)
for (j = 0; j < In; ++j) {
w[i][j] = rand()*2.0 / RAND_MAX - 1;
dw[i][j] = 0;
}
for (i = 0; i < Neuron; ++i)
for (j = 0; j < Out; ++j) {
v[j][i] = rand()*2.0 / RAND_MAX - 1;
dv[j][i] = 0;
}
}
//BP神经网络
//函数 computO(i) 负责的是通过BP神经网络的机制对样本 i 的输入,预测其输出。回想BP神经网络的基本模型(详情见 基本模型)对应的公式(1)还有 激活函数对应的公式(2):
void computO(int var) {
int i, j;
double sum, y;
for (i = 0; i < Neuron; ++i) {
sum = 0;
for (j = 0; j < In; ++j)
sum += w[i][j] * d_in[var][j];
o[i] = 1 / (1 + exp(-1 * sum));
}
for (i = 0; i < Out; ++i) {
sum = 0;
for (j = 0; j < Neuron; ++j)
sum += v[i][j] * o[j];
OutputData[i] = sum;
}
}
//函数 backUpdate(i) 负责的是将预测输出的结果与样本真实的结果进行比对,然后对神经网络中涉及到的权重进行修正,也这是BP神经网络实现的关键所在。如何求到对于 w[Neuron][In] 和 v[Out][Neuron] 进行修正的误差量便是关键所在!误差修正量的求法在基本模型一文中数学分析部分有解答,具体问题具体分析,落实到我们设计的这个BP神经网络上来说,需要得到的是对w[Neuron][In] 和 v[Out][Neuron] 两个数据进行修正误差,误差量用数据结构 dw[Neuron][In] 和 dv[Out][Neuron] 来进行存储
void backUpdate(int var)
{
int i, j;
double t;
for (i = 0; i < Neuron; ++i)
{
t = 0;
for (j = 0; j < Out; ++j) {
t += (OutputData[j] - d_out[var][j])*v[j][i];
dv[j][i] = A * dv[j][i] + B * (OutputData[j] - d_out[var][j])*o[i];
v[j][i] -= dv[j][i];
}
for (j = 0; j < In; ++j) {
dw[i][j] = a * dw[i][j] + b * t*o[i] * (1 - o[i])*d_in[var][j];
w[i][j] -= dw[i][j];
}
}
}
double result(double var1, double var2)
{
int i, j;
double sum, y;
var1 = (var1 - Minin[0] + 1) / (Maxin[0] - Minin[0] + 1);
var2 = (var2 - Minin[1] + 1) / (Maxin[1] - Minin[1] + 1);
for (i = 0; i < Neuron; ++i) {
sum = 0;
sum = w[i][0] * var1 + w[i][1] * var2;
o[i] = 1 / (1 + exp(-1 * sum));
}
sum = 0;
for (j = 0; j < Neuron; ++j)
sum += v[0][j] * o[j];
return sum * (Maxout[0] - Minout[0] + 1) + Minout[0] - 1;
}
void writeNeuron()
{
FILE *fp1;
int i, j;
if ((fp1 = fopen("D:\\neuron.txt", "w")) == NULL)
{
printf("can not open the neuron file\n");
exit(0);
}
for (i = 0; i < Neuron; ++i)
for (j = 0; j < In; ++j) {
fprintf(fp1, "%lf ", w[i][j]);
}
fprintf(fp1, "\n\n\n\n");
for (i = 0; i < Neuron; ++i)
for (j = 0; j < Out; ++j) {
fprintf(fp1, "%lf ", v[j][i]);
}
fclose(fp1);
}
void trainNetwork() //训练
{
int i, c01Count = 0;// c01Count训练次数 计数
int j;
do //do110
{
e01ErrorPrecision = 0;
for (i = 0; i < Data; ++i) {
computO(i);
for (j = 0; j < Out; ++j)
e01ErrorPrecision += fabs((OutputData[j] - d_out[i][j]) / d_out[i][j]);
backUpdate(i);
}
if (0 == c01Count % Display01Frequency) //1000) //20) //if220
{
printf("%d %lf\n", c01Count, e01ErrorPrecision / Data);
}//if220
c01Count++;
} while (c01Count<TrainC && e01ErrorPrecision / Data> Error001Precision); // 0.05);// 1); // 0.01); //do110
}//训练-End
int main()
{
std::cout << "Hello World!\n";
writeTest();
readData();
initBPNework();
trainNetwork();
printf("%d*%d=:%lf \n",6,3, result(6, 3));
printf("%f*%d=:%lf \n",3.2, 6, result(3.2, 6));
printf("%f*%d=:%lf \n",4.3,8, result(4.3, 8));
printf("%f*%d=:%lf \n",6.0,8, result(6, 8));
printf("%f*%d=:%lf \n",2.1,7, result(2.1, 7));
printf("%f*%d=:%lf \n",4.3,8, result(4.3, 8));
writeNeuron();
return 0;
}//
//
```
再运行一次,
训练BP网络学会“乘法”:
```
训练次数 误差
8500 0.081898
9000 0.079318
9500 0.075935
10000 0.071483
10500 0.066695
11000 0.063684
11500 0.062921
12000 0.062295
12500 0.062092
13000 0.061443
13500 0.060544
14000 0.059567
14500 0.058434
15000 0.057286
15500 0.056034
16000 0.054670
16500 0.053297
17000 0.051820
17500 0.050263
检验“BP网络”训练的成果:
6*3=:16.459228
3.200000*6=:18.756765
4.300000*8=:33.943728
6.000000*8=:47.677582
2.100000*7=:14.412758
4.300000*8=:33.943728
```
- BP神经网络到c++实现等--机器学习“掐死教程”
- 训练bp(神经)网络学会“乘法”--用”蚊子“训练高射炮
- Ann计算异或&前馈神经网络20200302
- 神经网络ANN的表示20200312
- 简单神经网络的后向传播(Backpropagration, BP)算法
- 牛顿迭代法求局部最优(解)20200310
- ubuntu安装numpy和pip3等
- 从零实现一个神经网络-numpy篇01
- _美国普林斯顿大学VictorZhou神经网络神文的改进和翻译20200311
- c语言-普林斯顿victorZhou神经网络实现210301
- bp网络实现xor异或的C语言实现202102
- bp网络实现xor异或-自动录入输入(写死20210202
- Mnist在python3.6上跑tensorFlow2.0一步一坑20210210
- numpy手写数字识别-直接用bp网络识别210201