BP神經網路原理分析及c++程式碼實現(下)
為了方便廣大使用者的使用,本人將BP神經網路寫成了一個BPNNS類,這樣使用者們可以很方便的將此類潛入到自己的工程當中,此類的具體的使用規則,下面會介紹。
/*************************************************************************** * 檔名稱:BPNNs.h * 摘 要:BP神經網路 * 作 者:黃繼昆 * * 修改記錄: *[日期] [作者/修改者] [修改原因] *2012.7.14 黃繼昆 新增 ***************************************************************************/ #pragma once #include <stdio.h> #include <math.h> //演算法 #define traingd 0 // 基本的梯度下降演算法 #define traingdm 1 // 增加動量項的梯度下降演算法 #define traingdx 2 // 動量及自適應學習速率的梯度下降演算法 #define traincgf 3 // 共軛梯度演算法 #define trainrp 4 // 彈性BP演算法 //使用的傳遞函式 #define SIGMOID 10 // sigmoid 函式 #define PURLINE 11 // purelin函式 // 神經網路 型別 #define BP 12 //bp神經網路 #define ITEMS 13 #define MAXWEIGHT ((float)0.3) #define SCALEWEIGHT ((float)32767) typedef float *PFLOAT; typedef PFLOAT VECTOR; typedef PFLOAT *MATRIX; //建立BP神經網路引數結構體 typedef struct _NNS_CREACTE { int InputNodes; // 輸入層節點數 int HiddenLayers; // 隱層數 int *HiddenNodes; // 各隱層的節點數 int OutputNodes; // 輸出層節點數 int Patterns; // 訓練例項數 }BPNNS_CreateInfo,*pBPNNS_CreateInfo; //訓練神經網路引數結構體 typedef struct _NNS_TRAIN { int TrainMethod; // 訓練中使用的演算法 int OLTF; // OutputLayerTransferFunc輸出層使用的傳遞函式 int HLTF; // HindderLayerTransferFunc隱層使用的傳遞函式 int Iterations; // 訓練次數 float ErrorLeve; // 誤差級別 float eta; // 定義學習速率(步長) float alpha; // 定義動量因子(該值在有動量的梯度下降演算法當中才有效) }BPNNS_TrainInfo,*pBPNNS_TrainInfo; class CBPNNs { public: CBPNNs(void); public: CBPNNs(BPNNS_CreateInfo CreateInfo); public: ~CBPNNs(void); public: //構造網路 // 為訓練資料開闢空間(1)(2)(3) void VectorAllocate(VECTOR *vector,int nCols); // (1) void AllocateCols(PFLOAT matrix[],int nRows,int nCols); // (2) void MatrixAllocate(MATRIX *pmatrix,int nRows,int nCols); // (3) void MatrixFree(MATRIX matrix,int nRows); // 釋放空間 bool AlotSize(); // 變數分配空間 bool FreeMatrix(); // 釋放開闢好的空間 bool InitWeight(); // 初始化權值 //網路的訓練用到的成員函式 public: // 計算各層輸出 bool CaculateLayeoutValue(); // 計算每層神經元的輸出和計算一般化誤差 bool CaculateHiddenLayoutValue(int p,int j); // 計算隱層各神經元的輸出 bool CaculateOutLayerOutputValue(int p,int j); // 計算輸出層各神經元的輸出 public: // 各層權值的確定 bool AdjustWeight(int Temp,int q); // 調整權值 bool Adjust_BP_OutputWeight(int j); // 調整traingd演算法的輸出層權值 bool Adjust_Bp_HiddenWeight(int j); // 調整traingd演算法的隱層權值 bool Adjust_IMBP_OutputWeight(int j); // 調整traingdm演算法的輸出層權值 bool Adjust_IMBp_HiddenWeight( int j ); // 調整traingdm演算法的隱層權值 bool Adjust_VLBP_OutputWeight(int j); // 調整traingdx演算法的輸出層權值 bool Adjust_VLBp_HiddenWeight(int j); // 調整traingdx演算法的隱層權值 bool Adjust_trainrp_OutputWeight(int j,int q); // 調整彈性梯度下降演算法的輸出層的權值 bool Adjust_trainrp_HiddenWeight(int j,int q); // 調整彈性梯度下降演算法的yin層的權值 bool Adjust_CGBP_OutputWeight(int j,int q); // 調整traincgf演算法的輸出層權值 bool Adjust_CGBp_HiddenWeight(int j,int q); // 調整traincgf演算法的隱層權值 bool LimitValue_0_1(float *value); // Sigmoid函式輸出限幅 bool InputTrainData(char* TrainInput); // 輸入訓練資料 bool OutputWeight(char* WeightOutput); // 輸出訓練權值 public: //網路的應用用到的成員函式 bool GetWeight(char* InputWeight); // 獲取權值 bool OutputNet(char* NetName); // 輸出訓練好的網路引數 bool GetNet(char* NetName); // 獲取訓練好的網路引數 /* bool TestData(); // 開闢空間測試 */ //網路的應用 public://供外界呼叫的藉口 bool CreateBPNNS(BPNNS_CreateInfo CreateInfo); bool Train(BPNNS_TrainInfo TrainInfo,char* TrainInput,char* WeightOutput,char* NetOutput); bool Calculate(char* TestDate,char* TestResult ); // 訓練過之後再實際當中應用 bool GetNetAndWeight(char* NetName,char* InputWeight); //測試介面 bool OutputTrainResult(char* TrainResult); // 輸出訓練結果 public: //定義成員變數 //網路結構 int nInputNodes; // 輸入層節點數 int nHiddenLayers; // 隱層數 int *nHiddenNodes; // 各隱層的節點數 int nOutputNodes; // 輸出層節 //網路訓練引數 int nPatterns; // 訓練例項數 int nIterations; // 訓練次數 float nErrorLevel; // 誤差級 int nTrainMethod; // 訓練演算法 int nOLTF; // 輸出層傳遞函式 int nHLTF; // 隱層使用的傳遞函式 //用來儲存網路運行當中所依賴的變數 MATRIX out0; // 輸入資料 MATRIX *out1; // 隱層輸出 MATRIX *delta1; // 輸入層->隱層一般化誤差 MATRIX *delw1; // 輸入層->隱層 前一次訓練得到的權值 MATRIX *beta1; // 隱層共軛梯度演算法因子 MATRIX *dk_hidden; // 隱層共軛梯度演算法因子 MATRIX *deldk_hidden; // 儲存上次迭代的演算法因子 MATRIX *Tempdelw1; // 快取改變的權值 MATRIX *w1; // 輸入層->隱層的權值 MATRIX out2; // 輸出層輸出 MATRIX delta2; // 隱層->輸出層一般化誤差 MATRIX dk_out; // 共軛梯度下降演算法的儲存因子 MATRIX deldk_out; // 儲存上一次演算法因子數值 MATRIX beta; // 共軛梯度下降演算法的儲存因子 MATRIX delta2Temp; // 記錄delta2的前一次的值 MATRIX delw2; // 隱層->輸出成前一次訓練得到的權值 MATRIX Tempdelw2; // 快取權值 MATRIX w2; // 隱層->輸出層的權值 MATRIX target; // 目標函式(BP是有導師的訓練) float neta; // 學習速率(步長) float nalpha; // 動量因子 int nReportErrors; // 每一百次輸出一次誤差 int JugeError; // 學習速度自適應調節判斷過度 float errorTemp; // 記錄均方誤差 bool AloatSizeJuge; // 判斷是否進行了空間開闢 /* 本神經網路所有的輸入、輸出資料都是通過讀取二進位制檔案的形式完成的。 */ FILE *fpPattern, // 開啟用來訓練的txt檔案 *fpWeightsOut, // 儲存訓練好的權值
*fpNetOut, // 儲存構建網路的引數 *fpNetInput, // 獲取構建好的網路引數 *fpNetRead, // 讀取之前訓練好的網路引數 *fpResults, // 儲存訓練好的結果 *fpWeightInput, // 開啟訓練好的權值 *fpTest, // 開啟測試資料 *fpTestResult; // 輸出測試結果 };
在這裡介紹下供外界呼叫介面的使用規則,具體實現原理參考本人部落格BP神經網路原理分析及c++程式碼實現(上),同時各個函式都已經有註釋。
public://供外界呼叫的藉口
bool CreateBPNNS(BPNNS_CreateInfo CreateInfo);
bool Train(BPNNS_TrainInfo TrainInfo,char* TrainInput,char* WeightOutput,char* NetOutput);
bool Calculate(char* TestDate,char* TestResult );
bool GetNetAndWeight(char* NetName,char* InputWeight);
(1) bool CreateBPNNS(BPNNS_CreateInfo CreateInfo);
BPNNS_CreateInfo結構體的具體資訊如標頭檔案所示。使用這種方式構造網路,使用者需要首先構造BPNNs物件,構造網路不需要傳遞任何資訊,即為空,然後呼叫該函式構造網路。當然,如果使用者在構造BP神經網路類的過程中已經傳遞了構造資訊,此函式不要呼叫了。
(2)Train(BPNNS_TrainInfo TrainInfo,char* TrainInput,char* WeightOutput,char* NetOutput)。
● TrainInfo
TrainInfo 是訓練引數結構體BPNNs_TrainInfo所定義的變數,裡面定義了訓練過程中所需要的引數資訊。
● TrainInput
TrainInput是輸入訓練資料的檔名,該程式對檔案中的資料格式的要求是,檔案當中所有的資料之間都要以空格或者換行分開,根據使用者建立網路結構體當中使用者設定的輸入層節點數和輸出層節點數,和訓練事例數,先是存放所有的輸入資料,然後再放前面放置的所有輸入資料對應的輸出結果。
● WeightOutput
WeightOut 是訓練好的網路的權值儲存的檔名,程式會根據使用者傳遞的檔名來將網路權值儲存在該檔案當中。
● NetOutput
NetOutput是訓練好的網路儲存的檔名,程式會根據使用者傳遞的檔名將網路儲存在該檔案當中
(3)Calculate(char* TestDate,char* TestResult );
呼叫這兩個函式可完成方式一的使用,Train函式上面已經敘述過了,下面著重敘述Calculate函式。Calculate函式是用來完成使用者對實際資料進行處理的函式。
TestDate:資料檔名,是使用者用來處理的資料所在的檔名,檔案當中第一個資料是資料的組數,然後下面依次排列各組資料,組與組之間以及同一組的資料之間都以空格或者換行進行分割。
TestResult:輸出結果檔名,根據TestDate的輸入,將處理的結果輸出到該檔案當中,資料在檔案當中排列的順序依照TestDate中的順序排列。
同時為了方便使用者使用已經建立好的網路進行處理資料,不要每次處理都去訓練網路,特引出了另一個藉口
使用者直接讀取已經訓練好的網路,對資料進行處理。
GetNetAndWeight(char* NetInfo,char* InputWeight);
Calculate(char* TestDate,char* TestResult );
NetInfo: 網路資訊檔名,檔案中存有建立網路引數和訓練網路引數,引數在檔案當中的存在方式參考函式Train(BPNNS_TrainInfo TrainInfo,char* TrainInput,char* WeightOutput,char* NetOutput)當中的NetOutput。
InputWeight: 權值檔名,檔案中存放了已經訓練好的BPNN的權值,存放格式參考函式Train(BPNNS_TrainInfo TrainInfo,char* TrainInput,char* WeightOutput,char* NetOutput)當中的WeightOutput。
TesDate: 測試資料檔名,檔案當中資料存在格式參考函式OutputWeight(char* WeightOutput) 當中的WeightOutput。
TestResult:測試結果檔名,用來儲存測試資料處理的結果。資料存在的格式參考函式OutputNet(char* NetInfo)當中的NetInfo。
另外,為了方便使用者檢測訓練好的資料是否能夠達到預期的效果,BPNNs 提供了一個輸出訓練結果的函式
bool OutputTrainResult(char* TrainResult); // 輸出訓練結果
TrainResult:訓練結果檔名,訓練好網路之後呼叫該函式,會將預期結果和實際輸出結果一起輸出到該檔案當中,使用者可以很方便的進行資料對比,檢測該網路的訓練結果。
到此,整個BP神經網路c++實現過程已經敘述完畢,如有需要,歡迎評論交流