关于bp神经网络算法的总结
学习自: https://blog.****.net/QKK612501/article/details/52893803
需要用以下两行代码:
#include"bpNetwork.h"
using namespace bpNetwork;
介绍:
提供 “basicNode” 类
定义:
basicNode<typename _type>(nodeType type,_type(*function)(vector<_type>,int,_type theta));
nodeType 有如下种类:
FRONT_NODE :输入节点
MID_NODE :隐藏节点(默认)
END_NODE:输出节点
function 是数据处理函数指针,
数据处理函数要有如下参数:
vector<_type> :提供数据
int :数据长度
_type :权值
头文件自带数据处理函数有:
Identity
Binary_Step
Logistic(Sigmoid)
tanh
arctan
RelU
PRelU
ElU
Softplus
basicNode类提供以下函数:
void giveData(_type Num);
提供输入。参数:输入数据
void addSon(basicNode* sonNode,_type(*con)(_type,_type),_type w=1);
添加子节点。参数:子节点指针,连接函数指针,权值(默认为1)
连接函数参数:数据,权值
头文件目前只提供:
Identity
void func(_type(*solveDat)(vector<_type>,int,_type));
改变数据处理函数。参数:见上
void searchSon(vector<basicNode<_type>*>* hiddenPoints,vector<basicNode<_type>*>* endPoints,vector<basicNode<_type>*>* edgeStack,vector<basicNode<_type>*>* nodeStack)
搜索子节点并入vector。参数:隐藏节点vector指针,末节点vector指针,读边学习vector指针,读节点学习vector指针
void endResult(_type* res)
确定返回数据指针。参数:返回指针
void exchangeTheta(_type newTheta);
void exchangeTheta(long id,_type newTheta);
void exchangeDerta(_type newTheta);
void exchangeDerta(long id,_type newTheta);
改权值。
long long getSonNum()
获得子节点数
void saveNode(const char * __restrict__ _Filename);
void saveNode(FILE* _FilePointer);
void readNode(const char * __restrict__ _Filename);
void readNode(FILE* _FilePointer);
存储节点到文件(不完备)
头文件自带学习函数(不完备):
void faltBack(vector<_type> inputs,vector<_type> outputs,vector<basicNode<_type>*>* inputPoints,unsigned long long learnTimes,_type learnWeight,double(*resultFunction)(vector<_type>*,vector<_type>*,vector<_type>*));//double resultFunciton(vector<_type>* wantOut,vector<_type*>* factOut,vector<_type>* oldOut) return weight:positive for
参数:输入数据vector,期望输出数据vector,输入节点指针vector的指针,学习次数,学习力度,权值计算函数(参数:希望输出数据vector的指针,实际输出的指针vector的指针,测试优化前输出。返回值:正数表示劣化了,负数表示优化了)
应用
我写的小型bp神经网络
源代码(C++)
#include<bits/stdc++.h>
#include"bpNetwork.h"
using namespace std;
using namespace bpNetwork;
FILE* sav;
float result,input;
int main(){
sav=fopen("save.sav","r");
basicNode<float>
node1(FRONT_NODE,&Logistic),
node2(MID_NODE,&Logistic),
node3(MID_NODE,&Logistic),
node4(MID_NODE,&Logistic),
node5(MID_NODE,&Logistic),
node6(MID_NODE,&Logistic),
node7(MID_NODE,&Logistic),
node8(MID_NODE,&Logistic),
node9(MID_NODE,&Logistic),
node10(END_NODE,&Logistic);
node1.addSon(&node2,&Identity);
node1.addSon(&node3,&Identity);
node1.addSon(&node4,&Identity);
node2.addSon(&node4,&Identity);
node2.addSon(&node6,&Identity);
node3.addSon(&node4,&Identity);
node3.addSon(&node5,&Identity);
node4.addSon(&node6,&Identity);
node4.addSon(&node7,&Identity);
node5.addSon(&node7,&Identity);
node5.addSon(&node8,&Identity);
node6.addSon(&node7,&Identity);
node6.addSon(&node9,&Identity);
node7.addSon(&node8,&Identity);
node7.addSon(&node9,&Identity);
node7.addSon(&node10,&Identity);
node8.addSon(&node10,&Identity);
node9.addSon(&node10,&Identity);
node10.endResult(&result);
scanf("%f",&input);
node1.giveData(input);
printf("%f",result);
}
代码
(我写的)头文件:bpNetwork.h
/*
Copyright (c) 2019 BooleanWar project,all rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include<bits/stdc++.h>
#include<windows.h>
#include<conio.h>
#include<math.h>
#include<pthread.h>
using namespace std;
/************************************************************************************************************************/
namespace bpNetwork{
#define FUNC(e,f,p) e(*f)(p)
typedef int nodeType;
#define FRONT_NODE 0
#define MID_NODE 1
#define END_NODE 2
double arctan(double x)
{
int i;
double r,e,f,sqr;
sqr=x*x;
r=0; e=x; i=1;
while(e/i>1e-15)
{
f=e/i;
r=(i%4==1)? r+f : r-f;
e=e*sqr; i+=2;
}
return r;
}
/************************************************************************************************************************/
//connection function
template <typename _type>
_type Identity(_type DATA,_type weight){
return DATA*weight;
}
//solve Data Functions
template <typename _type>
_type Identity(vector<_type>DATA,int vectorLen,_type THETA)
{
_type res=DATA[0];
for(int i=1;i<vectorLen;i++)
res=res+DATA[i];
res=res*THETA;
return res;
}
template <typename _type>
_type Binary_Step(vector<_type>DATA,int vectorLen,_type THETA)
{
_type res=DATA[0];
for(int i=1;i<vectorLen;i++)
res=res+DATA[i];
res=res*THETA;
return res>=0?1:0;
}
template <typename _type>
_type Logistic(vector<_type>DATA,int vectorLen,_type THETA)
{
_type res=DATA[0];
for(int i=1;i<vectorLen;i++)
res=res+DATA[i];
res=res*THETA;
return 1/(1+pow(M_E,res));
}
template <typename _type>
_type Sigmoid(vector<_type>DATA,int vectorLen,_type THETA)
{
_type res=DATA[0];
for(int i=1;i<vectorLen;i++)
res=res+DATA[i];
res=res*THETA;
return 1/(1+pow(2.7182818,res));
}
template <typename _type>
_type tanh(vector<_type>DATA,int vectorLen,_type THETA)
{
_type res=DATA[0];
for(int i=1;i<vectorLen;i++)
res=res+DATA[i];
res=res*THETA;
return tanh(res);
}
template <typename _type>
_type arctan(vector<_type>DATA,int vectorLen,_type THETA)
{
_type res=DATA[0];
for(int i=1;i<vectorLen;i++)
res=res+DATA[i];
res=res*THETA;
return arctan(res);
}
template <typename _type>
_type RelU(vector<_type>DATA,int vectorLen,_type THETA)
{
_type res=DATA[0];
for(int i=1;i<vectorLen;i++)
res=res+DATA[i];
res=res*THETA;
return res>=0?res:0;
}
template <typename _type>
_type PRelU(vector<_type>DATA,int vectorLen,_type THETA)
{
_type res=DATA[0];
for(int i=1;i<vectorLen;i++)
res=res+DATA[i];
return res>=0?res*THETA:res;
}
template <typename _type>
_type ElU(vector<_type>DATA,int vectorLen,_type THETA)
{
_type res=DATA[0];
for(int i=1;i<vectorLen;i++)
res=res+DATA[i];
return res>=0?res*THETA:res;
}
template <typename _type>
_type Softplus(vector<_type>DATA,int vectorLen,_type THETA)
{
_type res=DATA[0];
for(int i=1;i<vectorLen;i++)
res=res+DATA[i];
return log(1+pow(M_E,res));
}
/************************************************************************************************************************/
//other public functions
template<typename _type>
class basicNode{
public:
basicNode(nodeType type=MID_NODE,_type(*function)(vector<_type>,int,_type)=NULL):fatherNum(NULL),sonNum(NULL),type(type),theta(NULL),solveData(function),dataPoint(0),singleWeight(1){}
void giveData(_type Num){
_type dat;
data.push_back(Num);
dataPoint++;
if(dataPoint>=fatherNum)
if(type==MID_NODE||type==FRONT_NODE){
dat=solveData(data,fatherNum,singleWeight);
for(int i=0;i<sonNum;i++){
(*sons[i]).giveData((*connections[i])(dat,weight[i]));//wrong grammer
}
resetData();
}
else
{
(*result)=solveData(data,fatherNum,singleWeight);
}
}
void addSon(basicNode* sonNode,_type(*con)(_type,_type),_type w=1){
sons.push_back(sonNode);
connections.push_back(con);
weight.push_back(w);
sonNum++;
(*sonNode)._addFa(this);
}
void _addFa(basicNode* fatherNode){
fathers.push_back(fatherNode);
fatherNum++;
}
void func(_type(*solveDat)(vector<_type>,int,_type)){
solveData=solveDat;
}
void searchSon(vector<basicNode<_type>*>* hiddenPoints,vector<basicNode<_type>*>* endPoints,vector<basicNode<_type>*>* edgeStack,vector<basicNode<_type>*>* nodeStack){
(*nodeStack).push_back(this);
for(int i=0;i<sonNum;i++){
switch((*sons[i]).type){
case FRONT_NODE:
case MID_NODE:
(*edgeStack).push_back(this);
for(int j=0;j<(*hiddenPoints).length();j++)
if((*hiddenPoints)[j]==sons[j])return;
(*hiddenPoints).push_back(sons[i]);
(*sons[i]).search(hiddenPoints,endPoints);
break;
case END_NODE:
for(int i=0;i<(*endPoints).length();i++)
if((*endPoints)[i]==sons[i])return;
(*endPoints).push_back(sons[i]);
break;
}
}
}
void endResult(_type* res){
result=res;
}
void exchangeTheta(_type newTheta){
theta=newTheta;
}
void exchangeTheta(long id,_type newTheta){
weight[id]=newTheta;
}
void exchangeDerta(_type newTheta){
theta=newTheta+theta;
}
void exchangeDerta(long id,_type newTheta){
weight[id]=newTheta+weight[id];
}
long long getSonNum(){
return sonNum;
}
/************************************************************************************************************************/
//save Node functions
void saveNode(const char * __restrict__ _Filename){
FILE* standard=stdout;
freopen(_Filename,"w",stdout);
cout<<"Node Theta:"<<theta<<endl;
stdout=standard;
}
void saveNode(FILE* _FilePointer){
FILE* standard=stdout;
stdout=_FilePointer;
cout<<"Node Theta:"<<theta<<endl;
stdout=standard;
}
/************************************************************************************************************************/
//read Node functions
void readNode(const char * __restrict__ _Filename){
FILE* standard=stdin;
freopen(_Filename,"r",stdin);
scanf("Node Theta:");
cin>>theta;
scanf("\n");
stdin=standard;
}
void readNode(FILE* _FilePointer){
FILE* standard=stdin;
stdin=_FilePointer;
scanf("Node Theta:");
cin>>theta;
scanf("\n");
stdin=standard;
}
/************************************************************************************************************************/
private://private defines
nodeType type;
_type* result;
vector<basicNode*>sons;
vector<basicNode*>fathers;
vector<_type(*)(_type,_type)>connections;
vector<_type>data;
vector<_type>weight;
_type(*solveData)(vector<_type>,int,_type);
long long fatherNum;
long long sonNum;
int dataPoint;
_type singleWeight;
_type theta;
/************************************************************************************************************************/
//private functions
void resetData(){
data.clear();
dataPoint=0;
}
};
/************************************************************************************************************************/
//global functions
template<typename _type>
void faltBack(vector<_type> inputs,vector<_type> outputs,vector<basicNode<_type>*>* inputPointsPointer,unsigned long long learnTimes,_type learnWeight,double(*resultFunction)(vector<_type>*,vector<_type>*,vector<_type>*)){//double resultFunciton(vector<_type>* wantOut,vector<_type*>* factOut,vector<_type>* oldOut) return weight:positive for
vector<basicNode<_type>*> inputPoints=*inputPointsPointer;
vector<basicNode<_type>*> hiddenPoints;
vector<basicNode<_type>*> endPoints;
vector<basicNode<_type>*> exchangeEdge;
vector<basicNode<_type>*> exchangeNode;
vector<_type*> outputsPoints;
vector<_type> outputsPast;
_type derta;
int weight;
bool lastIsNegative=false;
for(long long i=0;i<inputPoints.length();i++)
{
exchangeEdge.push_back(inputPoints[i]);
exchangeNode.push_back(inputPoints[i]);
(*inputPoints)[i].searchSon(&hiddenPoints,&endPoints,&exchangeEdge,&exchangeNode);
}//search nodes
for(long long i=0;i<outputs.length();i++){
endPoints.push_back(new _type);
(*endPoints).endResult(outputsPoints[i]);
}//set return points
for(long long i=0;i<inputPoints.length();i++)
(*inputPoints).giveData(inputs[i]);
//input
for(long long i=0;i<endPoints.length();i++)
outputsPast.push_back(*endPoints[i]);
//set outputs
for(long long i=0;i=learnTimes;i++){
//study
for(long long j=0;j<exchangeEdge.length();j++)
//start&mid nodes
for(long long k=0;k<(*exchangeEdge[j]).getSonNum;k++)
{
//for each edge
weight=1;
reset: for(long long i=0;i<endPoints.length();i++)
outputsPast[i]=*endPoints[i];
//reset old output
(*exchangeEdge[j]).exchangeDerta(k,learnWeight*weight);
//reset weight
for(long long i=0;i<inputPoints.length();i++)
(*inputPoints).giveData(inputs[i]);
//input
if(resultFunction(&outputs,&endPoints,&outputsPast)>0){
weight*=-1;
if(lastIsNegative)
weight*=0.5;
else lastIsNegative=true;
}
else lastIsNegative=false;
//change weight
if(weight>=0.01||weight<=-0.01)
goto reset;
//loop
}
for(long long j=0;j<exchangeNode.length();j++){
weight=1;
//set weight
reset2: for(long long i=0;i<endPoints.length();i++)
outputsPast[i]=*endPoints[i];
//reset old output
(*exchangeEdge[j]).exchangeDerta(k,learnWeight*weight);
//change weight
for(long long i=0;i<inputPoints.length();i++)
(*inputPoints).giveData(inputs[i]);
//input
if(resultFunction(&outputs,&endPoints,&outputsPast)>0){
weight*=-1;
if(lastIsNegative)
weight*=0.5;
else lastIsNegative=true;
}
else lastIsNegative=false;
//change weight
if(weight>=0.01||weight<=-0.01)
goto reset2;
//loop
}
}
for(long long i=0;i<outputs.length();i++){
delete endPoints[i];
//free memory
}
}