初探神经网络:QT下建立BP网络模型

27 篇文章 1 订阅

初探神经网络:QT下建立BP网络模型


本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.


环境:

主机:WIN7

开发环境:Qt


实现功能:

建立了细胞类以及BP网络类.BP神经网络为3层结构:输入层,隐藏层,输出层.


说明:

1.细胞模型


2.BP网络模型


3.输入层细胞阈值为0,输出层细胞权值为1.

4.隐藏层传递函数为f(x) = 1 / (1 + e(-x))

5.需要载入的权文件名为w.txt,放在运行目录下,格式为每个数字一行.输入顺序为输入层细胞所有权,隐藏层细胞所有权.

6.需要载入的权阈值文件名为threshold.txt,放在运行目录下,格式为每个数字一行.输入顺序为隐藏层细胞所有阈值,输出层细胞所有阈值.

7.供BP网络学习的文件名为study.txt,放在运行目录下,格式为每个数字一行.输入顺序为第1次所有输入层细胞的输入,第1次所有输出层细胞的输出,第2次...

8.权值和阈值可以用提供的随机函数生成,范围是-1至1


源代码:

public.h:细胞及BP网络类头文件

#ifndef PUBLIC_H
#define PUBLIC_H

//头文件
#include <QWidget>
#include "qdebug.h"
#include "QFile"

#include "math.h"
#include <time.h>

//宏定义

//全局变量

//数据结构
//细胞
class _Cell
{
private:
    //输入数
    int num_in;
    //输出数
    int num_out;
    //输入
    double *pt_in;
    //输出
    double *pt_out;
    //输出,不加权
    double out_no_w;
    //权
    double *pt_w;
    //阈值
    double threshold;
    //传递函数类型
    int type_fun;
    //传递函数
    double fun(double x);
public:
    //初始化
    //num1:输入数
    //num2:输出数
    _Cell(int num1 = 0,int num2 = 0);
    //设置输入数
    void set_in_num(int num);
    //设置输出数
    void set_out_num(int num);
    //返回输入数
    int return_in_num();
    //返回输出数
    int return_out_num();
    //返回权值
    //num:指向的目标细胞
    double return_w(int num);
    //返回当前阈值
    double return_threshold();
    //返回输入
    //num为第num个输入
    double return_in(int num);
    //设置输入
    void set_in(double a,int num);
    //设置阈值
    void set_threshold(double a);
    //设置权
    void set_w(double a,int num);
    //设置传递函数类型
    void set_fun(int num);
    //计算输出
    void calc();
    //返回输出
    double output(int num);
    //返回输出不加权
    double output_no_w();
};

//BP网络
class _BP_Net
{
private:
    //输入层细胞数
    int num_in_layer;
    //隐藏层细胞数
    int num_hide_layer;
    //输出层细胞数
    int num_out_layer;
    //输入层细胞指针
    _Cell *pt_in_layer_cell;
    //隐藏层细胞指针
    _Cell *pt_hide_layer_cell;
    //输出层细胞指针
    _Cell *pt_out_layer_cell;
    //学习速率
    double g;
public:
    //初始化
    _BP_Net(int num_in = 0,int num_hide = 0,int num_out = 0);
    //设置输入层细胞数
    void set_num_in_layer(int num);
    //设置隐藏层细胞数
    void set_num_hide_layer(int num);
    //设置输出层细胞数
    void set_num_out_layer(int num);
    //返回输入层细胞数
    int return_num_in_layer();
    //返回隐藏层细胞数
    int return_num_hide_layer();
    //返回输出层细胞数
    int return_num_out_layer();
    //返回权值
    //i:层号,0输入层,1隐藏层,2输出层
    //j:本层细胞号
    //k:下一层细胞号
    //失败返回-1
    double return_w(int i,int j,int k);
    //返回阈值
    //i:层号,0输入层,1隐藏层,2输出层
    //j:本层细胞号
    //失败返回-1
    double return_threshold(int i,int j);
    //产生随机的权值,-1-1之间
    void set_rand_w();
    //产生随机的阈值,-1-1之间
    void set_rand_threshold();
    //设置输入层权值
    //a:权值,i:细胞号,j:细胞对应输出
    void set_in_layer_w(double a,int i,int j);
    //设置隐藏层权值
    //a:权值,i:细胞号,j:细胞对应输出
    void set_hide_layer_w(double a,int i,int j);
    //设置隐藏层阈值
    //a:阈值,num:细胞号
    void set_hide_layer_threshold(double a,int num);
    //设置输出层阈值
    //a:阈值,num:细胞号
    void set_out_layer_threshold(double a,int num);
    //设置学习速率
    void set_g(double a);
    //学习
    //right为正确的值数组
    void study(double *right);
    //计算输出
    void calc();
    //返回输出
    double output(int num);
    //设置输入层细胞输入
    void set_in(double a,int num);
};

