📄 bpclassification.cpp
字号:
{
W_HIDE_TO_OUTPUT[i][j]=(float)(rand() % 1000)/1000-0.5f;//随机生成
}
}
}
void TEST_Init_Weight_Difference(float W_INPUT_TO_HIDE[][NUM_NODE_HIDE_LAYER],float W_HIDE_TO_OUTPUT[][NUM_NODE_OUTPUT_LAYER],BP_Node* bpNode)
{
int i,j;
printf("输入层到隐藏层 权值(随机) 显示:\n");
for(i=0;i<NUM_NODE_INPUT_LAYER;i++)
{
for(j=0;j<NUM_NODE_HIDE_LAYER;j++)
{
printf("%.3f\t",W_INPUT_TO_HIDE[i][j]);
}
printf("\n");
}
printf("隐含层到输出层 权值(随机) 显示:\n");
for(i=0;i<NUM_NODE_HIDE_LAYER;i++)
{
for(j=0;j<NUM_NODE_OUTPUT_LAYER;j++)
{
printf("%.3f\t",W_HIDE_TO_OUTPUT[i][j]);
}
printf("\n");
}
printf("BP网各节点:\n");
for(i=0;i<NUM_NODE_TOTAL;i++)
{
printf("节点 %d :",i);
printf("数据-> %f\t 偏差: %.3f\t 教师值: %f\n",bpNode[i].data,bpNode[i].difference,bpNode[i].expect);
}
}
void Input_Single_Train_Data_To_Input_Layer(TrainData singleTrainData)
{
int i;
for(i=0;i<NUM_NODE_INPUT_LAYER;i++)
{
bpNode[i].data=singleTrainData.feature[i];
}
}
void Input_Teacher_Data_To_Output_Layer(TrainData singleTrainData)
{
int i;
i=0;
if(singleTrainData.nClass==0) //当前样本属于第0类
{
bpNode[INDEX_START_OUTPUT_LAYER].expect=1.0f;
bpNode[INDEX_START_OUTPUT_LAYER+1].expect=0.0f;
bpNode[INDEX_START_OUTPUT_LAYER+2].expect=0.0f;
}
else if(singleTrainData.nClass==1)
{
bpNode[INDEX_START_OUTPUT_LAYER].expect=0.0f;
bpNode[INDEX_START_OUTPUT_LAYER+1].expect=1.0f;
bpNode[INDEX_START_OUTPUT_LAYER+2].expect=0.0f;
}
else if(singleTrainData.nClass==2)
{
bpNode[INDEX_START_OUTPUT_LAYER].expect=0.0f;
bpNode[INDEX_START_OUTPUT_LAYER+1].expect=0.0f;
bpNode[INDEX_START_OUTPUT_LAYER+2].expect=1.0f;
}
else //出错
{
bpNode[INDEX_START_OUTPUT_LAYER].expect=-1.0f;
bpNode[INDEX_START_OUTPUT_LAYER+1].expect=-1.0f;
bpNode[INDEX_START_OUTPUT_LAYER+2].expect=-1.0f;
}
}
void Print_Input_Output_Layer_Before_Train()
{
int i=0;
//输出INPUT_LAYER各节点的值
printf("当前学习样本输入BP网,启动学习之前相关数据 显示:\n");
printf("输入层 显示:\n");
for(i=0;i<NUM_NODE_INPUT_LAYER;i++)
{
printf("节点 %d :",i);
printf("数据-> %f\t 偏差: %.3f\t 教师值: %f\n",bpNode[i].data,bpNode[i].difference,bpNode[i].expect);
}
//输出OUTPUT_LAYER各节点的值
printf("输出层 显示:\n");
for(i=INDEX_START_OUTPUT_LAYER;i<NUM_NODE_TOTAL;i++)
{
printf("节点 %d :",i);
printf("数据-> %f\t 偏差: %.3f\t 教师值: %f\n",bpNode[i].data,bpNode[i].difference,bpNode[i].expect);
}
}
void Train()
{
int i;
i=0;
for(i=0;i<NUM_CLASS*NUM_TRAIN_PER_CLASS;i++)
{
//先将每个学习样本分发到BP网的INPUT_LAYER
Input_Single_Train_Data_To_Input_Layer(train[i]);
//更改BP网OUTPUT_LAYER的教师值
Input_Teacher_Data_To_Output_Layer(train[i]);
//DEBUG
Print_Input_Output_Layer_Before_Train();
//DEBUG
prePropagation();//向前传播
while(!isStop(train[i]))
{
Update_Weight_Difference();
NUM_CURRENT_ITERATE++;
prePropagation();
}
}
}
void prePropagation()
{//功能:向前传播,计算每个隐含层和输出层的各个节点的输出
int i=0;
int j=0;
//处理INPUT_LAYER的输出,其输出即为其data值
for(i=INDEX_START_INPUT_LAYER;i<INDEX_START_HIDE_LAYER+NUM_NODE_INPUT_LAYER;i++)
{
bpNode[i].output=bpNode[i].data;
}
//处理HIDE_LAYER的输入与输出
for(i=INDEX_START_HIDE_LAYER;i<INDEX_START_HIDE_LAYER+NUM_NODE_HIDE_LAYER;i++)
{
for(j=INDEX_START_INPUT_LAYER;j<INDEX_START_INPUT_LAYER+NUM_NODE_INPUT_LAYER;j++)
{
bpNode[i].input+=(bpNode[j].output*W_INPUT_TO_HIDE[j][i]);
}
bpNode[i].input+=bpNode[i].difference;//HIDE_LAYER当前节点的纯输入
bpNode[i].output=(float)(1/(1+exp(bpNode[i].input)));//HIDE_LAYER当前节点的纯输出
}
//处理OUTPUT_LAYER的输入与输出
for(i=INDEX_START_OUTPUT_LAYER;i<INDEX_START_OUTPUT_LAYER+NUM_NODE_OUTPUT_LAYER;i++)
{
for(j=INDEX_START_HIDE_LAYER;j<INDEX_START_HIDE_LAYER+NUM_NODE_HIDE_LAYER;j++)
{
bpNode[i].input+=(bpNode[j].output*W_HIDE_TO_OUTPUT[j][i]);
}
bpNode[i].input+=bpNode[j].difference;
bpNode[i].output=(float)(1/(1+exp(bpNode[i].input)));
}
}
void CalcErr()
{//从OUTPUT_LAYER-->HIDE_LAYER依次计算各节点的
int i,j;
i=0;
j=0;
//OUTPUT_LAYER各节点的误差
for(i=INDEX_START_OUTPUT_LAYER;i<INDEX_START_OUTPUT_LAYER+NUM_NODE_OUTPUT_LAYER;i++)
{
bpNode[i].err=bpNode[i].output*(1-bpNode[i].output)*(bpNode[i].expect-bpNode[i].output);
}
//HIDE_LAYER各节点的误差
for(i=INDEX_START_HIDE_LAYER;i<INDEX_START_HIDE_LAYER+NUM_NODE_HIDE_LAYER;i++)
{
for(j=INDEX_START_OUTPUT_LAYER;j<INDEX_START_OUTPUT_LAYER+NUM_NODE_OUTPUT_LAYER;j++)
{
bpNode[i].err+=(bpNode[j].err*W_HIDE_TO_OUTPUT[i][j]);
}
bpNode[i].err=bpNode[i].output*(1-bpNode[i].output)*bpNode[i].err;
}
}
void Update_Weight_Difference()
{
int i,j;
i=0;
j=0;
//更新权值时要逆向
//更新OUTPUT_LAYER到HIDE_LAYER之间的权值
for(i=INDEX_START_OUTPUT_LAYER;i<INDEX_START_OUTPUT_LAYER+NUM_NODE_OUTPUT_LAYER;i++)
{
for(j=INDEX_START_HIDE_LAYER;j<INDEX_START_HIDE_LAYER+NUM_NODE_HIDE_LAYER;j++)
{//这里映射的概念
int tempJ=j-NUM_NODE_INPUT_LAYER;
int tempI=i-NUM_NODE_INPUT_LAYER-NUM_NODE_HIDE_LAYER;
W_HIDE_TO_OUTPUT[tempJ][tempI]=W_HIDE_TO_OUTPUT[tempJ][tempI]+(float)TRAIN_RATE*bpNode[i].err*bpNode[j].output;
}
}
//更新INPUT_LAYER到HIDE_LAYER之间的权值
for(i=INDEX_START_INPUT_LAYER;i<INDEX_START_INPUT_LAYER+NUM_NODE_INPUT_LAYER;i++)
{
for(j=INDEX_START_HIDE_LAYER;j<INDEX_START_HIDE_LAYER+NUM_NODE_HIDE_LAYER;j++)
{
int tempI=i;
int tempJ=j-NUM_NODE_INPUT_LAYER;
W_INPUT_TO_HIDE[tempJ][tempI]=W_INPUT_TO_HIDE[tempJ][tempI]+(float)TRAIN_RATE*bpNode[i].err*bpNode[j].output;
}
}
//更新偏差,逆向
//更新OUTPUT_LAYER各节点的偏差
for(i=INDEX_START_OUTPUT_LAYER;i<INDEX_START_OUTPUT_LAYER+NUM_NODE_OUTPUT_LAYER;i++)
{
bpNode[i].difference=bpNode[i].difference+(float)TRAIN_RATE*bpNode[i].err;
}
//更新HIDE_LAYER各节点的偏差
for(i=INDEX_START_HIDE_LAYER;i<INDEX_START_HIDE_LAYER+NUM_NODE_HIDE_LAYER;i++)
{
bpNode[i].difference=bpNode[i].difference+(float)TRAIN_RATE*bpNode[i].err;
}
}
bool isStop(TrainData current_Train_Data)
{//功能:判断迭代是否需要停止
bool result;
float diff;
result=false;
diff=0.0f;
if(NUM_CURRENT_ITERATE==NUM_MAX_ITERATE)
{
return true;
}
//BP网络输出与教师值的偏差是否满足要求
if(current_Train_Data.nClass==0)
{
diff=(float)fabs(bpNode[INDEX_START_OUTPUT_LAYER].expect-(float)fabs(bpNode[INDEX_START_OUTPUT_LAYER].output));
}
else if(current_Train_Data.nClass==1)
{
diff=(float)fabs(bpNode[INDEX_START_OUTPUT_LAYER+1].expect-(float)fabs(bpNode[INDEX_START_OUTPUT_LAYER+1].output));
}
else if(current_Train_Data.nClass==2)
{
diff=(float)fabs(bpNode[INDEX_START_OUTPUT_LAYER+2].expect-(float)fabs(bpNode[INDEX_START_OUTPUT_LAYER+2].output));
}
result=(diff<=THRESHOLD);
return result;
}
void printTrainResult()
{
int i=0;
//INPUT_LAYER
printf("训练结束后:\n");
printf("--------------------------\n");
printf("输入层 显示:\n");
for(i=INDEX_START_INPUT_LAYER;i<INDEX_START_INPUT_LAYER+NUM_NODE_INPUT_LAYER;i++)
{
printf("Data: %.3f\t Diff:%.3f\t Expect:%.3f\t Err:%.3f\t Input:%f\t Output:%f\n",bpNode[i].data,bpNode[i].difference,bpNode[i].err,bpNode[i].expect,bpNode[i].input,bpNode[i].output);
}
printf("隐含层 显示:\n");
for(i=INDEX_START_HIDE_LAYER;i<INDEX_START_HIDE_LAYER+NUM_NODE_HIDE_LAYER;i++)
{
printf("Data: %.3f\t Diff:%.3f\t Expect:%.3f\t Err:%.3f\t Input:%f\t Output:%f\n",bpNode[i].data,bpNode[i].difference,bpNode[i].err,bpNode[i].expect,bpNode[i].input,bpNode[i].output);
}
printf("输出层 显示:\n");
for(i=INDEX_START_OUTPUT_LAYER;i<INDEX_START_OUTPUT_LAYER+NUM_NODE_OUTPUT_LAYER;i++)
{
printf("Data: %.3f\t Diff:%.3f\t Expect:%.3f\t Err:%.3f\t Input:%f\t Output:%f\n",bpNode[i].data,bpNode[i].difference,bpNode[i].err,bpNode[i].expect,bpNode[i].input,bpNode[i].output);
}
}
void Test()
{
int i=0;
int j=0;
bool classA=false;
bool classB=false;
bool classC=false;
for(i=0;i<NUM_CLASS*NUM_TEST_PER_CLASS;i++)
{
for(j=INDEX_START_OUTPUT_LAYER;j<INDEX_START_OUTPUT_LAYER+NUM_NODE_OUTPUT_LAYER;j++)
{
bpNode[i].output=0.0f;
}
Input_Single_Train_Data_To_Input_Layer(train[i]);
prePropagation();
//依据OUTPUT_LAYER的各节点的值来修改test[i]
classA=((float)fabs(bpNode[INDEX_START_OUTPUT_LAYER].expect-(float)fabs(bpNode[INDEX_START_OUTPUT_LAYER].output))<=THRESHOLD);
classB=((float)fabs(bpNode[INDEX_START_OUTPUT_LAYER+1].expect-(float)fabs(bpNode[INDEX_START_OUTPUT_LAYER+1].output))<=THRESHOLD);
classC=((float)fabs(bpNode[INDEX_START_OUTPUT_LAYER+2].expect-(float)fabs(bpNode[INDEX_START_OUTPUT_LAYER+2].output))<=THRESHOLD);
if(classA)
{
test[i].result=0;
}
if(classB)
{
test[i].result=1;
}
if(classC)
{
test[i].result=2;
}
if(test[i].nClass==test[i].result)
{
test[i].Right=true;
}
else
{
test[i].Right=false;
}
}
}
void PrintTestResult()
{
int i=0;
printf("-----------------------\n");
for(i=0;i<NUM_CLASS*NUM_TEST_PER_CLASS;i++)
{
printf("测试样本编号: %d \t",i);
printf("实际结果: %d\t 测试结果: %d\n",test[i].nClass,test[i].result);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -