上个学期,自己做的课题研究车流量及数量的预测。本人是通过BP神经网络实现的,精度也提高了不少。无奈组员有其他事务现在停止研究了。希望能找到有缘人,也可以一起实现!
起初我先通过matlab模拟的BP函数来研究精度,下面是我实现中期的Java代码和测试数据(我收集的是每隔十分钟的数据,然后以前2小时的数据经过归一化处理后实现的预测后一个小时,下面的是实现代码,我并没有贴出BP的核心代码,如果有需要可以私聊)
import java.util.Arrays;
import java.math.*;
public class MyBPtest1{
public static void main(String[] args){
因为我们设定了输入层为2,才会有两个输入({,},{,}}这样的东西;同理输入层也为如此
所以说如果是5个输入,一个输出对于data就{{,,,,},{,,,,}。。。。。。};;;;;对于target{,,,,}
double cheweisum=500;//车位总量
double[][] yuandata = new double[][]{
{192,195,194,193,193,195,201,205,205,203,203,202},
{195,194,193,193,195,201,205,205,203,203,202,206},
{194,193,193,195,201,205,205,203,203,202,206,204},
{193,193,195,201,205,205,203,203,202,206,204,204},
{193,195,201,205,205,203,203,202,206,204,204,203},
{195,201,205,205,203,203,202,206,204,204,203,199},
{201,205,205,203,203,202,206,204,204,203,199,195},
{205,205,203,203,202,206,204,204,203,199,195,182},
{205,203,203,202,206,204,204,203,199,195,182,179},
{203,203,202,206,204,204,203,199,195,182,179,178},
{203,202,206,204,204,203,199,195,182,179,178,176},
{202,206,204,204,203,199,195,182,179,178,176,175},
{206,204,204,203,199,195,182,179,178,176,175,173}
};
double[][] yuantarget = new double[][]{
{206,204,204,203,199,195},{204,204,203,199,195,182},
{204,203,199,195,182,179},{203,199,195,182,179,178},
{199,195,182,179,178,176},{195,182,179,178,176,175},
{182,179,178,176,175,173},{179,178,176,175,173,175},
{178,176,175,173,175,182},{176,175,173,175,182,183},
{175,173,175,182,183,185},{173,175,182,183,185,179},
{175,182,183,185,179,182}};
///找出归一化的最大值和最小值 datamax,datamin
double datamax=0;double datamin=cheweisum;
datamax=findmax(yuandata);
datamin=findmin(yuandata);
System.out.printf("datamax:%.2f datamin:%.2f\n",datamax,datamin);
///把数据结果放在0-1之间(归一化),,,设置目标数据测试目标 归一化
double[][] data=new double[yuandata.length][yuandata[0].length];
data=guiyihua(yuandata,datamax,datamin);
double[][] target=new double[yuantarget.length][yuantarget[0].length];
target=guiyihua(yuantarget,datamax,datamin);
//初始化神经网络的基本配置
//第一个参数是一个整型数组,表示神经网络的层数和每层节点数,比如{3,10,10,10,10,2}表示输入层是3个节点,输出层是2个节点,中间有4层隐含层,每层10个节点
/第二个参数是学习步长(过小会使收敛速度太慢;过大则会使预测不准,跳过一些细节)。。。。第三个参数是动量系数(使波动小的预测重新振荡起来)
BpDeep bp = new BpDeep(new int[]{12,9,6}, 0.15, 0.9);
//迭代训练5000次 /这里我们没有设置训练到了某一精确度自动停止,而是实打实的训练这些次数
for(int n=0;n<5000;n++)
for(int i=0;i<data.length;i++)
bp.train(data[i], target[i]);
//根据训练结果来检验样本数据,并算出概率 1,2,3,4,5,6分别对应接下来的6个输出
double avg1=0;double avg2=0;double avg3=0;double avg4=0; double avg5=0; double avg6=0;
for(int j=0;j<data.length;j++){
double[] result = bp.computeOut(data[j]);
获得原数据result,即结果不是0-1的数
double[] yuanresult=new double[result.length];
for(int s=0;s<result.length;s++){
yuanresult[s]=result[s]*(datamax-datamin)+datamin;
}
double piancha1=Math.abs((yuanresult[0]-yuantarget[j][0]))/yuantarget[j][0]*100; avg1=avg1+piancha1;
double piancha2=Math.abs((yuanresult[1]-yuantarget[j][1]))/yuantarget[j][1]*100; avg2=avg2+piancha2;
double piancha3=Math.abs((yuanresult[2]-yuantarget[j][2]))/yuantarget[j][2]*100; avg3=avg3+piancha3;
double piancha4=Math.abs((yuanresult[3]-yuantarget[j][3]))/yuantarget[j][3]*100; avg4=avg4+piancha4;
double piancha5=Math.abs((yuanresult[4]-yuantarget[j][4]))/yuantarget[j][4]*100; avg5=avg5+piancha5;
double piancha6=Math.abs((yuanresult[5]-yuantarget[j][5]))/yuantarget[j][5]*100; avg6=avg6+piancha6;
//输出示例 函数
System.out.println("函数自拟和过程");
outputss(yuandata,yuantarget,yuanresult,j,piancha1,piancha2,piancha3,piancha4,piancha5,piancha6);
}
avg1=avg1/data.length;avg2=avg2/data.length;avg3=avg3/data.length;
avg4=avg4/data.length;avg5=avg5/data.length;avg6=avg6/data.length;
System.out.printf("多次模拟样本之后的平均预测准确偏差率:%.4f %.4f %.4f %.4f %.4f %.4f\n",
avg1,avg2,avg3,avg4,avg5,avg6);
前者是对自己做测试后者对新的数据做测试
double[][] yuanxxs=new double[][]{
{193,194,193,192,192,196,200,204,201,207,201,202},
{194,193,192,192,196,200,204,201,207,201,202,202},
{193,192,192,196,200,204,201,207,201,202,202,201},
{192,192,196,200,204,201,207,201,202,202,201,203},
{192,196,200,204,201,207,201,202,202,201,203,200},
{196,200,204,201,207,201,202,202,201,203,200,192},
{200,204,201,207,201,202,202,201,203,200,192,197},
{204,201,207,201,202,202,201,203,200,192,197,185},
{201,207,201,202,202,201,203,200,192,197,185,176},
{207,201,202,202,201,203,200,192,197,185,176,175},
{201,202,202,201,203,200,192,197,185,176,175,178},
{202,202,201,203,200,192,197,185,176,175,178,184},
{202,201,203,200,192,197,185,176,175,178,184,171}
};
double[][] yuanxxt=new double[][]{
{202,201,203,200,192,197},{201,203,200,192,197,185},
{203,200,192,197,185,176},{200,192,197,185,176,175},
{192,197,185,176,175,178},{197,185,176,175,178,184},
{185,176,175,178,184,171},{176,175,178,184,171,178},
{175,178,184,171,178,180},{178,184,171,178,180,181},
{184,171,178,180,181,186},{171,178,180,181,186,172},
{178,180,181,186,172,184}
};
double[][] xxs=new double[yuanxxs.length][yuanxxs[0].length];
xxs=guiyihua(yuanxxs,datamax,datamin);
double[][] xxt=new double[yuanxxt.length][yuanxxt[0].length];
xxt=guiyihua(yuanxxt,datamax,datamin);
//根据训练结果来预测一条新数据的分类,现在先不讨论这一步
double[] x = new double[]{192,195,194,193,193};
// double[] result = bp.computeOut(x);
// System.out.println(Arrays.toString(x)+":"+Arrays.toString(result));
}
public static double findmin(double[][] a){
double min=10000;//取一个较大的值
for(int m=0;m<a.length;m++){
for(int n=0;n<a[m].length;n++){
if(min>a[m][n]) min=a[m][n];
}
}
return min;
}
public static double findmax(double[][] a){
double max=0;//取一个较小的值
for(int m=0;m<a.length;m++){
for(int n=0;n<a[m].length;n++){
if(max<a[m][n]) max=a[m][n];
}
}
return max;
}
public static double[][] guiyihua(double[][] yuana,double max,double min){
double[][] a=new double[yuana.length][yuana[0].length];
for(int m=0;m<yuana.length;m++){
for(int n=0;n<yuana[m].length;n++){
a[m][n]=Math.abs(yuana[m][n]-min)/(max-min);
}
}
return a;
}
public static void outputss(double[][] yuandata,double[][] yuantarget,double[] yuanresult,
int j,double piancha1,double piancha2,double piancha3,
double piancha4,double piancha5,double piancha6){
/在这里根据以后的偏差值,来继续加 ,“预测较好”、“预测正常”、“预测结果不好”(根据用户节选时间,例几点 或 第一个输出结果来预测)
///String cheweitishi="";
///if(yuanresult[0]/cheweisum<0.01) cheweitishi="无车位剩余";
///else if(yuanresult[0]/cheweisum>=0.01&&yuanresult[0]/cheweisum<0.06) cheweitishi="剩余车位不多了";
///else if(yuanresult[0]/cheweisum>=0.06&&yuanresult[0]/cheweisum<0.16) cheweitishi="还有一部分车位";
///else cheweitishi="剩余车位充足";
输出示例
System.out.println(Arrays.toString(yuandata[j]));
System.out.printf("原目标--%.4f %.4f %.4f %.4f %.4f %.4f\n",yuantarget[j][0],yuantarget[j][1],
yuantarget[j][2],yuantarget[j][3],yuantarget[j][4],yuantarget[j][5]);
System.out.printf("现结果--%.4f %.4f %.4f %.4f %.4f %.4f\n",
yuanresult[0],yuanresult[1],yuanresult[2],yuanresult[3],yuanresult[4],yuanresult[5]);
System.out.printf("偏差1-%.4f 偏差2-%.4f 偏差3-%.4f 偏差4-%.4f 偏差5-%.4f 偏差6-%.4f\n\n",
piancha1,piancha2,piancha3,piancha4,piancha5,piancha6);
}
}