//全局函数
//初始化
//归一化函数
//dst:目标数据
//min:最小值
//max:最大值
double mapminmax(double dst,double min,double max);
//反归一化
//dst:目标数据
//min:最小值
//max:最大值
double premapminmax(double dst,double min,double max);
//加载权值
//dir:目录,bp_net:神经网络
//成功返回1,失败返回-1
int load_w(QString dir,_BP_Net *bp_net);
//加载阈值
//dir:目录,bp_net:神经网络
//成功返回1,失败返回-1
int load_threshold(QString dir,_BP_Net *bp_net);
//写入权值
//dir:目录,bp_net:神经网络
//成功返回1,失败返回-1
int write_w(QString dir,_BP_Net *bp_net);
//写入阈值
//dir:目录,bp_net:神经网络
//成功返回1,失败返回-1
int write_threshold(QString dir,_BP_Net *bp_net);
//读取正确的值,并且学习
//dir:目录,bp_net:神经网络
//成功返回1,失败返回-1
int study(QString dir,_BP_Net *bp_net);

#endif // PUBLIC_H

public.c:实现类的各个方法

#include "public.h"

//全局变量定义

//细胞方法
//初始化
//num1:输入数
//num2:输出数
_Cell::_Cell(int num1,int num2)
{
    num_in = num1;
    num_out = num2;

    if (num1 != 0 && num2 != 0)
    {
        //开辟空间
        pt_in = new double[num_in];
        pt_out = new double[num_out];
        pt_w = new double[num_out];
    }
}

//设置输入数
void _Cell::set_in_num(int num)
{
    num_in = num;
}

//设置输出数
void _Cell::set_out_num(int num)
{
    num_out = num;

    //开辟空间
    pt_in = new double[num_in];
    pt_out = new double[num_out];
    pt_w = new double[num_out];
}

//返回输入数
int _Cell::return_in_num()
{
    return num_in;
}

//返回输出数
int _Cell::return_out_num()
{
    return num_out;
}

//返回权值
//num:指向的目标细胞
double _Cell::return_w(int num)
{
    return pt_w[num];
}

//返回当前阈值
double _Cell::return_threshold()
{
    return threshold;
}

//返回输入
//num为第num个输入
double _Cell::return_in(int num)
{
    return pt_in[num];
}

//传递函数
double _Cell::fun(double x)
{
    //判断传递函数类型
    if (type_fun == 0)
    {
        //直接传递
        return x;
    }
    else
    {
        //连续曲线
        return(1.0 / (1.0 + exp(-1.0 * x)));
    }
}

//设置权
void _Cell::set_w(double a,int num)
{
    pt_w[num] = a;
}

//设置阈值
void _Cell::set_threshold(double a)
{
    threshold = a;
}

//设置输入
void _Cell::set_in(double a,int num)
{
    pt_in[num] = a;
}

//设置传递函数类型
void _Cell::set_fun(int num)
{
    if (num != 1)
    {
        type_fun = 0;
    }
    else
    {
        type_fun = 1;
    }
}

//返回输出
double _Cell::output(int num)
{
    return pt_out[num];
}

//返回输出不加权
double _Cell::output_no_w()
{
    return out_no_w;
}

//计算输出
void _Cell::calc()
{
    int i = 0;
    double temp = 0;

    for (i = 0;i < num_in;i++)
    {
        temp += pt_in[i];
    }
    temp -= threshold;

    out_no_w = fun(temp);
    //输出加权
    for (i = 0;i < num_out;i++)
    {
        pt_out[i] = out_no_w * pt_w[i];
    }
}

