06.神经网络反向传播+梯度下降分类

模型不太对。。。是一次失败的尝试,后面再改吧。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const double eps=1e-4;
//除去a0每层分别有2 4 4 2个节点 
double g(double x)//激活函数 
{
  return 1.0/(1.0+exp(-x)); 
} 

double theta[20][20][20];
double delta[20][20];
double Delta[20][20][20];
double D[20][20][20];
double a[20][20];
double z[20][20];
double x[20][20],y[20][20]; 
int n,m,l;

//向前传播 
void solve()
{
  //计算第二层
  for(int i=1;i<=4;i++)
  {
  	z[2][i]=0.0;
  	for(int j=0;j<=2;j++)
  	{
  	  z[2][i]=1.0*z[2][i]+1.0*theta[1][i][j]*a[1][j];
  	  //cout<<j<<" "<<i<<" "<<theta[1][i][j]<<endl;
	}
	a[2][i]=g(z[2][i]);
  } 
  a[2][0]=1.0;
  
  //计算第三层
  for(int i=1;i<=4;i++)
  {
  	z[3][i]=0.0;
  	for(int j=0;j<=4;j++)
  	{
  	  z[3][i]=1.0*z[3][i]+1.0*theta[2][i][j]*a[2][j];
	}
	a[3][i]=g(z[3][i]);
  } 
  a[3][0]=1.0;
  
  //输出层
  for(int i=1;i<=2;i++)
  {
  	z[4][i]=0.0;
  	for(int j=0;j<=4;j++)
  	{
  	  z[4][i]=1.0*z[4][i]+1.0*theta[3][i][j]*a[3][j];
	}
	a[4][i]=g(z[4][i]);
  } 
  
}

void train()
{
  double alpha=0.1;
  double lambda=1.0;
  int t=2000;
  while(t--)
  {
  	//初始化 
	for(int i=0;i<=15;i++)
    for(int j=0;j<=15;j++)
    for(int k=0;k<=15;k++)	
    Delta[i][j][k]=0.0;  
    
    //遍历一次训练集 
    for(int cas=1;cas<=m;cas++)
	{
	  //给输入层赋值 
	  for(int i=1;i<=2;i++)
	  {
	  	a[1][i]=1.0*x[cas][i];
	  } 
	  a[1][0]=1.0;
	  solve();
	  
	  //反向传播
	  //输出层 
	  for(int i=1;i<=2;i++)
	  {
	  	delta[4][i]=1.0*a[4][i]-1.0*y[cas][i];
	  	//cout<<cas<<" "<<i<<" "<<a[4][i]<<" "<<y[cas][i]<<" "<<delta[4][i]<<endl;
	  } 
	  //第三层 
	  for(int j=1;j<=4;j++)
	  {
	  	double tmp=0.0;
	  	for(int i=1;i<=2;i++)
	  	{
	  		tmp=1.0*tmp+theta[3][i][j]*delta[4][i];
		}
	  	delta[3][j]=1.0*tmp*(1.0*a[3][j]*(1.0-1.0*a[3][j]));//不用担心a=1 
	  	//cout<<delta[3][j]<<endl;
	  }
	  //第二层 
	  for(int j=0;j<=4;j++)
	  {
	  	double tmp=0.0;
	  	for(int i=1;i<=4;i++)
	  	{
	  		tmp=1.0*tmp+theta[2][i][j]*delta[3][i];
		}
	  	delta[2][j]=1.0*tmp*(1.0*a[2][j]*(1.0-1.0*a[2][j])); 
	  }
	  
	  //计算总误差
	  //第一层
	  for(int i=0;i<=4;i++)
      for(int j=0;j<=2;j++)
      {
      	Delta[1][i][j]=1.0*Delta[1][i][j]+1.0*a[1][j]*delta[2][i];
	  } 
	  //第二层
	  for(int i=0;i<=4;i++)
      for(int j=0;j<=4;j++)
      {
      	Delta[2][i][j]=1.0*Delta[2][i][j]+1.0*a[2][j]*delta[3][i];
	  } 
	  //第三层
	  for(int i=1;i<=2;i++)
      for(int j=0;j<=4;j++)
      {
      	Delta[3][i][j]=1.0*Delta[3][i][j]+1.0*a[3][j]*delta[4][i];
      	//cout<<Delta[3][i][j]<<endl;
	  } 
	} 
	
	//更新theta 
	for(int i=1;i<=4;i++)
    for(int j=0;j<=2;j++)
    {
      if(j==0)
      theta[1][i][j]=1.0*theta[1][i][j]-1.0*alpha/(1.0*m)*Delta[1][i][j];
      else
      theta[1][i][j]=1.0*theta[1][i][j]-1.0*alpha*(1.0/(1.0*m)*Delta[1][i][j]+1.0*theta[1][i][j]*lambda);
	} 
	for(int i=1;i<=4;i++)
    for(int j=0;j<=4;j++)
    {
      if(j==0)
      theta[2][i][j]=1.0*theta[2][i][j]-1.0*alpha/(1.0*m)*Delta[2][i][j];
      else
      theta[2][i][j]=1.0*theta[2][i][j]-1.0*alpha*(1.0/(1.0*m)*Delta[2][i][j]+1.0*theta[2][i][j]*lambda);
	} 
	for(int i=1;i<=2;i++)
    for(int j=0;j<=4;j++)
    {
      if(j==0)
      theta[3][i][j]=1.0*theta[3][i][j]-1.0*alpha/(1.0*m)*Delta[3][i][j];
      else
      theta[3][i][j]=1.0*theta[3][i][j]-1.0*alpha*(1.0/(1.0*m)*Delta[3][i][j]+1.0*theta[3][i][j]*lambda);
	} 
  }
  	   
}

int main()
{
  n=2,m=10,l=2;
  x[1][1]=1,x[1][2]=1,y[1][1]=1,y[1][2]=0;//第一个代表第几个样例,第二个代表第几个特征 
  x[2][1]=1,x[2][2]=2,y[2][1]=1,y[2][2]=0;
  x[3][1]=2,x[3][2]=1,y[3][1]=1,y[3][2]=0;
  x[4][1]=5,x[4][2]=1,y[4][1]=1,y[4][2]=0;
  x[5][1]=6,x[5][2]=1,y[5][1]=1,y[5][2]=0;//前五个为一种 
  
  x[6][1]=1,x[6][2]=5,y[6][1]=0,y[6][2]=1;
  x[7][1]=1,x[7][2]=6,y[7][1]=0,y[7][2]=1;
  x[8][1]=4,x[8][2]=4,y[8][1]=0,y[8][2]=1;
  x[9][1]=4,x[9][2]=5,y[9][1]=0,y[9][2]=1;
  x[10][1]=4,x[10][2]=6,y[10][1]=0,y[10][2]=1;
  
  for(int i=0;i<=10;i++)
  for(int j=0;j<=10;j++)
  for(int k=0;k<=10;k++)
  theta[i][j][k]=0.8*rand();
  train();
  cout<<a[4][1]<<" "<<a[4][2]<<endl;
  while(1)
  {
  	double x1,x2;
  	cin>>x1>>x2;
  	a[1][1]=x1,a[1][2]=x2;
  	a[1][0]=1.0;
  	solve();
  	cout<<a[4][1]<<" "<<a[4][2]<<endl;
  }
  
  
  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值