// BP演算法.cpp : 定義控制台應用程式的進入點。<br />//</p><p>#include "stdafx.h"<br />#include "iostream"<br />#include <string.h><br />#include <stdio.h><br />#include <stdlib.h><br />#include <math.h><br />#include <time.h></p><p>#define N4//列,N維輸入資料<br />#define M214//行,M個樣本記錄<br />#define TrainCount 150//訓練樣本個數,總樣本的75%<br />#define TestCount 64//測試樣本個數,總樣本的25%</p><p>FILE *sample=fopen("sample.txt","r");//樣本資料所在檔案<br />FILE *trainData=fopen("trainData.txt","w+");//訓練資料所在檔案<br />FILE *test=fopen("test.txt","w+");//測試資料所在檔案<br />FILE *expectation=fopen("expectation.txt","w+");//期望輸出的資料所在檔案<br />FILE *testActual=fopen("testActual.txt","w+");//測試集資料中待預測資料的實際值<br />FILE *minmax=fopen("minmax.txt","w+");//最大值和最小值</p><p>float A[M][N]={0};//樣本資料,N維,初始化為0<br />float Train[TrainCount][N]={0};//參與訓練的樣本<br />float Test[TestCount][N]={0};//參與測試的樣本</p><p>float Max[N];//每維資料的最大值,不初始化<br />float Min[N];//每維資料的最小值,不初始化</p><p>float Weight[M][N];//權重值</p><p>void readSample()//讀取樣本資料<br />{<br />if(sample==0)<br />{<br />printf("找不到樣本資料");<br />return;<br />}<br />for (int i=0;i<M;i++)<br />{<br />for (int j=0;j<N;j++)<br />{<br />fscanf(sample,"%f",&A[i][j]);<br />}<br />}<br />printf("樣本資料讀取完畢/n");<br />}</p><p>void findMinMax()//找最大值和最小值<br />{<br />for (int i=0;i<N;i++)//對於每一維<br />{<br />Min[i]=A[0][i];//假設最小值為第一個資料<br />Max[i]=A[0][i];//假設最大值為第一個資料</p><p>for (int j=0;j<M;j++)//對於每一條記錄<br />{<br />if (Max[i]<A[j][i])//注意下標,調換了<br />{<br />Max[i]=A[j][i];<br />}<br />if (Min[i]>A[j][i])<br />{<br />Min[i]=A[j][i];<br />}<br />}<br />fprintf(minmax,"/n第%d維資料,最小值%f ,最大值%f ",i,Min[i],Max[i]);<br />}<br />printf("最大值最小值尋找完畢/n");<br />}</p><p>void reflect()//樣本資料歸一化<br />{<br />for (int i=0;i<N;i++)//每一維資料都需要歸一化<br />{<br />for (int j=0;j<M;j++)//每一條記錄<br />{<br />A[j][i]=(A[j][i]-Min[i])/(Max[i]-Min[i]);<br />}<br />}<br />printf("樣本資料歸一化完畢/n");<br />}</p><p>void setTrain()//設定訓練樣本,隨機產生總體樣本容量的75%<br />{<br />srand((unsigned)time(NULL));//產生一個以目前時間為種子的隨機數</p><p>for (int j=0;j<N;j++)//對於每一維資料,都需要訓練樣本<br />{<br />for (int i=0;i<TrainCount;i++)<br />{<br />int r=rand()%M;//產生0-99之間的隨機數。注意:有可能重複!<br />Train[i][j]=A[r][j];<br />//printf("隨機數是%d/n",r);<br />}<br />}<br />printf("訓練樣本提取完畢/n");<br />}</p><p>void saveTrain()//儲存訓練集到trainData.txt<br />{<br />if(trainData==0)<br />{<br />printf("找不到樣本資料檔案");<br />return;<br />}<br />for (int i=0;i<TrainCount;i++)<br />{<br />for (int j=0;j<N;j++)<br />{<br />fprintf(trainData,"%f ",Train[i][j]);<br />}<br />fprintf(trainData,"/n");<br />}<br />printf("樣本資料寫入完畢/n");<br />}</p><p>void saveExpectation()//儲存期望輸出資料到expectation.txt<br />{<br />if(expectation==0)<br />{<br />printf("找不到樣本資料檔案");<br />return;<br />}<br />for (int i=0;i<TrainCount;i++)<br />{<br />fprintf(expectation,"%f /n",Train[i][N-1]);//最後一維是溶解氧資料<br />}<br />printf("期望輸出資料寫入完畢/n");<br />}<br />void setTest()//設定測試樣本,隨機產生總體樣本容量的25%<br />{<br />srand((unsigned)time(NULL));//產生一個以目前時間為種子的隨機數</p><p>for (int j=0;j<N;j++)//對於每一維資料,都需要訓練樣本<br />{<br />for (int i=0;i<TestCount;i++)<br />{<br />int r=rand()%M;//產生0-99之間的隨機數。注意:有可能重複!<br />Test[i][j]=A[r][j];<br />//printf("隨機數是%d/n",r);<br />}<br />}<br />printf("訓練樣本提取完畢/n");<br />}</p><p>void saveTest()//儲存測試集到test.txt<br />{<br />if(test==0)<br />{<br />printf("找不到測試資料檔案");<br />return;<br />}<br />for (int i=0;i<TestCount;i++)<br />{<br />for (int j=0;j<N;j++)<br />{<br />fprintf(test,"%f ",Test[i][j]);<br />}<br />fprintf(test,"/n");<br />}<br />printf("測試資料寫入完畢/n");<br />}</p><p>void saveTestActual()//儲存測試集中的實際值到testActual.txt<br />{<br />if(testActual==0)<br />{<br />printf("找不到測試資料中待測參數的檔案");<br />return;<br />}<br />for (int i=0;i<TestCount;i++)<br />{<br />fprintf(testActual,"%f /n",Test[i][N-1]);//溶解氧在最後一列<br />}<br />printf("測試資料中待測參數的檔案寫入完畢/n");<br />}</p><p>void outputSample()//輸出樣本資料<br />{<br />printf("樣本資料如下:/n");<br />for (int i=0;i<M;i++)<br />{<br />for (int j=0;j<N;j++)<br />{<br />printf("%f, ",A[i][j]);<br />}<br />printf("/n");<br />}<br />}</p><p>void outputTrain()//輸出訓練樣本<br />{<br />printf("訓練資料如下:/n");<br />for (int i=0;i<TrainCount;i++)<br />{<br />for (int j=0;j<N;j++)<br />{<br />printf("%f, ",Train[i][j]);<br />}<br />printf("/n");<br />}<br />}</p><p>void outputTest()//輸出測試樣本<br />{<br />printf("測試資料如下:/n");<br />for (int i=0;i<TestCount;i++)<br />{<br />for (int j=0;j<N;j++)<br />{<br />printf("%f, ",Test[i][j]);<br />}<br />printf("/n");<br />}<br />}<br />int _tmain(int argc, _TCHAR* argv[])<br />{<br />readSample();//讀取樣本<br />findMinMax();//找到各維的最大最小值<br />reflect();//歸一化</p><p>setTrain();//隨機選取75%樣本作為訓練集<br />saveTrain();//儲存訓練集</p><p>saveExpectation();//儲存期望輸出的資料</p><p>setTest();//隨機選取25%樣本作為測試集<br />saveTest();//儲存測試集<br />saveTestActual();//儲存待比較的實際值<br />system("pause");<br />return 0;<br />}
%匯入資料,之後運行如下代碼
%輸入3維訓練向量。已經歸一化處理。trainData.txt 。匯入資料
P=trainData(:,:);
P=P';%轉置
%輸出1維期望輸出向量。已經歸一化處理。expectation.txt
T=expectation(:);
T=T';%轉置
%輸入向量的取值範圍[0,1]。記得是4維
threshold=[0 1; 0 1; 0 1;0 1];
%建立BP網路,隱層神經元個數9(根據網路的效能向大或者向小取值調整)2*n+1,n=4
%輸出神經元個數1,
%中介層神經元傳遞函數tansig(S型正切函數)
%輸出層神經元傳遞函數logsig(S型對數函數)
%訓練函數traingdx(梯度下降法學習,且學習速率是自適應的)
net=newff(threshold,[7 1],{'tansig','logsig'},'traingdx');
%網路訓練次數
net.trainParam.epochs=1000;
%訓練目標
net.trainParam.goal=0.001;
%開始訓練
net=train(net,P,T);
%匯入test.txt,然後運行如下代碼
%接著訓練部分。
P_Test=test(:,:);
P_Test=P_Test';
Y=sim(net,P_Test);
%加上下面的語句,儲存結果到c://result.txt。還是需要處理的,當然比直接複製好多了
%csvwrite('c://result.txt',Y)
%z注意儲存結果到自己的工作目錄
%%匯入result.txt,運行下面代碼
%R=result(:);
%Y=result=R
將R匯出到excel中
也可在matlab中進行曲線的類比,源碼:
匯入testActual.txt,
和result.txt進行比較
注意轉置
%假設長度為64
Z=test(:,4);%實際值
x=1:1:64;
plot(x,Y,'b');%預測值
hold on
plot(x,Z,'r');%實際值