//BP网络方法
//初始化
_BP_Net::_BP_Net(int num_in,int num_hide,int num_out)
{
    int i = 0;

    num_in_layer = num_in;
    num_hide_layer = num_hide;
    num_out_layer = num_out;

    //初始化学习速率
    g = 0.5;

    if (num_in_layer != 0 &&
        num_hide_layer != 0 &&
        num_out_layer != 0)
    {
        //初始化每层细胞指针
        pt_in_layer_cell = new _Cell[num_in];
        pt_hide_layer_cell = new _Cell[num_hide];
        pt_out_layer_cell = new _Cell[num_out];

        //初始化每层细胞的输入,输出,传递函数类型
        //初始化输入层
        for (i = 0;i < num_in_layer;i++)
        {
            pt_in_layer_cell[i].set_in_num(1);
            pt_in_layer_cell[i].set_out_num(num_hide_layer);
            pt_in_layer_cell[i].set_fun(0);
            //初始化输入层阈值0.0
            pt_in_layer_cell[i].set_threshold(0.0);
        }

        //初始化隐藏层
        for (i = 0;i < num_hide_layer;i++)
        {
            pt_hide_layer_cell[i].set_in_num(num_in_layer);
            pt_hide_layer_cell[i].set_out_num(num_out_layer);
            pt_hide_layer_cell[i].set_fun(1);
        }

        //初始化输出层
        for (i = 0;i < num_out_layer;i++)
        {
            pt_out_layer_cell[i].set_in_num(num_hide_layer);
            pt_out_layer_cell[i].set_out_num(1);
            pt_out_layer_cell[i].set_fun(0);
            //初始化输出层权值1.0
            pt_out_layer_cell[i].set_w(1.0,0);
        }
    }
}

//设置输入层细胞数
void _BP_Net::set_num_in_layer(int num)
{
    num_in_layer = num;
}

//设置隐藏层细胞数
void _BP_Net::set_num_hide_layer(int num)
{
    num_hide_layer = num;
}

//设置输出层细胞数
void _BP_Net::set_num_out_layer(int num)
{
    int i = 0;

    num_out_layer = num;
    //初始化每层细胞指针
    pt_in_layer_cell = new _Cell[num_in_layer];
    pt_hide_layer_cell = new _Cell[num_hide_layer];
    pt_out_layer_cell = new _Cell[num_out_layer];

    //初始化每层细胞的输入,输出,传递函数类型
    //初始化输入层
    for (i = 0;i < num_in_layer;i++)
    {
        pt_in_layer_cell[i].set_in_num(1);
        pt_in_layer_cell[i].set_out_num(num_hide_layer);
        pt_in_layer_cell[i].set_fun(0);
        //初始化输入层阈值0.0
        pt_in_layer_cell[i].set_threshold(0.0);
    }

    //初始化隐藏层
    for (i = 0;i < num_hide_layer;i++)
    {
        pt_hide_layer_cell[i].set_in_num(num_in_layer);
        pt_hide_layer_cell[i].set_out_num(num_out_layer);
        pt_hide_layer_cell[i].set_fun(1);
    }

    //初始化输出层
    for (i = 0;i < num_out_layer;i++)
    {
        pt_out_layer_cell[i].set_in_num(num_hide_layer);
        pt_out_layer_cell[i].set_out_num(1);
        pt_out_layer_cell[i].set_fun(0);
        //初始化输出层权值1.0
        pt_out_layer_cell[i].set_w(1.0,0);
    }
}

//返回输入层细胞数
int _BP_Net::return_num_in_layer()
{
    return num_in_layer;
}

//返回隐藏层细胞数
int _BP_Net::return_num_hide_layer()
{
    return num_hide_layer;
}

//返回输出层细胞数
int _BP_Net::return_num_out_layer()
{
    return num_out_layer;
}

//返回权值
//i:层号,0输入层,1隐藏层,2输出层
//j:本层细胞号
//k:下一层细胞号
//失败返回-1
double _BP_Net::return_w(int i,int j,int k)
{
    switch (i)
    {
    case 0:
        {
            //输入层
            return pt_in_layer_cell[j].return_w(k);
            break;
        }
    case 1:
        {
            //隐藏层
            return pt_hide_layer_cell[j].return_w(k);
            break;
        }
    case 2:
        {
            //输出层
            return pt_out_layer_cell[j].return_w(k);
            break;
        }
    default:
        {
            return -1;
            break;
        }
    }
}

