我与黑夜 2015-11-21 13:05 采纳率: 0%
浏览 2206

BP算法的C语言实现,代码个人测试正确, 但是wrong answer, 求大神指点

#include
#include
#include
#include
#include
//#include "user.h"
#include
#include
#include
#include
#include
#include

#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES

using namespace std;

#define OUT_COUT 8 //输出向量维数
#define IN_COUT 72 //输入向量维数
#define COUT 792 //样本数量
#define NN 99 //单个样本数量

typedef struct { //bp人工神经网络结构
int h; //实际使用隐层数量
//double v[IN_COUT][IN_COUT/3]; //隐藏层权矩阵i,隐层节点最大数量为50
double v[IN_COUT/3][IN_COUT];
//double w[IN_COUT/3][OUT_COUT]; //输出层权矩阵
double w[OUT_COUT][IN_COUT/3];

double b1[IN_COUT/3];
double b2[OUT_COUT];
double x[COUT][IN_COUT];
double y[COUT][OUT_COUT];

double a;          //学习率
double b;          //精度控制参数
int LoopCout;      //最大循环次数

} bp_nn;

double fnet(double net) { //Sigmoid函数,神经网络激活函数
//return 1/(1+exp(-net));
return 2.0/(1+exp(-net))-1.0;
}

int InitBp(bp_nn *bp) { //初始化bp网络

/*printf("请输入隐层节点数,最大数为100:\n");    
scanf_s("%d", &(*bp).h);

printf("请输入学习率:\n");
scanf_s("%lf", &(*bp).a);    //(*bp).a为double型数据,所以必须是lf

printf("请输入精度控制参数:\n");
scanf_s("%lf", &(*bp).b);

printf("请输入最大循环次数:\n");
scanf_s("%d", &(*bp).LoopCout);*/

(*bp).h = 24;
(*bp).a = 0.4;
(*bp).b = 0.0001;
(*bp).LoopCout = 2000;

int i, j;
srand((unsigned)time(NULL));
for (i = 0; i < (*bp).h; i++) 
{
    for (j = 0; j < IN_COUT; j++)
    {
        (*bp).v[i][j] = rand() / (double)(RAND_MAX);  
    }
(*bp).b1[i] = rand()/(double)(RAND_MAX);
}

for (i = 0; i < OUT_COUT; i++) 
{
    for (j = 0; j < (*bp).h; j++)
    {
        (*bp).w[i][j] = rand() / (double)(RAND_MAX); 
    }
(*bp).b2[i] = rand()/(double)(RAND_MAX);
}

return 1;

}

int TrainBp(bp_nn *bp, double x[COUT][IN_COUT], double y[COUT][OUT_COUT]) {
//训练bp网络,样本为x,理想输出为y
double f = (*bp).b; //精度控制参数
double a = (*bp).a; //学习率
int h = (*bp).h; //隐层节点数
//double v[IN_COUT][IN_COUT/3], w[IN_COUT/3][OUT_COUT]; //权矩阵
double v[IN_COUT/3][IN_COUT], w[OUT_COUT][IN_COUT/3]; //权矩阵
double b1[IN_COUT/3],b2[OUT_COUT];
double ChgH[IN_COUT/3], ChgO[OUT_COUT]; //修改量矩阵
double O1[IN_COUT/3], O2[OUT_COUT]; //隐层和输出层输出量
int LoopCout = (*bp).LoopCout; //最大循环次数
int i, j, k, n;
double temp;

for (i = 0; i < h; i++) 
{// 复制结构体中的权矩阵 
    for (j = 0; j < IN_COUT; j++)
    {
        v[i][j] = (*bp).v[i][j];
    }
    b1[i] = (*bp).b1[i];
}

for (i = 0; i < OUT_COUT; i++)
{
    for (j = 0; j < h; j++)
    {
        w[i][j] = (*bp).w[i][j];
    }
    b2[i] = (*bp).b2[i];
}


double e = f + 1;
for (n = 0; e > f && n < LoopCout; n++) 
{ //对每个样本训练网络
    e = 0;
    for (i= 0; i < COUT; i++) 
    { 
        for (k= 0; k < h; k++) 
        {          //计算隐层输出向量
            temp = 0;
            for (j = 0; j < IN_COUT; j++)
                temp = temp + x[i][j] * v[k][j];    
            O1[k] = fnet(temp+(*bp).b1[i]);
        }

        for (k = 0; k < OUT_COUT; k++) 
        { //计算输出层输出向量
            temp = 0;
            for (j = 0; j < h; j++)
                temp = temp + O1[j] * w[k][j];
            O2[k] = fnet(temp+(*bp).b2[k]);
        }

        for (j = 0; j < OUT_COUT; j++)
        {//计算输出层的权修改量    
            ChgO[j] = O2[j] * (1 - O2[j]) * (y[i][j] - O2[j]);
        }

        for (j = 0; j < OUT_COUT ; j++)
        {//计算输出误差
            e = e + (y[i][j] - O2[j]) * (y[i][j] - O2[j]);
        }

        for (j = 0; j < OUT_COUT; j++) 
        {         //计算隐层权修改量
            temp = 0;
            for (k = 0; k < h; k++)
                temp = temp + w[j][k] * ChgO[k];
            ChgH[j] = temp * O1[j] * (1 - O1[j]);
        }

        for (j = 0; j < OUT_COUT; j++)
        {//修改输出层权矩阵
            for (k = 0; k < h; k++)
            {
                w[j][k] = w[j][k] + a * O1[j] * ChgO[k];
            }
        }
        for (j = 0; j < h; j++)
        {
            for (k = 0; k < IN_COUT; k++)
            {
                v[j][k] = v[j][k] + a * x[i][j] * ChgH[k]; 
            }
        }
    }
    if (n % 10 == 0)
        printf("误差 : %f\n", e);
}

printf("总共循环次数:%d\n", n);
printf("调整后的隐层权矩阵:\n");
for (i = 0; i < h; i++) {    
    for (j = 0; j < IN_COUT; j++)
        printf("%f    ", v[i][j]);    
    printf("\n");
}
printf("调整后的输出层权矩阵:\n");
for (i = 0; i < OUT_COUT; i++) {
    for (j = 0; j < h; j++)
        printf("%f    ", w[i][j]);    
    printf("\n");
}
for (i = 0; i < h; i++) 
{//把结果复制回结构体 
    for (j = 0; j < IN_COUT; j++)
    {
        (*bp).v[i][j] = v[i][j];
    }
    (*bp).b1[i] = b1[i];
}
for (i = 0; i < OUT_COUT; i++)
{
    for (j = 0; j < h; j++)
    {
        (*bp).w[i][j] = w[i][j];
    }
    (*bp).b2[i] = b2[i];
}
printf("bp网络训练结束!\n");

return 1;

}

int UseBp(bp_nn *bp) { //使用bp网络
float Input[IN_COUT];
double O1[50];
double O2[OUT_COUT]; //O1为隐层输出,O2为输出层输出
while (1) { //持续执行,除非中断程序
printf("请输入3个数:\n");
int i, j;
for (i = 0; i < IN_COUT; i++)
scanf_s("%f", &Input[i]);
double temp;
for (i = 0; i < (*bp).h; i++) {
temp = 0;
for (j = 0; j < IN_COUT; j++)
temp += Input[j] * (*bp).v[j][i];
O1[i] = fnet(temp-(*bp).b1[i]);
}
for (i = 0; i < OUT_COUT; i++) {
temp = 0;
for (j = 0; j < (*bp).h; j++)
temp += O1[j] * (*bp).w[j][i];
O2[i] = fnet(temp-(*bp).b2[i]);
}
printf("结果: ");
for (i = 0; i < OUT_COUT; i++)
printf("%.3f ", O2[i]);
printf("\n");
}
return 1;
}

void readFP(double x[COUT][IN_COUT],double y[COUT][OUT_COUT])
{
//bp_nn bp1;
ifstream fileinput1;
ifstream fileinput2;
ifstream fileinput3;
ifstream fileinput4;
ifstream fileinput5;
ifstream fileinput6;
ifstream fileinput7;
ifstream fileinput8;

fileinput1.open("emgclose.txt");
fileinput2.open("emgopen.txt");
fileinput3.open("emgext.txt");
fileinput4.open("emgfle.txt");
fileinput5.open("emgsph.txt");
fileinput6.open("emgcyl.txt");
fileinput7.open("emgtri.txt");
fileinput8.open("emgkey.txt");
    for(int m = 0;m< NN;++m)
    {
        for(int i =0;i < IN_COUT;++i)
        {
            fileinput1 >> x[m][i];
        }
    }

    for(int m = NN;m<2*NN;++m)
    {
        for(int i =0;i < IN_COUT;++i)
        {
            fileinput2 >> x[m][i];
        }
    }

    for(int m = 2*NN;m<3*NN;++m)
    {
        for(int i =0;i < IN_COUT;++i)
        {
            fileinput3 >> x[m][i];
        }
    }

    for(int m = 3*NN;m<4*NN;++m)
    {
        for(int i =0;i < IN_COUT;++i)
        {
            fileinput4 >> x[m][i];
        }
    }

    for(int m = 4*NN;m<5*NN;++m)
    {
        for(int i =0;i < IN_COUT;++i)
        {
            fileinput5 >> x[m][i];
        }
    }

    for(int m = 5*NN;m<6*NN;++m)
    {
        for(int i =0;i < IN_COUT;++i)
        {
            fileinput6 >> x[m][i];
        }
    }

    for(int m = 6*NN;m<7*NN;++m)
    {
        for(int i =0;i < IN_COUT;++i)
        {
            fileinput7 >> x[m][i];
        }
    }

    for(int m = 7*NN;m<8*NN;++m)
    {
        for(int i =0;i < IN_COUT;++i)
        {
            fileinput8 >> x[m][i];
        }
    }

fileinput1.close();
fileinput2.close();
fileinput3.close();
fileinput4.close();
fileinput5.close();
fileinput6.close();
fileinput7.close();
fileinput8.close();

ifstream fileinput;
fileinput.open("teach.txt");

for (int m2 = 0; m2 < OUT_COUT; m2++)
    {
        for (int i = 0; i < OUT_COUT; i++)
        {
            fileinput>>y[m2][i];
        }
        for (int j = m2*NN; j < (m2+1)*NN; j++)
        {
            for (int k = 0; k < OUT_COUT; k++)
            {
                y[j][k] = y[m2][k];
            }
        }

    }
for (int i = 0; i < NN; i++)
{
    for (int j = 0; j < OUT_COUT; j++)
    {
        y[i][j] = y[0][j];
    }
}

fileinput.close();

double Mininput[IN_COUT] = {0.0};
double Maxinput[IN_COUT] = {0.0};
//找出训练的数据相应的最大值、最小值,为归一化做准备
for (int i = 0; i < IN_COUT; i++)
    {
        Mininput[i] = Maxinput[i] = x[0][i];
        for (int j = 0; j < COUT; j++)
        {
            Mininput[i] = Mininput[i] < x[j][i]?Mininput[i]:x[j][i];
            Maxinput[i] = Maxinput[i] > x[j][i]?Maxinput[i]:x[j][i];
        }
    }

//归一化处理
for (int i = 0; i < OUT_COUT; i++)
{
    for (int j = 0; j < COUT; j++)
    {
        y[j][i] = 2.0*(y[j][i] - 0.0)/(1.0 - 0.0)-1.0;
    }
}

for (int i = 0; i < IN_COUT; i++)
{
    for (int j = 0; j < COUT; j++)
    {
        //X[i][j] = (X1[i][j] - Mininput[i]+1)/(Maxinput[i] - Mininput[i]+1);
        x[j][i] = 2.0*(x[j][i] - Mininput[i])/(Maxinput[i] - Mininput[i])-1.0;
    }
}

}

int main()
{
/* float x[COUT][IN_COUT] = {{0.8,0.5,0},
{0.9,0.7,0.3},
{1,0.8,0.5},
{0,0.2,0.3},
{0.2,0.1,1.3},
{0.2,0.7,0.8}}; //训练样本
int y[COUT][OUT_COUT] = {{0,1},
{0,1},
{0,1},
{1,0},
{1,0},
{1,0}}; */ //理想输出

bp_nn bp;
readFP(bp.x,bp.y);




InitBp(&bp);                    //初始化bp网络结构
TrainBp(&bp, bp.x, bp.y);             //训练bp神经网络

// UseBp(&bp); //测试bp神经网络

return 1;

}

  • 写回答

1条回答

  • havedream_one 2015-11-21 14:32
    关注

    你试着调整下隐含层节点数,学习率这些参数,其次看看修正权值是否正确
    http://www.hankcs.com/ml/back-propagation-neural-network.html

    评论

报告相同问题?

悬赏问题

  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?