网络拓扑结构5-9-1读取数据库并训练预测
来源:互联网 发布:域名流量劫持 编辑:程序博客网 时间:2024/04/27 08:24
本文针对“网络拓扑结构5-3-1读取数据库并训练预测 ”做了如下改进:
1、网络的拓扑结构由5-3-1改为5-9-1,更加接近理论值“隐层节点个数=输入层节点个数*2-1”
2、先从数据库读取原始数据,之后进行归一化处理,而不是之前的顺便归一化。这样便于查看从数据库读取的数据是否准确可靠
3、添加了数据补偿的功能,若数据上报有丢失,用前6组(1小时)数据的平均值代替之
4、在训练的时候使用变量控制权值、阈值、误差、隐层数据的下标,而不是之前的硬性绑定。
:::数据背景和上次相同:::
package pa; import java.sql.*; public class BP{ public static int M=6; //记录条数 public static int N=6; //字段个数 public static double Data[][]=new double[M][N]; //从数据库中读取的原始数据,并归一化 public static double Max[]=new double[N]; //各个字段的最大值,归一化和反归一化时要用到 public static double Min[]=new double[N]; //各个字段的最小值,归一化和反归一化时要用到 public static double Step=0.6; //学习次数 public static int TrainTimes=800; public static int L0=5; //输入层节点数 public static int L1=9; //隐层节点数 public static int L2=1; //输出层节点数 public static double Weight01[][]=new double[L0][L1]; public static double Weight12[][]=new double[L1][L2]; public static double Threshold1[]=new double[L1]; public static double Threshold2[]=new double[L2]; /*函数说明 * public static void getData()//准备数据 * public static void reflect()//将数据归一化处理 * public static void checkData()//检验数据是否有丢失。若有,用前六组的数据补充 * public static void init()//初始化权值和阈值 * public static double transfer(double x)//传递函数 * public static double train(double i1 ,double i2,double i3, double i4,double i5,double d) * 训练函数。输入参数是归一化处理之后的数据,返回正向传播的结果 * public static double run(double i1,double i2,double i3,double i4,double i5) * 测试函数。输入参数是归一化处理之后的数据,返回值也是归一化的。和实际值进行比较,需要反归一化 * public static void print()//打印所有的权值和阈值 * public static void main(String[] args) //主函数,负责调用训练函数和测试函数,输出测试的结果 */ public static void getData() { //从数据库中读取 String driverName="com.mysql.jdbc.Driver";//驱动程序名 String userName="root";//数据库用户名 String userPasswd="xhp";//密码 String dbName="test";//数据库名 String tableName="table713";//表名 try { String url="jdbc:mysql://localhost/"+dbName+"?user="+userName+"&password="+userPasswd;//连接字符串 Class.forName(driverName); Connection connection=DriverManager.getConnection(url); Statement statement = connection.createStatement(); String sql="SELECT * FROM "+tableName+" where ID >=1"; ResultSet rs = statement.executeQuery(sql); for(int i=0;i<M;i++) { if(rs.next()) { Data[i][0]=Double.parseDouble(rs.getString("sun")); Data[i][1]=Double.parseDouble(rs.getString("temprature")); Data[i][2]=Double.parseDouble(rs.getString("airpress")); Data[i][3]=Double.parseDouble(rs.getString("PH")); Data[i][4]=Double.parseDouble(rs.getString("humidity")); Data[i][5]=Double.parseDouble(rs.getString("DO")); } } rs.close(); statement.close(); connection.close(); } catch(ClassNotFoundException e) { e.printStackTrace(); } catch(SQLException e) { e.printStackTrace(); } } public static void reflect() { //寻找每个字段的最大值最小值 for(int i=0;i<N;i++) { Max[i]=-32767; Min[i]=32767; for(int j=0;j<M;j++) { if(Data[j][i]>Max[i]) { Max[i]=Data[j][i]; } if(Data[j][i]<Min[i]) { Min[i]=Data[j][i]; } } } //归一化处理 for(int i=0;i<M;i++) { for(int j=0;j<N;j++) { Data[i][j]=(Data[i][j]-Min[j])/(Max[j]-Min[j]); } } } public static void checkData(){//若前6组数据有缺失的,就没有办法了(需要从数据库中重新读取,很费时间的)for(int i=6;i<M;i++){for(int j=0;j<N;j++){if(Data[i][j]==0){double temp=0;for(int k=1;k<=6;k++){temp+=Data[i-k][j];//从历史记录里面读取6组数据}Data[i][j]=(float)temp/6;//取平均值}}}} public static void printData() { for(int i=0;i<M;i++) { for(int j=0;j<N;j++) { System.out.print(Data[i][j]+" "); } System.out.println(); } } public static void init() { for(int i=0;i<L0;i++) { for(int j=0;j<L1;j++) { Weight01[i][j]=Math.random()*2-1; } } for(int i=0;i<L1;i++) { for(int j=0;j<L2;j++) { Weight12[i][j]=Math.random()*2-1; } } for(int i=0;i<L1;i++) { Threshold1[i]=Math.random()*2-1; } for(int i=0;i<L2;i++) { Threshold2[i]=Math.random()*2-1; } } public static double transfer(double x) { return 1/(1+Math.exp(-x)); } public static double train(double i1 ,double i2,double i3, double i4,double i5,double d) { double Input[]=new double[L0];//输入层单元 double Hide[]=new double[L1];//隐层单元 double out=0;//输出层的输出 //设置输入层的数值 Input[0]=i1; Input[1]=i2; Input[2]=i3; Input[3]=i4; Input[4]=i5; //计算隐含层的神经元值,隐层的输入 for(int i=0;i<L1;i++) { for(int j=0;j<L0;j++) { Hide[i]+=Input[j]*Weight01[j][i]; } Hide[i]+=Threshold1[i]; } //使用S函数,隐层的输出 for(int i=0;i<L1;i++) { Hide[i]=transfer(Hide[i]); } //计算输出层的值,输出层的输入 for(int i=0;i<L2;i++) { for(int j=0;j<L1;j++) { out+=Hide[j]*Weight12[j][i]; } out+=Threshold2[i]; } //使用S函数,输出层的输出 out=transfer(out); //计算误差,反向传播 double error1[]=new double[L1];//隐层的误差 double error2[]=new double[L2];//输出层的误差 //计算输出层的误差 error2[0]=out*(1-out)*(d-out); //计算隐层的误差 for(int i=0;i<L1;i++) { error1[i]=Hide[i]*(1-Hide[i])*(Weight12[i][0])*(error2[0]); } //调整阈值 ,正向调整 //调整隐层的阈值 for(int i=0;i<L1;i++) { Threshold1[i]+=Step*error1[i]; } //输出层的阈值 Threshold2[0]+=Step*error2[0]; //调整权值 //输入层和隐层之间的权值 for(int i=0;i<L0;i++) { for(int j=0;j<L1;j++) { Weight01[i][j]+=Step*Input[i]*error1[j]; } } //隐层和输出层之间的权值 for(int i=0;i<L1;i++) { Weight12[i][0]+=Step*Hide[i]*error2[0]; } return out; } public static double run(double i1,double i2,double i3,double i4,double i5) { double Hide[]=new double[L1]; double out=0; //计算隐层的输入 for(int i=0;i<L1;i++) { Hide[i]=1*Threshold1[i]+i1*Weight01[0][i]+i2*Weight01[1][i]+i3*Weight01[2][i]+i4*Weight01[3][i]+i5*Weight01[4][i]; } //计算隐层的输出 for(int i=0;i<L1;i++) { Hide[i]=transfer(Hide[i]); } //计算输出层的输入 for(int i=0;i<L2;i++) { for(int j=0;j<L1;j++) { out+=Hide[j]*Weight12[j][i]; } out+=Threshold2[i]; } //计算输出层的输出 return transfer(out); } public static void print() { System.out.println("权值Weight01:"); for(int i=0;i<L0;i++) { for(int j=0;j<L1;j++) { System.out.print(Weight01[i][j]+" "); } System.out.println(); } System.out.println("权值Weight12:"); for(int i=0;i<L1;i++) { for(int j=0;j<L2;j++) { System.out.print(Weight12[i][j]+" "); } System.out.println(); } System.out.println("阈值Threshold1:"); for(int i=0;i<L1;i++) { System.out.print(Threshold1[i]+" "); } System.out.println("\n阈值Threshold2:"); for(int i=0;i<L2;i++) { System.out.print(Threshold2[i]+" "); } System.out.println("\n权值阈值打印完毕!"); } public static void main(String[] args) { getData(); reflect(); init(); for(int i=0;i<TrainTimes;i++) { for(int j=0;j<M;j++) { train(Data[j][0],Data[j][1],Data[j][2],Data[j][3],Data[j][4],Data[j][5]); } } double result=run(Data[5][0],Data[5][1],Data[5][2],Data[5][3],Data[5][4]); result=result*(Max[5]-Min[5])+Min[5]; System.out.println("预测值:"+result); double act=Data[5][5]*(Max[5]-Min[5])+Min[5]; System.out.println("实际值:"+act); } }
运行结果(未打印权值阈值,也未跟踪数据。如需要,可直接调用printData()函数):
预测值:1789.2462399023625
实际值:1790.0
----------------------------------------------------------------------------------------------------------------------------------------------------------
重新找数据进行验证网络的功能
参考书:陈志泊等。数据仓库与数据挖掘。北京:清华大学出版社,2009.5
P196。
1、修改记录条数M=9,字段个数N=5(3个输入,2个输出,分别训练和测试);输入层节点个数L0=3,隐层节点个数L1=7。
2、重写getData()函数,直接绑定数据。
public static void getData() { Data[0][0]=19.96; Data[0][1]=35.86; Data[0][2]=8.27; Data[0][3]=4.71; Data[0][4]=19.96; Data[1][0]=19; Data[1][1]=36.79; Data[1][2]=8.54; Data[1][3]=3.82; Data[1][4]=19; Data[2][0]=20.06; Data[2][1]=34.74; Data[2][2]=8.06; Data[2][3]=4.87; Data[2][4]=20.06; Data[3][0]=18.72; Data[3][1]=34.65; Data[3][2]=8.22; Data[3][3]=4.56; Data[3][4]=18.72; Data[4][0]=20.42; Data[4][1]=30.16; Data[4][2]=7.04; Data[4][3]=4.07; Data[4][4]=20.42; Data[5][0]=17.08; Data[5][1]=34.22; Data[5][2]=8.35; Data[5][3]=3.68; Data[5][4]=17.08; Data[6][0]=17.38; Data[6][1]=36.41; Data[6][2]=8.76; Data[6][3]=3.84; Data[6][4]=17.38; Data[7][0]=19.53; Data[7][1]=35.72; Data[7][2]=8.24; Data[7][3]=3.97; Data[7][4]=19.53; Data[8][0]=19.96; Data[8][1]=36.09; Data[8][2]=8.27; Data[8][3]=4.32; Data[8][4]=19.96; }
3、重写train()函数
修改函数的参数和输入层的内容即可
public static double train(double i1 ,double i2,double i3,double d) { double Input[]=new double[L0];//输入层单元 double Hide[]=new double[L1];//隐层单元 double out=0;//输出层的输出 //设置输入层的数值 Input[0]=i1; Input[1]=i2; Input[2]=i3;……}
其余部分不变。因为是下标控制的。
4、重写run()函数
public static double run(double i1,double i2,double i3) { double Hide[]=new double[L1]; double out=0; //计算隐层的输入 for(int i=0;i<L1;i++) { Hide[i]=1*Threshold1[i]+i1*Weight01[0][i]+i2*Weight01[1][i]+i3*Weight01[2][i]; } //计算隐层的输出 for(int i=0;i<L1;i++) { Hide[i]=transfer(Hide[i]); } //计算输出层的输入 for(int i=0;i<L2;i++) { for(int j=0;j<L1;j++) { out+=Hide[j]*Weight12[j][i]; } out+=Threshold2[i]; } //计算输出层的输出 return transfer(out); }
5、在main()函数中进行第1个输出的预测
public static void main(String[] args) { getData(); printData(); reflect(); init(); System.out.print("训练并测试第1个输出\n"); for(int i=0;i<TrainTimes;i++) { for(int j=0;j<M-1;j++)//训练前8个样本 { train(Data[j][0],Data[j][1],Data[j][2],Data[j][3]); //注意期望输出是第4列 } } double result=run(Data[8][0],Data[8][1],Data[8][2]); //测试第9个样本 result=result*(Max[3]-Min[3])+Min[3]; System.out.println("预测值:"+result); double act=Data[8][3]*(Max[3]-Min[3])+Min[3]; System.out.println("实际值:"+act); }
6、第1个测试的运行结果
训练并测试第1个输出
预测值:4.430013110096122
实际值:4.32
::::看来结果还是不错滴,哈哈~
7、在main()函数中进行第2个输出的预测
public static void main(String[] args) { getData(); printData(); reflect(); init(); System.out.print("训练并测试第2个输出\n"); for(int i=0;i<TrainTimes;i++) { for(int j=0;j<M-1;j++)//训练前8个样本 { train(Data[j][0],Data[j][1],Data[j][2],Data[j][4]); //注意期望输出是第5列 } } double result=run(Data[8][0],Data[8][1],Data[8][2]); //测试第9个样本 result=result*(Max[4]-Min[4])+Min[4]; System.out.println("预测值:"+result); double act=Data[8][4]*(Max[4]-Min[4])+Min[4]; System.out.println("实际值:"+act); }
8、第2个测试的运行结果
训练并测试第2个输出
预测值:19.92995445524996
实际值:19.96
:::结果也是不错滴,第2次哈哈~
总结:
所有样本(包括用于测试的样本)进行归一化,取得最大值和最小值。
前8个样本参与训练,后一个样本参与测试。
测试的结果需要反归一化,反归一化需要该列的max和min,这些在归一化的过程中得到。实际值本身也参加的最大值和最小值的筛选。
为什么在这样的环境下就可以,在yx实际报上来的数据中运行就是不行呢??
- 网络拓扑结构5-9-1读取数据库并训练预测
- 网络拓扑结构5-9-1读取数据库并训练预测(实际数值)
- 网络拓扑结构5-3-1读取数据库并训练预测
- caffe2 学习笔记04-训练网络并进行预测
- 网络的拓扑结构
- 常见网络拓扑结构
- 网络拓扑结构
- 8网络拓扑结构
- ZigBee网络拓扑结构
- 网络拓扑结构
- 网络拓扑结构
- 网络拓扑结构
- 网络拓扑结构
- 网络拓扑结构
- 网络的拓扑结构
- 读取网络中的数据并写入数据库
- iris数据集的读取,训练,预测
- caffe训练模型并预测图片类型
- Centos YUM源 中国科技大学镜像
- Love is gone
- 面向接口编程的作用
- makefile进入子文件夹执行make
- javascript 浏览器兼容性心得
- 网络拓扑结构5-9-1读取数据库并训练预测
- JAVA 中 验证IP的有效性
- Zookeeper全解析——Client端
- 红黑树
- 网络socket编程指南之一
- 软件质量概述
- 弹出窗口总结
- 摄像机防穿帮virtools思路实现
- CFileDialog中的控件子类化问题