是一次惨痛的教训,再写神经网络时,就很疑惑。
为什么有时运算会出错,大量检查算法,因为它是不经常的错误,所以没留意。
rb与r,w与bw最好配对,因为w写fwrite会在每个0A前加0D(换行,回车)(window平台)
r是在自动转0A,但用rb就不同了。
所以每一次调文件,训练结果总是怪怪的。
更新了~~~~
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#include<iostream>
using namespace std;
class Cell
{
public:
int insig_row, out_columu; double v;
double* out;
double** w;
double* insig;
double* back_e;
Cell()
{
v = 1;
printf("cell success\n");
}
void initCell(int out_columu, int insig_row)
{
int i, j;
this->out_columu = out_columu;
this->insig_row = insig_row;
this->out = new double[out_columu];
this->w = new double* [insig_row];
for (i = 0; i < insig_row; i++)
this->w[i] = new double[out_columu];
srand(time(NULL));
for (i = 0; i < insig_row; i++)
for (j = 0; j < out_columu; j++)
this->w[i][j] = ((double)rand() / ((RAND_MAX - 1) / 2)) - 1;
this->insig = new double[insig_row];
this->back_e = new double[out_columu];
printf("initCell success\n");
//printf("insig_row:%d out_columu:%d\n", this->insig_row,this->out_columu);
}
void Loadcell(double* w, int out_columu, int insig_row)
{
this->out_columu = out_columu;
this->insig_row = insig_row;
this->out = new double[out_columu];
this->w = new double* [insig_row];
for (int i = 0; i < insig_row; i++)
this->w[i] = new double[out_columu];
for (int i = 0; i < insig_row; i++)
for (int j = 0; j < out_columu; j++)
this->w[i][j] = w[j+i* out_columu];
this->insig = new double[insig_row];
this->back_e = new double[out_columu];
printf("LoadCell success\n");
}
~Cell()
{
delete this->out;
for (int i = 0; i < insig_row; i++)
{
delete (this->w[i]);
}
delete w;
delete this->insig;
delete this->back_e;
printf("Cell delete ok!\n");
}
double sig(double x)
{
return 1 / (1 + exp(-x));
}
double* forward(double* out, int outlength)
{
if (outlength < out_columu)
{
printf("缺少输入\n");
return 0;
}
int i, j; double sum = 0;
for (j = 0; j < insig_row; j++)
{
sum = 0;
for (i = 0; i < out_columu && i < outlength; i++)
{
this->out[i] = out[i];
sum += this->out[i] * w[j][i];
}
insig[j] = sig(sum);
//insig[j] = sum;
}
return insig;
}
double* backward(double* e, int elength)
{
if (elength < insig_row)
{
printf("缺少误差输入\n");
return 0;
}
int i, j, k; double sum = 0;
for (i = 0; i < out_columu; i++)
{
sum = 0;
for (j = 0; j < insig_row; j++)
sum += insig[j] * (1 - insig[j]) * w[j][i];
back_e[i] = sum;
}
for (j = 0; j < insig_row; j++)
for (i = 0; i < out_columu; i++)
w[j][i] = w[j][i] + e[j] * insig[j] * (1 - insig[j]) * out[i] * v;
//w[j][i] = w[j][i] + e[j] *out[i];
return back_e;
}
void adjust_v(double* e, int elength)
{
double sum = 0;
for (int i = 0; i < elength; i++)
sum += fabs(e[i]); this->v = sin((3.1415926 / 2) * (sum / elength));
printf(" 学习率: %lf sum: %lf\n", v, sum);
}
void print(void)
{
int i, j;
printf("矩阵:\n");
for (i = 0; i < insig_row; i++)
{
for (j = 0; j < out_columu; j++)
printf("%+9.8lf ", this->w[i][j]);
printf("\n");
}
printf("out_columu:%d insig_row:%d\n",out_columu, insig_row);
}
};
void printeroror(double* e, int elength)
{
double sum = 0;
printf("误差:");
for (int i = 0; i < elength; i++)
{
printf("%-9.6lf ", e[i]);
//sum += e[i];
}
//printf("总误差:%lf", sum);
printf("\n");
}
void printout(double* out, int i)
{
printf("输出:");
for (int i = 0; i < 3; i++)
{
printf("%-9.4lf ", out[i]);
}
printf("\n");
}
class network
{
public:
Cell* cells;
int times = 50000, * layers = NULL, num;
double* e;
double* input;
double* output;
void createnetwork()
{
int mid, i;
printf("输入层数:");
scanf("%d", &num);
printf("输入次数:");
scanf("%d", &this->times);
layers = new int[num + 1];
cells = new Cell[num - 1];
printf("输入每层的输出数:");
for (int i = 0; i < num; i++)
scanf("%d", &layers[i]);
for (int j = 0, i = 0; j < num - 1; j++, i++)
{
cells[i].initCell(layers[j], layers[j + 1]);
}
layers[num] = 0;
printf("layers[]:");/*layers信息*/
for (i = 0; i < num; i++)
{
printf("%d ", layers[i]);
}
printf("\n");
}
void clear()
{
delete layers;
delete[]cells;
delete e;
printf("network delete ok!\n");
}
void Trainnetwork(double* input, double* target)
{
double* cellin, *cell_e; int i;
e = new double[layers[num-1]];
cellin = input;
for (int k = 0; k < times; k++)
{
for (i = 0; i < num-1; i++)
{
cellin = cells[i].forward(cellin, layers[i]);
//printout(cellin,layers[i]);
}
for (i = 0; i < layers[num-1]; i++)
{
e[i] = target[i] - cellin[i];
}
printeroror(e, layers[num-1]);
cell_e = e;
for (i = num-1-1; i >= 0; i--)
{
cell_e = cells[i].backward(cell_e, layers[i+1]);
}
}
}
void savenetwork()
{
char name[30] = { '\0' };
printf("savenetwork输入文件名:\n");
scanf("%s", &name);
strcat(name, ".network");
FILE* netfile = fopen(name, "wb");
fseek(netfile, 0, SEEK_SET);
fwrite(layers,sizeof(int)*(num+1), 1, netfile);
for (int i = 0; i < num - 1; i++)
{
for(int j=0;j< cells[i].insig_row;j++)
fwrite(cells[i].w[j], sizeof(double) , cells[i].out_columu, netfile);
}
fclose(netfile);
}
void readnekwork()
{
char name[30] = { '\0' }; int c = 1, * p = &c; num = 0;
double* read_w;
printf("readnekwork输入文件名:\n");
scanf("%s", &name);
strcat(name, ".network");
FILE* netfile = fopen(name, "rb");
printf("OK!!!!\n");
if (!netfile)
{
printf("文件不存在!\n");
return;
}
fseek(netfile, 0, SEEK_SET);
layers = new int[10000];
while (*p != 0)
{
fread(p, sizeof(int), 1, netfile);
layers[num++] = *p;
if (num > 9990)
{
printf("文件层数过大\n");
return;
}
}
printf("read layers:");
for (int k = 0; k < num; k++)
printf("%d ", layers[k]);
printf("\n");
cells = new Cell[num - 1];
read_w = new double[1000000];
for (int j = 0, i = 0; j < num - 1; j++, i++)
{
fread(read_w, sizeof(double) * layers[j] * layers[j + 1],1, netfile);
printf("read read_w:");
for (int k = 0; k < layers[j] * layers[j + 1]; k++)
printf("%lf ", read_w[k]);
printf("\n");
cells[i].Loadcell(read_w, layers[j], layers[j + 1]);
}
delete read_w;
}
void printcells()
{
for (int i = 0; i < num - 1; i++)
{
cells[i].print();
}
}
};
int main()
{
network net; double input[3] = { 0.9,0.3,0.4 }, target[3] = { 0.5,0.5,0.5 };
net.createnetwork();
net.printcells();
net.Trainnetwork(input, target);
net.printcells();
net.savenetwork();
net.readnekwork();
net.printcells();
net.clear();
return 0;
}
已经完成存储,训练了