# bp网络 改为多项式的改进

1. 11月前

### u.n.owen围观中

1楼 2018年2月9日
11月前u.n.owen围观中 重新编辑

实现的代码

#include<vector>
#include<cassert>
#include<cmath>
#include<iostream>
using std::fabs;
using std::vector;
using std::cout;
using std::endl;
using std::ends;

typedef double Data_0;
class Data_1{
public:
vector<double> 	data;

Data_1(){}
Data_1(vector<double> d){
int i,n=d.size();
for(i=0;i<n;++i){
data.push_back(d[i]);
}
}
operator vector<double>(){		return data;	}
double& operator[](unsigned int i){
assert(i<=data.size());
if(i==data.size()){
data.resize(i+1);
}
return data[i];
}
int size(){		return data.size();	}
};

/*
class Cell{
public:
double y;
double dy;
vector<double > w;
};*/
class Ploycell{
public:
double y;
double dy;
vector<Ploycell > *w;

Ploycell():y(0),dy(0){
w = new vector<Ploycell>;
}
//Ploycell(int y_):y(y_),dy(0){		w = new vector<Ploycell>;}
Ploycell(const Ploycell &p):y(p.y),dy(p.dy),w(p.w){}
Ploycell& operator =(const Ploycell &p){		y=p.y,dy=p.dy,w=p.w;return *this;	}
void clean(){
int i,n=w->size();
for(i=0;i<n;++i){
(*w)[i].clean();
}
delete w;
}
~Ploycell(){}
operator Data_1(){
Data_1 a;
int i,n=w->size();
for(i=0;i<n;++i){
a.data.push_back((*w)[i].y);
}
return a;
}

void fun(Data_1& d){	//Data_1 operator*(Data_1);
y=0;
dy=0;
unsigned int i,n=d.size();
if(w->size()<n){
w->resize(n);
}
n=w->size();
d.data.resize(n,0);
for(i=0;i<n;++i){
if((*w)[i].w->size()!=0){/////////////////
(*w)[i].fun(d);
}
y += (*w)[i].y * d[i];//f(x)=x
}
}
void updata_0(const Data_1& d){
int i,n=w->size();
if(n==0)	return;
for(i=0;i<n;++i){
(*w)[i].dy = dy * d.data[i];
(*w)[i].updata_0(d);
}
dy=0;
}
void updata_1(double p=1){
int i,n=w->size();
if(n==0){
y -= dy;
dy *= p;
}else{
for(i=0;i<n;++i)
(*w)[i].updata_1();
}
}
void updata_2(){
int i,n=w->size();
if(n==0){
(*w).resize(1);
return;
}
for(i=0;i<n;++i){
(*w)[i].updata_2();
}
}
};

class Ploy_stream{
public:
Ploycell poly;
vector<Data_1> sample_i;
vector<double> sample_o;
double e000;
int updatatime;

Ploy_stream():e000(0.01),updatatime(100){}
~Ploy_stream(){
poly.clean();
}

sample_i.push_back(i);
sample_o.push_back(o);
}
Data_1 a;
a.data.push_back(1);
a.data.insert(a.data.end(),i.begin(),i.end());
}
double math(Data_1 in){
poly.fun(in);
return poly.y;
}
void math(vector<double> in){
Data_1 a;
a.data.push_back(1);
a.data.insert(a.data.end(),in.begin(),in.end());
math(a);
}
void train(){
double l=1;
int i,n=sample_i.size();
double E,e=1000000000;
int t=0,time=10000;
int T=0;//updatatime=100

Data_1 a;
int j,m;

do{
E=0;
for(i=0;i<n;++i){
poly.fun(sample_i[i]);
poly.dy = (poly.y-sample_o[i])*l/n;
E=fabs(poly.y-sample_o[i]);
//a=sample_i[i];
m=sample_i[i].data.size();
a.data.resize(m);//a.data.clear();
for(j=0;j<m;++j){
//误差还原 		//y=sum(w[i]*x[i]),,dy=sum(dw*x),dw[i]=dy/x[i]	// ->dw[i]=dy/x[i]*k?
if(sample_i[i][j]==0){
a[j]=0;
}else{
a[j]=1.0/sample_i[i][j];
}
}
poly.updata_0(a);
}
poly.updata_1(1);

if(e/E<1.1){
l*=0.5;
++T;
if(T%updatatime==0){// updatatime=10；
poly.updata_2();
l=1;
}
}
cout<<t<<"\t"<<E<<endl;
e=E;
++t;
}while(t<time&&E>e000);

if(t==time){
cout<<"train_uncomplate"<<endl;
}else{
cout<<"train_complate"<<endl;
}
}
};
2. ### u.n.owen围观中

