數據挖掘之神經網絡SOM算法


/*
神經網絡SOM算法思想:分為輸入層和競爭層,輸入層就是樣本的輸入,假如我現在有5個樣本A,B,C,D,E,他們是5維向量,競爭層是10*10的二維平面,相當於100個神經元,這些神經元也是5維向量,這些神經元對輸入向量進行競爭,最后只有一個神經元獲勝,越是與輸入向量相似,競爭力越強,假如現在位於(7,8)的神經元最相似,它有權力去修改以它為中心的神經元的值,越靠近它的神經元影響越大,越是接近獲勝神經元。假如樣本A對應的獲勝神經元是(7,8),B對應的獲勝神經元是(6,8),因為這兩個神經元靠得很近,所以樣本A和B很相似。如果C對應的獲勝神經元是(1,1),與另外兩個距離比較遠,所以C與A,B相似度較低。
*/
#include<fstream.h> #include<iomanip.h> #include<stdio.h> #include<cstdlib.h> #include<math.h> using namespace std; #define InputLayerNum 35 #define OutputLayerRow 8 #define OutputLayerColumn 12 #define total_iteration_Num 80 #define error_limit 0.0001 #define efficiency 0.9 int i,j,k,l,m,n; int inputMode[26][7][5]; double weight[OutputLayerRow*OutputLayerColumn][InputLayerNum]; int current_iteration_num=0; double study_efficiency=efficiency; double distance[OutputLayerRow*OutputLayerColumn]; int neighbor_width=OutputLayerColumn; int neighbor_height=OutputLayerRow; int row[OutputLayerRow],column[OutputLayerColumn]; int flag[OutputLayerRow][OutputLayerColumn]; int temp_row,temp_column; int winner_row,winner_column; double min_distance=1000.0; /****************************************************/ //該函數初始化距離變量為0,初始化保存生勝出節點的位置的變量 /****************************************************/ void init_distance(){ for(i=0;i<OutputLayerRow;i++) for(j=0;j<OutputLayerColumn;j++) distance[i*OutputLayerColumn+j]=0.0; } /****************************************************/ //該函數用於計算歐氏距離,並找到獲勝神經元 /****************************************************/ void eula_distance(){ int ttLow,ttUp,ppLow,ppUp; ttLow=winner_column-neighbor_width/2; ttUp=winner_column+neighbor_width/2; ppLow=winner_row-neighbor_height/2; ppUp=winner_row+neighbor_height/2; if(ttLow<0) ttLow=0; if(ttUp>=OutputLayerColumn) ttUp=OutputLayerColumn-1; if(ppLow<0) ppLow=0; if(ppUp>=OutputLayerRow) ppUp=OutputLayerRow-1; for(i=ppLow;i<=ppUp;i++) for(j=ttLow;j<=ttUp;j++){ if(!(flag[i][i]==100)){ for(m=0;m<7;m++) for(n=0;n<5;n++) distance[i*OutputLayerColumn+j]+=pow((inputMode[l][m][n]- weight[i*OutputLayerColumn+j][m*5+n]),2); if(distance[i*OutputLayerColumn+j]<min_distance){ min_distance=distance[i*OutputLayerColumn+j]; temp_row=i; temp_column=j; } } } if(current_iteration_num>0){ if(min_distance<=error_limit){ row[temp_row]=temp_row; row[temp_column]=temp_column; flag[temp_row][temp_column]=100; } } } /****************************************************/ //調整權值 /****************************************************/ void weight_change(){ int ttLow,ttUp,ppLow,ppUp; winner_row=temp_row; winner_column=temp_column; ttLow=winner_column-neighbor_width/2; ttUp=winner_column+neighbor_width/2; ppLow=winner_row-neighbor_height/2; ppUp=winner_row+neighbor_height/2; if(ttLow<0) ttLow=0; if(ttUp>=OutputLayerColumn) ttUp=OutputLayerColumn-1; if(ppLow<0) ppLow=0; if(ppUp>=OutputLayerRow) ppUp=OutputLayerRow-1; for(i=ppLow;i<=ppUp;i++) for(j=ttLow;j<=ttUp;j++){ if(!(flag[i][j]==100)){ for(m=0;m<7;m++) for(n=0;n<5;n++) weight[i*OutputLayerColumn+j][m*5+n]+= study_efficiency*(inputMode[l][m][n]-weight[i*OutputLayerColumn+j][m*5+n]); } } } /****************************************************/ //調整學習效率以及獲勝節點的鄰域大小 /****************************************************/ void paraChange(){ study_efficiency=study_efficiency*(1.0-((double)current_iteration_num)/total_iteration_Num); neighbor_width=(int)(neighbor_width*(1.0-((double)current_iteration_num)/total_iteration_Num)); neighbor_height=(int)(neighbor_height*(1.0-((double)current_iteration_num)/total_iteration_Num)); } /****************************************************/ //該函數用於將所有輸入模式從文件中讀入,並存放在數組inputMode中 //同時進行權值的初始化,采用隨機賦值的方法 /****************************************************/ void initialize(){ for(i=0;i<OutputLayerRow;i++) row[i]=100; for(j=0;j<OutputLayerColumn;j++) column[j]=100; for(i=0;i<OutputLayerRow;i++) for(j=0;j<OutputLayerColumn;j++) flag[i][j]=0; FILE *pf=fopen("輸入數據.txt","a+"); if(pf==NULL){ cout<<"Can not input file!\n"; exit(0); } for(i=0;i<26;i++) for(j=0;j<7;j++) for(k=0;k<5;k++) fscanf(pf,"%d",&inputMode[i][j][k]); //用於測試是否能夠正確讀入輸入模式 char character[26]; for(i=0;i<26;i++) character[i]=(65+i); ofstream mode("輸出數據.txt",ios::out); for(i=0;i<26;i++){ mode<<character[i]<<'\n'<<endl; for(j=0;j<7;j++){ for(k=0;k<5;k++) mode<<inputMode[i][j][k]<<" "; mode<<"\n"; } mode<<"\n\n\n"; } //權值隨機初始化,采用隨機賦值的方法 for(i=0;i<OutputLayerRow;i++) for(j=0;j<OutputLayerColumn;j++) for(k=0;k<InputLayerNum;k++) weight[i*OutputLayerColumn+j][k]=(double)(rand()%101)/100.0; //用於測試是否能夠正確初始化權值 ofstream quan("初始權值.txt",ios::out); for(i=0;i<OutputLayerRow;i++) for(j=0;j<OutputLayerColumn;j++){ quan<<"\n\n\n"<<"Node["<<i+1<<"]["<<j+1<<"]"<<"\n"; for(k=0;k<InputLayerNum;k++){ if(k%5==0) quan<<"\n"; quan<<setprecision(6)<<setiosflags(ios::fixed)<<weight[i*OutputLayerColumn+j][k]<<" "; } quan<<"\n\n\n"; } } int main(){ int iteration_numbers[26]; int total_num=0; char character[26]; void test_netWork_1(); void test_netWork_2(); for(l=0;l<26;l++){ iteration_numbers[l]=0; character[l]=(65+l); } initialize(); for(l=0;l<26;l++){ winner_row=OutputLayerRow/2; winner_column=OutputLayerColumn/2; while(current_iteration_num<total_iteration_Num){//迭代次數控制 init_distance(); eula_distance(); weight_change(); if(min_distance<=error_limit) break; ++current_iteration_num; paraChange(); } iteration_numbers[l]=current_iteration_num+1; neighbor_width=OutputLayerColumn; //修改鄰域的寬度 neighbor_height=OutputLayerRow; //修改鄰域的高度 study_efficiency=efficiency; //學習率重置 current_iteration_num=0; //重置迭代次數 min_distance=1000.0; //重置最小距離 } /***********************************/ //輸出部分 /***********************************/ for(l=0;l<26;l++) total_num+=iteration_numbers[l]; ofstream iteration_num("迭代次數.txt",ios::out); for(l=0;l<26;l++){ iteration_num<<character[l]<<"迭代"<<iteration_numbers[l]<<"次!\n"<<endl; if(l==25) iteration_num<<"整個訓練過程共迭代"<<total_num<<"次!\n"<<endl; } ofstream all_weight("訓練后所有權值.txt",ios::out); ofstream winner_weight("訓練后勝出權值.txt",ios::out); for(i=0;i<OutputLayerRow;i++) for(j=0;j<OutputLayerColumn;j++){ printf("\n\n\n"); all_weight<<"\n\n\n"<<"Node["<<i+1<<"]["<<j+1<<"]"<<"\n"; for(k=0;k<InputLayerNum;k++){ if(k%5==0){ printf("\n"); all_weight<<"\n"; } if(weight[i*OutputLayerColumn+j][k]>0.9999999) weight[i*OutputLayerColumn+j][k]=1.0; if(weight[i*OutputLayerColumn+j][k]<0.0000001) weight[i*OutputLayerColumn+j][k]=0.0; printf("%f ",weight[i*OutputLayerColumn+j][k]); all_weight<<setprecision(8)<<setiosflags(ios::fixed)<<weight[i*OutputLayerColumn+j][k]<<" "; } } ofstream winner_node("獲勝節點.txt",ios::out); for(i=0;i<OutputLayerRow;i++) for(j=0;j<OutputLayerColumn;j++){ if(flag[i][j]==100){ //獲勝節點 printf("\n\n\n"); winner_weight<<"\n\n\n"<<"Node["<<i+1<<"]["<<j+1<<"]"<<"\n"; for(k=0;k<InputLayerNum;k++){ if(k%5==0){ printf("\n"); winner_weight<<"\n"; } if(weight[i*OutputLayerColumn+j][k]>0.9999999) weight[i*OutputLayerColumn+j][k]=1.0; if(weight[i*OutputLayerColumn+j][k]<0.0000001) weight[i*OutputLayerColumn+j][k]=0.0; printf("%f ",weight[i*OutputLayerColumn+j][k]); winner_weight<<setprecision(8)<<setiosflags(ios::fixed)<<weight[i*OutputLayerColumn+j][k]<<" "; } winner_node<<"Node["<<i+1<<"]["<<j+1<<"]"<<endl; } } printf("\n"); test_netWork_1(); test_netWork_2(); return 0; } void test_netWork_1(){ ofstream test1("標准測試.txt",ios::out); char character[26]; for(i=0;i<26;i++) character[i]=(65+i); for(l=0;l<26;l++){ for(i=0;i<OutputLayerRow;i++) for(j=0;j<OutputLayerColumn;j++) distance[i*OutputLayerColumn+j]=0.0; min_distance=1000; for(i=0;i<OutputLayerRow;i++) for(j=0;j<OutputLayerColumn;j++){ for(m=0;m<7;m++) for(n=0;n<5;n++) distance[i*OutputLayerColumn+j]+=pow(inputMode[l][m][n]-weight[i*OutputLayerColumn+j][m*5+n],2); if(distance[i*OutputLayerColumn+j]<min_distance){ min_distance=distance[i*OutputLayerColumn+j]; temp_row=i; temp_column=j; } } test1<<character[l]<<"'s winner is Node["<<temp_row+1<<"]["<<temp_column+1<<"]"<<endl<<endl; } } /****************************************************/ //利用非標准數據測試訓練后的網絡 /****************************************************/ void test_netWork_2(){ ofstream test2("非標准測試.txt",ios::out); char character[26]; FILe *pf=fopen("非標准數據測試.txt","a+"); if(pf==NULL){ cout<<"Can not open input file!\n"; exit(0); } for(i=0;i<26;i++) for(j=0;j<7;j++) for(k=0;k<5;k++) fscanf(pf,"%d",&inputMode[i][j][k]); for(i=0;i<26;i++) character[i]=(65+i); for(l=0;l<26;l++){ for(i=0;i<OutputLayerRow;i++) for(j=0;j<OutputLayerColumn;j++) distance[i*OutputLayerColumn+j]=0.0; min_distance=1000; for(i=0;i<OutputLayerRow;i++) for(j=0;j<OutputLayerColumn;j++){ for(m=0;m<7;m++) for(n=0;n<5;n++) distance[i*OutputLayerColumn+j]+=pow(inputMode[l][m][n]-weight[i*OutputLayerColumn+j][m*5+n],2); if(distance[i*OutputLayerColumn+j]<min_distance){ min_distance=distance[i*OutputLayerColumn+j]; temp_row=i; temp_column=j; } } test2<<character[l]<<"'s winner is Node["<<temp_row+1<<"]["<<temp_column+1<<"]"<<endl<<endl; } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM