初探神经网络: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;
}