//返回阈值
//i:层号,0输入层,1隐藏层,2输出层
//j:本层细胞号
//失败返回-1
double _BP_Net::return_threshold(int i,int j)
{
    switch (i)
    {
    case 0:
        {
            //输入层
            return pt_in_layer_cell[j].return_threshold();
            break;
        }
    case 1:
        {
            //隐藏层
            return pt_hide_layer_cell[j].return_threshold();
            break;
        }
    case 2:
        {
            //输出层
            return pt_out_layer_cell[j].return_threshold();
            break;
        }
    default:
        {
            return -1;
            break;
        }
    }
}

//产生随机的权值,-1-1
void _BP_Net::set_rand_w()
{
    int i = 0;
    int j = 0;
    double temp = 0;

    //获取随机数种子
    srand((unsigned)time(NULL));

    //初始化输入层权值
    for (i = 0;i < num_in_layer;i++)
    {
        for (j = 0;j < pt_in_layer_cell[0].return_out_num();j++)
        {
            temp = (double)(rand() % 200 - 100) / 100.0;
            pt_in_layer_cell[i].set_w(temp,j);
        }
    }

    //初始化隐藏层权值
    for (i = 0;i < num_hide_layer;i++)
    {
        for (j = 0;j < pt_hide_layer_cell[0].return_out_num();j++)
        {
            temp = (double)(rand() % 200 - 100) / 100.0;
            pt_hide_layer_cell[i].set_w(temp,j);
        }
    }

    //初始化输出层权值
    //设置权值为1
    for (i = 0;i < num_out_layer;i++)
    {
        for (j = 0;j < pt_out_layer_cell[0].return_out_num();j++)
        {
            //temp = (double)(rand() % 200 - 100) / 100.0;
            pt_out_layer_cell[i].set_w(1.0,j);
        }
    }
}

//产生随机的阈值,-1-1
void _BP_Net::set_rand_threshold()
{
    int i = 0;
    double temp = 0;

    //获取随机数种子
    srand((unsigned)time(NULL));

    //初始化输入层阈值
    //设置为0
    for (i = 0;i < num_in_layer;i++)
    {
        pt_in_layer_cell[i].set_threshold(0.0);
    }

    //初始化隐藏层权值
    for (i = 0;i < num_hide_layer;i++)
    {
        temp = (double)(rand() % 200 - 100) / 100.0;
        pt_hide_layer_cell[i].set_threshold(temp);
    }

    //初始化输出层权值
    //设置权值为1
    for (i = 0;i < num_out_layer;i++)
    {
        temp = (double)(rand() % 200 - 100) / 100.0;
        pt_out_layer_cell[i].set_threshold(temp);
    }
}

//设置输入层权值
//a:权值,i:细胞号,j:细胞对应输出
void _BP_Net::set_in_layer_w(double a,int i,int j)
{
    pt_in_layer_cell[i].set_w(a,j);
}

//设置隐藏层权值
//a:权值,i:细胞号,j:细胞对应输出
void _BP_Net::set_hide_layer_w(double a,int i,int j)
{
    pt_hide_layer_cell[i].set_w(a,j);
}

//设置隐藏层阈值
//a:阈值,num:细胞号
void _BP_Net::set_hide_layer_threshold(double a,int num)
{
    pt_hide_layer_cell[num].set_threshold(a);
}

//设置输出层阈值
//a:阈值,num:细胞号
void _BP_Net::set_out_layer_threshold(double a,int num)
{
    pt_out_layer_cell[num].set_threshold(a);
}

//设置学习速率
void _BP_Net::set_g(double a)
{
    g = a;
}