2楼 2018年2月9日
11月前u.n.owen围观中 重新编辑

设第n层和第m层，且n=m+1
如代码所示，
将神经模型： $y_n = f( \sum y_{m,i} * w_{m,i} )$ ，$y_{0,i}=x_i$
改为： $y_n = \sum x_i * y_{m,i}$
将反向传播模型：$dw_{m,i} = dy_n * f' * y_{m,i}$
$dy_{m,i} = dy_n * f' * w_{m,i}$
改为： $dy_{m,i} = dy_n / x_i ,(x_i 不为0)$
$dy_{m,i} = 0 ,(x_i = 0)$

测试用代码

#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include<vector>

#include"B_poly.h"

using std::cout;
using std::cerr;
using std::endl;
using std::ends;
using std::ofstream;
using std::ifstream;

using std::vector;

int Data=11000;
int Inn=2;
int Outn=1;

vector<vector<double> > In;
vector<vector<double> > Out;

void writeTest(){
double r1,r2;
int i;
srand((unsigned)time(NULL));

ofstream f1("in_1.txt");
if(f1.fail()){
cerr<<"can not open the in file"<<endl;
exit(0);
}
ofstream f2("out_1.txt");
if(f2.fail()){
cerr<<"can not open the out file"<<endl;
exit(0);
}

for(i=0;i<Data;i++){
r1=rand()%1000/1.0;
r2=rand()%1000/1.0;
f1<<r1<<" "<<r2<<endl;
f2<<sqrt(r1*r1+r2*r2)<<endl;
}
f1.close();
f2.close();
}

int i,j;
double t;
vector<double> in_;

ifstream f1("in_1.txt");
if(f1.fail()){
cerr<<"can not open the in file"<<endl;
exit(0);
}
for(i=0;i<Data;i++){
for(j=0; j<Inn; j++){
f1 >> t;
in_.push_back(t);
}
In.push_back(in_);
in_.clear();
}

ifstream f2("out_1.txt");
if(f2.fail()){
cerr<<"can not open the out file"<<endl;
exit(0);
}
for(i=0;i<Data;i++)
for(j=0; j<Outn; j++){
f2 >> t;
in_.push_back(t);
Out.push_back(in_);
in_.clear();
}
}

int main(){
Ploy_stream p;
p.updatatime=20;

writeTest();

int i,n=In.size();
//cout<<n<<endl;
for(i=0;i<n;++i){
}
p.train();

int j,x=0;
vector<double> a;
for (i = 1;i <= 1000; i+=100){
for (j = 1;j <= 1000; j+=100){
a.push_back(i);
a.push_back(j);
p.math(a);
printf("[%d,%d]=%.1lf  ",i,j,p.poly.y);
a.clear();
x++;
if (x%10==0){
printf("\n");
}
}
}
}
3. ### 丁香丛中的雪狼

3楼 2018年2月11日

看起来是很高深的东西呢。。。楼主能不能告诉我，这些是用于做什么的？

4. ### u.n.owen围观中

4楼 2018年2月11日

@丁香丛中的雪狼 看起来是很高深的东西呢。。。楼主能不能告诉我，这些是用于做什么的？

就是拟合出个函数，输入任意维度的那种。。。
虽然不管怎么想，最简单的方法就是最小二乘法处理下就完事了。但想象中觉得写个 自动生成函数然后进行矩阵运算 的程序好麻烦呀。。。
其实原理很简单的。而且发这帖子主要因为，反向传播的那个公式，昨天我刚发现公式推导是错的，而且当时我稀里糊涂的就信了，就好气了。。。