bp

头文件

/*
 * bp.h
 *
 *  Created on: 2013年12月10日
 *      Author: sai
 */

#ifndef BP_H_
#define BP_H_

#include "linalgebra.h"
#include <string>

/******************************************************************************
               前向反馈神经网络,三层神经元(一个隐藏层)
******************************************************************************/
class BP3
{
public:
    BP3(int inSize, int hideSize, int outSize);
    ~BP3();
    void train(Vector sample[], Vector target[], int size);
    void calc(const Vector& sample); //根据输入计算各个神经元节点的值
    void backPropagation(Vector& sample, Vector& answer); //训练权值
    void readFile(const std::string& fileName);
    void saveFile(const std::string& fileName) const;
    void normalize(Vector aVec[], int size);
    void speedUp();
//protected:
    Vector vI; //输入层的值
    Vector vH; //隐藏层的值
    Vector vO; //输出层的值
    
    Vector eH; //隐藏层误差
    Vector eO; //输出层误差
    
    Matrix wH; //每个输入层到中间层的权值
    Matrix wO; //每个中间层到输出层的权值
    
    Matrix dH; //上次wH的调整幅度
    Matrix dO; //上次wO的调整幅度
    
    Vector tH; //输入层到隐藏层的阈值
    Vector tO; //隐藏层到输出层的阈值
    
    int iSize; //输入层大小
    int hSize; //隐藏层大小
    int oSize; //输出层大小
    
    double eta; //学习步长
    double alpha; //动量项系数
};

#endif /* BP_H_ */

 

源文件

/*
 * bp.cpp
 *
 *  Created on: 2013年12月10日
 *      Author: sai
 */


#include "bp.h"
#include <iostream>
#include <fstream>
#include <cfloat>
using namespace std;

BP3::BP3(int inSize, int hideSize, int outSize)
{
    eta = 0.3;
    alpha = 0.8;
    
    iSize = inSize;
    vI.resize(iSize);
    
    hSize = hideSize;
    vH.resize(hSize);    
    wH.resize(hSize, iSize);
    for (int i=0; i<hSize; i++)
        for (int j=0; j<iSize; j++)
            wH.data[i][j] = 0.6 * rand() / RAND_MAX - 0.3; //权值初始化为[-0.3,0.3]
    tH.resize(hSize);
    eH.resize(hSize);
    dH.resize(hSize, iSize);
    dH.zero();
    
    oSize = outSize;
    vO.resize(oSize);    
    wO.resize(oSize, hSize);
    for (int i=0; i<oSize; i++)
        for (int j=0; j<hSize; j++)
            wO.data[i][j] = 0.6 * rand() / RAND_MAX - 0.3;
    tO.resize(oSize);
    eO.resize(oSize);
    dO.resize(oSize, hSize);
    dO.zero();
    
/*    cout<<"wH:\n"<<wH<<endl
        <<"wO:\n"<<wO<<endl
        <<"dH:\n"<<dH<<endl
        <<"dO:\n"<<dO<<endl;*/
}

BP3::~BP3()
{
}

void BP3::normalize(Vector aVec[], int size)
{
    Vector min(aVec[0].size()), max(aVec[0].size());
    min.zero();
    max.zero();
    
    for (int i=0; i<size; i++)
        for (int j=0; j<aVec[j].size(); j++)
            if (aVec[i][j] > max[j])
                max[j] = aVec[i][j];
            else if (aVec[i][j] < min[j])
                min[j] = aVec[i][j];    
    for (int i=0; i<size; i++)
        for (int j=0; j<aVec[j].size(); j++)
            aVec[i][j] = (aVec[i][j]-min[j]+0.001) / (max[j]-min[j]+0.001);    
/*    for (int i=0; i<size; i++)
    {
        for (int j=0; j<aVec[j].size(); j++)
            cout<<aVec[i][j]<<'\t';
        cout<<endl;
    }*/
}

void BP3::speedUp()
{
    for (int i=0; i<oSize; i++)
        if (vO[i] < 0.1)
            vO[i] = 0.1;
        else if (vO[i] > 0.9)
            vO[i] = 0.9;
}

void BP3::calc(const Vector& sample)
{
    //输入层
    vI = sample;
    
    //隐藏层
    vH = wH * vI + tH;
    for (int i=0; i<hSize; i++)
        vH[i] = 1 / (1 + exp(-vH[i]));
    
    //输出层
    vO = wO * vH - tO;
    for (int i=0; i<oSize; i++)
        vO[i] = 1 / (1 + exp(-vO[i]));
}

void BP3::backPropagation(Vector& sample, Vector& target)
{    
    //输出层调整
//    eO = vO * (1-vO) * (target - vO); 
    for (int i=0; i<oSize; i++) //输出层误差
        eO[i] = vO[i] * (1-vO[i]) * (target[i] - vO[i]);    
    dO = eta * eO * vH.transpose() + alpha * dO; //输出层权值修正量    
    wO += dO; //修正输出层权值
    tO += eta * eO;    
    
    //隐藏层调整
    eH = eO.transpose() * wO; //隐藏层误差
//    eH = vH * (1 - vH) * eH;    
    for (int i=0; i<hSize; i++)
        eH[i] = vH[i] * (1-vH[i]) * eH[i];
    dH = eta * eH * vI.transpose() + alpha * dH; //隐藏层权值修正量    
    wH += dH; //修正隐藏层权值
    tH = eta * eH;
}

void BP3::train(Vector sample[], Vector target[], int size)
{
    normalize(sample, size);
    
    for (int t=0; t<100000; t++) //训练次数
    {
        for (int i=0; i<size; i++)
        {
            calc(sample[i]); //正向传播
//            speedUp();
            backPropagation(sample[i], target[i]); //反向传播
        }
        
        double error = 0;
        for (int i=0; i<size; i++)
        {
            calc(sample[i]);
            for (int j=0; j<oSize; j++)
                error += fabs(vO[j] - target[i][j]);
        }
        cout<<error<<endl;
    }
}

void BP3::saveFile(const std::string& fileName) const
{
    ofstream f(fileName.c_str(), ios::binary);
    
    f.write((char*)(&iSize), sizeof(int));
    f.write((char*)(&hSize), sizeof(int));
    f.write((char*)(&oSize), sizeof(int));
    
    for (int i=0; i<hSize; i++)
        for (int j=0; j<iSize; j++)
            f.write((char*)(&wH[i][j]), sizeof(double));
    for (int i=0; i<hSize; i++)
        f.write((char*)(&tH[i]), sizeof(int));
    
    for (int i=0; i<oSize; i++)
        for (int j=0; j<hSize; j++)
            f.write((char*)(&wO[i][j]), sizeof(double));
    for (int i=0; i<oSize; i++)
        f.write((char*)(&tO[i]), sizeof(int));
}

void BP3::readFile(const std::string& fileName)
{
    ifstream f(fileName.c_str(), ios::binary);
    if (!f)
    {
        cerr<<"文件不存在,错误发生在函数"<<__FUNCTION__<<endl;
        return;
    }    
        
    f.read((char*)(&iSize), sizeof(int));
    f.read((char*)(&hSize), sizeof(int));
    f.read((char*)(&oSize), sizeof(int));
    
    vI.resize(iSize);
    
    vH.resize(hSize);    
    wH.resize(hSize, iSize);    
    for (int i=0; i<hSize; i++)
        for (int j=0; j<iSize; j++)
            f.read((char*)(&wH[i][j]), sizeof(double));
    tH.resize(hSize);
    for (int i=0; i<hSize; i++)
        f.read((char*)(&tH[i]), sizeof(int));
    eH.resize(hSize);
    dH.resize(hSize, iSize);
    dH.zero();
    
    vO.resize(oSize);
    wO.resize(oSize, hSize);    
    for (int i=0; i<oSize; i++)
        for (int j=0; j<hSize; j++)
            f.read((char*)(&wO[i][j]), sizeof(double));
    tO.resize(oSize);
    for (int i=0; i<oSize; i++)
        f.read((char*)(&tO[i]), sizeof(int));
    eO.resize(oSize);
    dO.resize(oSize, hSize);
    dO.zero();
}

 

 

 

 

 

 

 

posted on 2013-10-08 08:42  赛欧拉  阅读(258)  评论(0)    收藏  举报