📄 bp1.2.cpp
字号:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define Learn 0.3 //学习率
#define err 0.00001 //最大误差
typedef struct LNode //存储实例和期望值
{
float x1;
float x2;
float y1;
float y2;
struct LNode *next;
}LNode, *LinkList;
void readexample(LinkList *L); //从文件读取实例
float MAXE(float E[],int e); //求最大误差
void Print_L(LinkList *L); //输出实例
void See_emax(float EMAX[]); //查看某次学习最大误差
void initiarray(float w1[][4],float w2[][4],float w3[][3]); //随机初始权矩阵
void initiarray2(float w1[][4],float w2[][4],float w3[][3]); //显示初始权矩阵
void printarray(float w1[][4],float w2[][4],float w3[][3]); //输出权矩阵
void learn(LinkList L, float w1[][4],float w2[][4],float w3[][3],float EMAX[]); //学习实例
void assess(float w1[][4],float w2[][4],float w3[][3]); //模糊评判
void main()
{
LinkList L= (LinkList)malloc(sizeof(LNode));
float w1[3][4],w2[4][4],w3[4][3],EMAX[200000];
readexample(&L);
// Print_L(&L);
// initiarray(w1,w2,w3); //随机初始权矩阵
initiarray2(w1,w2,w3); //显示初始权矩阵
// printarray(w1,w2,w3);
// printf("---------------\n");
learn(L, w1,w2,w3,EMAX);
assess(w1,w2,w3);
See_emax(EMAX);
printarray(w1,w2,w3);
}
void learn(LinkList L, float w1[][4],float w2[][4],float w3[][3],float EMAX[])
{
int i,j,e;
long t=1;
unsigned long a=0,count=0;
float MAX=1.0;
float E[41],E2[4],E3[4],E4[3],o1[3],o2[4],o3[4],o4[3];
LinkList p;
while(MAX>err)
{
e=1;
p=L->next;
while(p)
{
o1[1]=p->x1;
o1[2]=p->x2;
for(i=1;i<=3;i++)
o2[i]=1/(1+exp(-(w1[1][i]*o1[1]+w1[2][i]*o1[2]))); //第2层输出
for(i=1;i<=3;i++)
o3[i]=1/(1+exp(-(w2[1][i]*o2[1]+w2[2][i]*o2[2]+w2[3][i]*o2[3]))); //第3层输出
for(i=1;i<=2;i++)
o4[i]=1/(1+exp(-(w3[1][i]*o3[1]+w3[2][i]*o3[2]+w3[3][i]*o3[3]))); //第4层输出
E4[1]=o4[1]-p->y1; //计算每次输出误差
E[e++]=fabs(E4[1]); //存放每次误差
E4[2]=o4[2]-p->y2;
E[e++]=fabs(E4[2]);
for(i=1;i<=3;i++)
E3[i]=o3[i]*(1-o3[i])*(w3[i][1]*E4[1]+w3[i][2]*E4[2]); //第3层误差
for(i=1;i<=3;i++)
E2[i]=o2[i]*(1-o2[i])*(w2[i][1]*E3[1]+w2[i][2]*E3[2]+w2[i][3]*E3[3]); //第2层误差
for(i=1;i<=3;i++)
for(j=1;j<=2;j++)
w3[i][j]=w3[i][j]-Learn*E4[j]*o3[i]; //修改W3矩阵
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
w2[i][j]=w2[i][j]-Learn*E3[j]*o2[i]; //修改W2矩阵
for(i=1;i<=2;i++)
for(j=1;j<=3;j++)
w1[i][j]=w1[i][j]-Learn*E2[j]*o1[i]; //修改W1矩阵
p=p->next;
} //while(p)
count++; // 学习遍数+1
MAX=MAXE(E,e); //计算最大误差
EMAX[t++]=MAX;
}//while(MAX>err)
printf("学习遍数count=%ld\n",count);
}
void readexample(LinkList *L) //从指定文件读取实例
{
FILE *fp;
LinkList p=*L,r;
if((fp=fopen("c:\\bp1.txt","r"))==NULL)
{
printf("Open file error!\n");
exit(0);
}
while(!feof(fp))
{
r=(LinkList)malloc(sizeof(LNode));
r->next=NULL;
p->next=r;
fscanf(fp,"%f%f%f%f",&r->x1,&r->x2,&r->y1,&r->y2);
p=r;
}
fclose(fp);
}
void initiarray(float w1[][4],float w2[][4],float w3[][3]) //随机初始权矩阵
{
int i,j;
for(i=1;i<=2;i++)
for(j=1;j<=3;j++)
w1[i][j]=rand()%100*1.0/100;
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
w2[i][j]=rand()%100*1.0/100;
for(i=1;i<=3;i++)
for(j=1;j<=2;j++)
w3[i][j]=rand()%100*1.0/100;
}
void initiarray2(float w1[][4],float w2[][4],float w3[][3]) //显示初始权矩阵
{
FILE *fp;
int i,j;
if((fp=fopen("c:\\bp11.txt","r"))==NULL)
{
printf("Open file error!\n");
exit(0);
}
for(i=1;i<=2;i++)
for(j=1;j<=3;j++)
fscanf(fp,"%f",&w1[i][j]);
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
fscanf(fp,"%f",&w2[i][j]);
for(i=1;i<=3;i++)
for(j=1;j<=2;j++)
fscanf(fp,"%f",&w3[i][j]);
fclose(fp);
}
float MAXE(float E[21],int e) //返回最大误差值
{
float max=0;
int i;
for(i=1;i<e;i++)
if(max<E[i])
max=E[i];
return max;
}
void printarray(float w1[][4],float w2[][4],float w3[][3]) //输出权矩阵
{
int i,j;
printf("最后权矩阵如下:\n");
for(i=1;i<=2;i++)
for(j=1;j<=3;j++)
printf("w1[%d][%d]=%f ",i,j,w1[i][j]);
printf("\n");
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
printf("w2[%d][%d]=%f ",i,j,w2[i][j]);
printf("\n");
for(i=1;i<=3;i++)
for(j=1;j<=2;j++)
printf("w3[%d][%d]=%f ",i,j,w3[i][j]);
printf("\n");
}
void Print_L(LinkList *L) //输出读取的实例
{
LinkList p=(*L)->next;
if(!p)
printf("链表创建为空");
while(p)
{
printf("%f %f %f %f\n",p->x1,p->x2,p->y1,p->y2);
p=p->next;
}
printf("\n");
}
void See_emax(float EMAX[])
{
long i;
printf("输入学习的遍数:");
scanf("%d",&i);
printf("EMAX[%ld]=%f \n",i,EMAX[i]);
}
void assess(float w1[][4],float w2[][4],float w3[][3])
{
int i;
float o1[3],o2[4],o3[4],o4[3],b[3];
printf("输入实例x1,x2:");
scanf("%f%f",&o1[1],&o1[2]);
for(i=1;i<=3;i++)
o2[i]=1/(1+exp(-(w1[1][i]*o1[1]+w1[2][i]*o1[2]))); //第2层输出
for(i=1;i<=3;i++)
o3[i]=1/(1+exp(-(w2[1][i]*o2[1]+w2[2][i]*o2[2]+w2[3][i]*o2[3]))); //第3层输出
for(i=1;i<=2;i++)
o4[i]=1/(1+exp(-(w3[1][i]*o3[1]+w3[2][i]*o3[2]+w3[3][i]*o3[3]))); //第4层输出
printf("y1=%f,y2=%f\n",o4[1],o4[2]);
printf("对象X的评价:");
for(i=1;i<=2;i++)
{
b[i]=(float)((int)(o4[i]*10+0.5))/10.0;
switch ((int)(10*b[i]))
{
case 10: printf("“肯定是”"); break;
case 9 : printf("“几乎是”"); break;
case 8 : printf("“极是”"); break;
case 7 : printf("“很是”"); break;
case 6 : printf("“相当是”"); break;
case 5 : printf("“差不多是”"); break;
case 4 : printf("“比较像是”"); break;
case 3 : printf("“有些像是”"); break;
case 2 : printf("“有点像是”"); break;
case 1 : printf("“稍稍像是”"); break;
case 0 : printf("“肯定不是”"); break;
default: break;
}
if(i==1) printf("属于R1类,");
if(i==2) printf("属于R2类。");
}
printf("\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -