机器学习--BP神经网络的C++实现

原创 2016年06月06日 23:55:57

激活函数:Sigmoid
使用的是周志华老师的《机器学习》一书上的更新公式。
一共有三层,第一层是三维的,第二层是4维,输出层是1维。
这里写图片描述

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
using namespace std;

#define  innode 3  //输入结点数  
#define  outnode 1 //输出结点数  
#define  trainsample 8//BP训练样本数 
#define  INF 99999999 //定义无穷大

//初始化权值
void initialValue(double **weight1,double **weight2,double *bias1,double *bias2,int n1,int n2,int n3)
{
    for(int i=0; i<n1; i++)
    {
        for(int j=0; j<n2; j++)
        {
            //用来设置rand()产生随机数时的随机数种子。参数seed必须是个整数,如果每次seed都设相同值,rand()所产生的随机数值每次就会一样
            srand(time(NULL));
            weight1[i][j]=rand()%100/(100.0);
        }
    }
    for(int i=0; i<n2; i++)
    {
        for(int j=0; j<n3; j++)
        {
            srand(time(NULL));
            weight2[i][j]=rand()%100/(100.0);
        }
    }
    for(int i=0; i<n2; i++)
    {
        srand(time(NULL));
        bias1[i]=rand()%100/(100.0);
    }
    for(int i=0; i<n3; i++)
    {
        srand(time(NULL));
        bias2[i]=rand()%100/(100.0);
    }
}

double sigmoid(double x)
{
    return 1/(1+exp(-x));
}

//计算样本实际输出
void  computeY(double **weight1,double **weight2,double *bias1,double *bias2,int n1,int n2,int n3,double X[innode],double predictY[outnode],double *hideY)
{
    double sum=0;

    //计算隐层输出
    for(int i=0; i<n2; i++)
    {
        for(int j=0; j<n1; j++)
        {
            sum += weight1[j][i]*X[j];
        }
        sum=sigmoid(sum-bias1[i]);
        hideY[i]=sum;
    }
    sum=0;
    //计算最后一层输出
    for(int i=0; i<n3; i++)
    {
        for(int j=0; j<n2; j++)
        {
            sum += weight2[j][i]*hideY[i];
        }
        sum=sigmoid(sum-bias2[i]);
        predictY[i]=sum;
    }
}
//计算输出神经元的梯度
void computeOutputDY(int n3,double predictY[outnode],double Y[outnode],double *outputDweight)
{
    for(int i=0; i<n3; i++)
    {
        outputDweight[i]=predictY[i]*(1-predictY[i])*(Y[i]-predictY[i]);
    }

}

//计算隐藏神经元的梯度
void computeHideDY(double **weight2,int n2,int n3,double *hideY,double *outputDweight,double *hideDweight)
{
    for(int i=0; i<n2; i++)
    {
        double sum=0;
        for(int j=0; j<n3; j++)
        {
            sum+=weight2[i][j]*outputDweight[j];
        }
        hideDweight[i]=hideY[i]*(1-hideY[i])*sum;
    }
}

//更新权值
void updateWeight(double **weight1,double **weight2,double *bias1,double *bias2,int n1,int n2,int n3,double X[innode],double *hideY,double *outputDweight,double *hideDweight,double ratio)
{
    for(int i=0; i<n1; i++)
    {
        for(int j=0; j<n2; j++)
        {
            weight1[i][j]+=ratio*hideDweight[j]*X[i];
        }
    }
    for(int i=0; i<n2; i++)
    {
        for(int j=0; j<n3; j++)
        {
            weight2[i][j]+=ratio*outputDweight[j]*hideY[i];
        }
    }
    for(int i=0; i<n2; i++)
    {
        bias1[i]-=ratio*hideDweight[i];
    }
    for(int i=0; i<n3; i++)
    {
        bias2[i]-=ratio*outputDweight[i];
    }
}
//计算均方误差
double computeError(double predictY[outnode],double Y[outnode],int n)
{
    double error=0.0;
    for(int i=0; i<n; i++)
    {
        error += ((predictY[i]-Y[i])*(predictY[i]-Y[i]));
    }
    return error;
}
int main()
{
    //三层神经网络,各层的维度
    int n1=0,n2=0,n3=0;
    cout<<"输入各层的维度:";
    cin>>n1>>n2>>n3;

    //输入层与隐层的连接权n1xn2,隐层与输出层的连接权n2xn3
    double **weight1=new double*[n1];
    for(int i=0;i<n1;i++)
        weight1[i]=new double[n2];

    double **weight2=new double*[n2];
    for(int i=0;i<n2;i++)
        weight2[i]=new double[n3];

    //隐藏层的梯度项,输出层的梯度项
    double *outputDweight = new double[n3];
    double *hideDweight = new double[n2];

    //隐层的偏置,输出层的偏置
    double *bias1 = new double[n2];
    double *bias2 = new double[n3];

    //输入样本  n1=3,n3=1
    double X[trainsample][innode]= {{0,0,0},{0,0,1},{0,1,0},{0,1,1},{1,0,0},{1,0,1},{1,1,0},{1,1,1}};  
    //期望输出样本  
    double Y[trainsample][outnode]={{0},{0.1429},{0.2857},{0.4286},{0.5714},{0.7143},{0.8571},{1.0000}};  

    //实际输出样本
    double **predictY=new double*[trainsample];
    for(int i=0;i<trainsample;i++)
        predictY[i]=new double[outnode];

    //隐层输出样本
    double *hideY=new double[n2];

    //权值,偏置初始化
    initialValue(weight1,weight2,bias1,bias2,n1,n2,n3);

    double error=INF;
    //学习率
    double ratio=0.5;

    while(error>0.005)
    {
        error=0.0;
        for(int i=0; i<trainsample; i++)
        {
            //计算输出层的值
            computeY(weight1,weight2,bias1,bias2,n1,n2,n3,X[i],predictY[i],hideY);
            //计算输出层的梯度项
            computeOutputDY(n3,predictY[i],Y[i],outputDweight);
            //计算隐层的梯度项
            computeHideDY(weight2,n2,n3,hideY,outputDweight,hideDweight);
            //更新权值
            updateWeight(weight1,weight2,bias1,bias2,n1,n2,n3,X[i],hideY,outputDweight,hideDweight,ratio);
            //计算均方误差
            error += computeError(predictY[i],Y[i],outnode);
        }
        error=0.5*error;
    }

    //输出网络的输出与实际输出的对应
    for(int i=0; i<trainsample; i++)
    {
        for(int j=0; j<outnode; j++)
        {
            cout<<"predictY[i][j]::"<<predictY[i][j]<<"----"<<"Y[i][j]::"<<Y[i][j]<<endl;
        }
    }

    //释放空间
    for(int i=0;i<n1;i++)
    {
        delete []  weight1[i];  
    }
    for(int i=0;i<n2;i++)
    {
        delete []  weight2[i];
    }

    delete [] weight1;
    delete [] weight2;
    delete [] bias1;
    delete [] bias2;
}

值得推荐的C/C++框架和库 (真的很强大)

值得学习的C语言开源项目 - 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作...

c++开源机器学习库及机器学习知识框架(更新中)

1)mlpack is a C++ machine learning library. 2)PLearn is a C++ library aimed at research and develop...

Shark:强大的开源C++机器学习库

申明:本文非笔者原创,原文转载自:http://sigvc.org/bbs/thread-872-1-1.html Shark 是一个快速、模块化、功能丰富的开源 C++ 机器学习库,...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

c++开源机器学习库(更新中20140330)

1)mlpack is a C++ machine learning library.[按:据说代码风格比shogun强多了;另外可以在win上编译的指南是:https://trac.research...

开源机器学习C++库Shark的编译与开发环境搭建

Shark是一个快速、模块化、功能丰富的开源C++机器学习库,提供了各种机器学习相关技术,比如线性/非线性优化、基于内核学习算法、神经网络等。   机器学习(MachineLearning)是...
  • deirjie
  • deirjie
  • 2014年08月20日 18:50
  • 3699

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

机器学习基石PLA算法c++语言实现

其中的Item.label为数据中的判断结果,例如在授予信用卡的时候为 是 或者 否,其算法的目的就在于确定其中wight中个分量的值 #include #include #include u...

机器学习:概念学习FIND-S算法C++实现

一、概念 概念学习:是指从有关某个布尔函数的输入输出训练样例中推断出该布尔函数。 二、概念学习任务 任何概念学习任务能被描述为:实例的集合X、实例集合上的目标函数c、候选假设的集合H以及训练样例...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:机器学习--BP神经网络的C++实现
举报原因:
原因补充:

(最多只允许输入30个字)