//学习
//right为正确的值数组
void _BP_Net::study(double *right)
{
    int i = 0;
    int j = 0;
    int k = 0;
    double sum = 0.0;
    double temp = 0.0;

    //误差指针
    double *pt_e = new double[num_out_layer];
    //计算各个误差
    for (k = 0;k < num_out_layer;k++)
    {
        pt_e[k] = *right - pt_out_layer_cell[k].output_no_w();
        right++;
        //qDebug() << "wucha:" << pt_e[i];
    }

    //阈值更新
    //隐藏层阈值更新
    for (j = 0;j < num_hide_layer;j++)
    {
        sum = 0;
        //计算输出层节点输出误差和
        for (k = 0;k < num_out_layer;k++)
        {
            sum += pt_hide_layer_cell[j].return_w(k) * pt_e[k];
        }
        temp = pt_hide_layer_cell[j].return_threshold() + \
               g * pt_hide_layer_cell[j].output_no_w() * \
               (1 - pt_hide_layer_cell[j].output_no_w()) * sum;
        //qDebug() << "wucha:" << sum;
        //qDebug() << "yi qian de yu zhi" << pt_hide_layer_cell[j].return_threshold();
        //qDebug() << "xian zai de yu zhi" << temp;
        //qDebug() << "bu jia quan shu chu" << pt_hide_layer_cell[j].output_no_w();
        pt_hide_layer_cell[i].set_threshold(temp);
        //qDebug() << "hide threshold" << temp;
    }

    //输出层阈值更新
    for (k = 0;k < num_out_layer;k++)
    {
        temp = pt_out_layer_cell[k].return_threshold() + pt_e[k];
        pt_out_layer_cell[k].set_threshold(temp);
        //qDebug() << "out threshold" << temp;
    }

    //权值更新
    //输入层权值更新
    for (i = 0;i < num_in_layer;i++)
    {
        for (j = 0;j < num_hide_layer;j++)
        {
            sum = 0;
            //计算输出层节点输出误差和
            for (k = 0;k < num_out_layer;k++)
            {
                sum += pt_hide_layer_cell[j].return_w(k) * pt_e[k];
            }
            temp = pt_in_layer_cell[i].return_w(j) + \
                   g * pt_hide_layer_cell[j].output_no_w() * \
                   (1 - pt_hide_layer_cell[j].output_no_w()) * \
                   pt_in_layer_cell[i].return_in(0) * sum;
            //qDebug() << "wucha:" << sum;
            //qDebug() << "yi qian de quan zhi" << pt_in_layer_cell[i].return_w(j);
            //qDebug() << "xian zai de quan zhi" << temp;
            pt_in_layer_cell[i].set_w(temp,j);

            //qDebug() << "in w" << temp;
        }
    }

    //隐藏层权值更新
    for (j = 0;j < num_hide_layer;j++)
    {
        for (k = 0;k < num_out_layer;k++)
        {
            temp = pt_hide_layer_cell[j].return_w(k) + \
                   g * pt_hide_layer_cell[j].output_no_w() * pt_e[k];
            //qDebug() << "wucha:" << pt_e[j];
            //qDebug() << "yi qian de quan zhi" << pt_hide_layer_cell[i].return_w(j);
            //qDebug() << "xian zai de quan zhi" << temp;
            pt_hide_layer_cell[j].set_w(temp,k);

            //qDebug() << "hide w" << temp;
        }
    }
}

//计算输出
void _BP_Net::calc()
{
    int i = 0;
    int j = 0;
    int k = 0;

    //计算输入层细胞输出
    for (i = 0;i < num_in_layer;i++)
    {
        pt_in_layer_cell[i].calc();
    }

    //设置隐藏层细胞输入,并计算隐藏层细胞输出
    for (j = 0;j < num_hide_layer;j++)
    {
        for (i = 0;i < num_in_layer;i++)
        {
            pt_hide_layer_cell[j].set_in(pt_in_layer_cell[i].output(j),i);
        }
        pt_hide_layer_cell[j].calc();
    }

    //设置输出层细胞输入,并计算输出层细胞输出
    for (k = 0;k < num_out_layer;k++)
    {
        for (j = 0;j < num_hide_layer;j++)
        {
            pt_out_layer_cell[k].set_in(pt_hide_layer_cell[j].output(k),j);
        }
        pt_out_layer_cell[k].calc();
    }
}

//返回输出
double _BP_Net::output(int num)
{
    double temp = 0.0;
    temp = pt_out_layer_cell[num].output(0);
    return temp;
}

//设置输入层细胞输入
void _BP_Net::set_in(double a,int num)
{
    pt_in_layer_cell[num].set_in(a,0);
}

//全局函数定义
//归一化函数
//dst:目标数据
//min:最小值
//max:最大值
double mapminmax(double dst,double min,double max)
{
    double temp = 0;

    temp = (dst - min) / (max - min);
    return temp;
}

//反归一化
//dst:目标数据
//min:最小值
//max:最大值
double premapminmax(double dst,double min,double max)
{
    double temp = 0;

    temp = dst * (max - min) + min;
    return temp;
}

//加载权值
//dir:目录,bp_net:神经网络
//成功返回1,失败返回-1
int load_w(QString dir,_BP_Net *bp_net)
{
    QFile file(dir);
    QByteArray line;
    bool ok;
    int i = 0;
    int j = 0;
    int k = 0;
    double temp = 0.0;

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        return -1;
    }

    //读到末尾或者已经写完则退出
    //i指示层数
    i = 0;
    //j指示细胞号
    j = 0;
    //k指示目标细胞号
    k = 0;
    while (!file.atEnd())
    {
        //如果隐藏层全部赋值则退出
        if (i >= 2)
        {
            break;
        }

        //读取数据
        line = file.readLine();
        line.chop(1);
        temp = line.toDouble(&ok);
        if (ok == false)
        {
            return -1;
        }
        //赋值给输入层权值
        if (i == 0)
        {
            bp_net->set_in_layer_w(temp,j,k);
            k++;
            //如果超过最大目标细胞号,则开始本层下一个细胞
            if (k >= bp_net->return_num_hide_layer())
            {
                k = 0;
                j++;
            }
            //如果超过最大细胞号,则开始下一层
            if (j >= bp_net->return_num_in_layer())
            {
                j = 0;
                i++;
            }
            continue;
        }

        //赋值给隐藏层权值
        if (i == 1)
        {
            bp_net->set_hide_layer_w(temp,j,k);
            k++;
            //如果超过最大目标细胞号,则开始本层下一个细胞
            if (k >= bp_net->return_num_out_layer())
            {
                k = 0;
                j++;
            }
            //如果超过最大细胞号,则开始下一层
            if (j >= bp_net->return_num_hide_layer())
            {
                j = 0;
                i++;
            }
            continue;
        }
    }

    file.close();
    return 1;
}

//加载阈值
//dir:目录,bp_net:神经网络
//成功返回1,失败返回-1
int load_threshold(QString dir,_BP_Net *bp_net)
{
    QFile file(dir);
    QByteArray line;
    bool ok;
    int i = 0;
    int j = 0;
    double temp = 0.0;

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        return -1;
    }

    //读到末尾或者已经写完则退出
    //i指示层数
    i = 1;
    //j指示细胞号
    j = 0;
    while (!file.atEnd())
    {
        //如果输出层全部赋值则退出
        if (i >= 3)
        {
            break;
        }

        //读取数据
        line = file.readLine();
        line.chop(1);
        temp = line.toDouble(&ok);
        if (ok == false)
        {
            return -1;
        }
        //赋值给隐藏层阈值
        if (i == 1)
        {
            bp_net->set_hide_layer_threshold(temp,j);
            j++;
            //如果超过最大细胞号,则开始下一层
            if (j >= bp_net->return_num_hide_layer())
            {
                j = 0;
                i++;
            }
            continue;
        }

        //赋值给输出层阈值
        if (i == 2)
        {
            bp_net->set_out_layer_threshold(temp,j);
            j++;
            //如果超过最大细胞号,则开始下一层
            if (j >= bp_net->return_num_out_layer())
            {
                j = 0;
                i++;
            }
            continue;
        }
    }

    file.close();
    return 1;
}

//写入权值
//dir:目录,bp_net:神经网络
//成功返回1,失败返回-1
int write_w(QString dir,_BP_Net *bp_net)
{
    QFile file(dir);
    QByteArray line;
    int i = 0;
    int j = 0;
    int k = 0;

    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        return -1;
    }

    //i指示层数
    i = 0;
    //j指示细胞号
    j = 0;
    //k指示目标细胞号
    k = 0;
    while (1)
    {
        //如果隐藏层全部赋值则退出
        if (i >= 2)
        {
            break;
        }

        //读取数据
        line = QByteArray::number(bp_net->return_w(i,j,k));
        line.append('\n');
        //写入
        file.write(line);
        //判断输入层权值是否写完
        if (i == 0)
        {
            k++;
            //如果超过下层最大细胞号,则开始本层下一个细胞
            if (k >= bp_net->return_num_hide_layer())
            {
                k = 0;
                j++;
            }
            //如果超过本层最大细胞号,则开始下一层
            if (j >= bp_net->return_num_in_layer())
            {
                j = 0;
                i++;
            }
            continue;
        }

        //判断隐藏层权值是否写完
        if (i == 1)
        {
            k++;
            //如果超过最大目标细胞号,则开始本层下一个细胞
            if (k >= bp_net->return_num_out_layer())
            {
                k = 0;
                j++;
            }
            //如果超过最大细胞号,则开始下一层
            if (j >= bp_net->return_num_hide_layer())
            {
                j = 0;
                i++;
            }
            continue;
        }
    }

    file.close();
    return 1;
}

//写入阈值
//dir:目录,bp_net:神经网络
//成功返回1,失败返回-1
int write_threshold(QString dir,_BP_Net *bp_net)
{
    QFile file(dir);
    QByteArray line;
    int i = 0;
    int j = 0;

    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        return -1;
    }

    //i指示层数
    i = 1;
    //j指示细胞号
    j = 0;
    while (1)
    {
        //如果输出层全部赋值则退出
        if (i >= 3)
        {
            break;
        }

        //读取数据
        line = QByteArray::number(bp_net->return_threshold(i,j));
        line.append('\n');
        //写入
        file.write(line);
        //判断隐藏层权值是否写完
        if (i == 1)
        {
            j++;
            //如果超过本层最大细胞号,则开始下一层
            if (j >= bp_net->return_num_hide_layer())
            {
                j = 0;
                i++;
            }
            continue;
        }

        //判断输出层权值是否写完
        if (i == 2)
        {
            j++;
            //如果超过最大细胞号,则开始下一层
            if (j >= bp_net->return_num_out_layer())
            {
                j = 0;
                i++;
            }
            continue;
        }
    }

    file.close();
    return 1;
}

//读取正确的值,并且学习
//dir:目录,bp_net:神经网络
//成功返回1,失败返回-1
int study(QString dir,_BP_Net *bp_net)
{
    QFile file(dir);
    QByteArray line;
    bool ok;
    int i = 0;
    int j = 0;
    double temp = 0.0;
    double *pt_in;
    double *pt_right;
    //指示输入还是输出,0是输入,1是输出
    int flag = 0;

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        return -1;
    }

    //设置正确数组
    pt_in = new double[bp_net->return_num_in_layer()];
    pt_right = new double[bp_net->return_num_out_layer()];

    //读到末尾或者已经写完则退出
    //i指示细胞号
    i = 0;
    flag = 0;
    do
    {
        //如果到达文件尾,则退出
        if (file.atEnd())
        {
            break;
        }
        //读取数据
        line = file.readLine();
        line.chop(1);
        temp = line.toDouble(&ok);
        if (ok == false)
        {
            return -1;
        }
        if (flag == 0)
        {
            //输入
            pt_in[i++] = temp;
            //当输入层写完
            if (i >= bp_net->return_num_in_layer())
            {
                //开始工作,计算输出
                //设置输入
                for (j = 0;j < bp_net->return_num_in_layer();j++)
                {
                    bp_net->set_in(pt_in[j],j);
                }
                //计算输出
                bp_net->calc();
                //输出
                qDebug() << "out" << bp_net->output(0);

                //准备学习
                i = 0;
                flag = 1;
                continue;
            }
        }
        else
        {
            //输出
            pt_right[i++] = temp;
            //当输出层写完
            if (i >= bp_net->return_num_out_layer())
            {
                //开始学习
                bp_net->study(pt_right);

                //准备下一轮学习
                i = 0;
                flag = 0;
                continue;
            }
        }
    }while (1);

    file.close();
    return 1;
}


widget.c:测试程序

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    int i = 0;

    //初始化BP网络
    _BP_Net bp_net;
    //设置各层细胞数
    bp_net.set_num_in_layer(1);
    bp_net.set_num_hide_layer(10);
    bp_net.set_num_out_layer(1);
    //设置随机权值
    //bp_net.set_rand_w();
    //设置随机阈值
    //bp_net.set_rand_threshold();
    //设置阈值和权值
    load_w("w.txt",&bp_net);
    load_threshold("threshold.txt",&bp_net);


    //开始学习
    for (i = 0;i < 1;i++)
    {
        study("study.txt",&bp_net);
    }
    //学好后,写入新的权值和阈值
    write_w("w.txt",&bp_net);
    write_threshold("threshold.txt",&bp_net);


    //设置输入
    bp_net.set_in(0.3,0);
    //计算输出
    bp_net.calc();
    //输出
    qDebug() << "out:" << bp_net.output(0);

}

Widget::~Widget()
{
    delete ui;
}




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值