你好,游客 登录 注册 搜索
背景:
阅读新闻

HotSpot关联规则算法(2)-- 挖掘连续型和离散型数据

[日期:2015-03-19] 来源:  作者: [字体: ]

本篇代码可在 http://download.csdn.net/detail/fansy1990/8502323下载。

前篇《HotSpot关联规则算法(1)-- 挖掘离散型数据》分析了离散型数据的HotSpot关联规则,本篇分析离散型和连续型数据的HotSpot关联规则挖掘。

1. 首先看下数据格式(txt文档):

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @attribute outlook {sunny, overcast, rainy} 
  2. @attribute temperature numeric 
  3. @attribute humidity numeric 
  4. @attribute windy {TRUE, FALSE} 
  5. @attribute play {yes, no} 
  6. sunny,85,85,FALSE,no 
  7. sunny,80,90,TRUE,no 
  8. overcast,83,86,FALSE,yes 
  9. rainy,70,96,FALSE,yes 
  10. rainy,68,80,FALSE,yes 
  11. rainy,65,70,TRUE,no 
  12. overcast,64,65,TRUE,yes 
  13. sunny,72,95,FALSE,no 
  14. sunny,69,70,FALSE,yes 
  15. rainy,75,80,FALSE,yes 
  16. sunny,75,70,TRUE,yes 
  17. overcast,72,90,TRUE,yes 
  18. overcast,81,75,FALSE,yes 
  19. rainy,71,91,TRUE,no 

此 数据参考weka自带数据weather.arff,而且数据格式,比如写上@attribute 等都是参考weka的数据格式来的。下面代码中使用的数据格式如上所述,其格式描述如下:1)前m行以@attribute开头,代码m个属性,其中最后 一个为目标属性;2)如果属性是数值型,则在attribute后面空格跟属性名,再空格跟numeric;如果是离散型,那么attribute后面空 格跟属性名,再空格使用大括号把离散值括起来,离散值用逗号分隔;3)目标属性必须是离散型的(关于目标属性应该一定要属于离散型的这点要求,其实只是我 代码里面这样说而已,一般的HotSpot算法并没有这个要求。如果目标属性一定要求是连续型的,可以在lz代码基础上进行修改)。

2. 数据读取

《HotSpot关联规则算法(1)》中的数据读取是针对离散型的数据的,所以需要进行修改,这里修改后只针对离散型数据进行编码,连续型数据保持即可,同时还需设置一个布尔数组指明属性列属于离散型还是连续型。其读取代码如下所示:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. while ((tempString = reader.readLine()) != null) { 
  2.                 // 第一行数据是标题 
  3.                 if (tempString.indexOf(HSUtils.FILEFORMAT) == 0) { 
  4.  
  5.                     String attr = ""
  6.                     String[] attrStates = null
  7.                     if (tempString.contains("{")) { 
  8.                         attr = tempString.substring( 
  9.                                 HSUtils.FILEFORMAT.length(), 
  10.                                 tempString.indexOf("{")).trim(); 
  11.                         attrStates = tempString.substring( 
  12.                                 tempString.indexOf("{") + 1
  13.                                 tempString.indexOf("}")).split(","); 
  14.                         for (int i = 0; i < attrStates.length; i++) { 
  15.                             attrStates[i] = attrStates[i].trim(); 
  16.                         } 
  17.                         numericList.add(false); 
  18.                         this.attributeStates.put(attr, attrStates);// 在这里添加即可 
  19.                     } else {// numeric 
  20.                         if (tempString.contains("numeric")) { 
  21.                             attr = tempString.substring( 
  22.                                     HSUtils.FILEFORMAT.length(), 
  23.                                     tempString.indexOf("numeric")).trim(); 
  24.                             numericList.add(true); 
  25.                         } else { 
  26.                             // error 数据格式错误 
  27.                             throw new Exception("数据格式错误,请检查!"); 
  28.                         } 
  29.  
  30.                     } 
  31.                     attrList.add(attr); 
  32.                     line++; 
  33.  
  34.                     continue
  35.                 } 
  36.                 if (flag) { 
  37.                     this.attributes = new String[line]; 
  38.                     this.isNumeric = new Boolean[line]; 
  39.                     attrList.toArray(this.attributes);// 复制值到数组中 
  40.                     numericList.toArray(this.isNumeric); 
  41.                     flag = false
  42.                 } 
  43.                 String[] tempStrings = tempString.split(splitter); 
  44.                 lists.add(strArr2IntArr(tempStrings)); 
  45.             } 

这里只贴了while循环里面的代码,这里的代码即针对前面描述的数据格式规则进行变量初始化(其实,这里使用List存储转换后的数据,一般是可以使用数组来存储的,把List的数据转为数组即可,这样在后面的操作中可以更快,如果要优化,可以从这方面入手)。

3.  HotSpot关联规则树的节点定义说明:

由于这里增加了连续型属性数据,所以针对单个节点需增加一个布尔型变量lessThan,用于指明是要大于或者小于该节点数据,同时stateIndex应该是一个数值了(当前节点的值),而不是离散型数据状态的下标了。

4. 算法伪代码(建树过程)

在 算法伪代码中的计算潜在节点时,针对连续型变量使用不同的方法,在weka源码中使用方法:evaluateNumeric来进行判断。在lz的代码中此 部分是完全参考源码中的代码的,不过有一点就是在调用evaluateNumeric这个算法后,会针对某一列进行排序,即一个二维数组按某列进行全局排 序。这个方法在weka源码中是使用Instances的quickSort方法进行排序的(使用了递归,没仔细看)。这里lz则是直接把List转为二 维数组然后进行排序的,其方法如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.      * 根据attrIndex进行排序,attrIndex必须是numeric的 此方法可能需要优化 
  3.      * List 使用数组是否更快? 可以考虑使用数组 
  4.      * @param intData 
  5.      * @param attrIndex 
  6.      * @return 
  7.      */ 
  8.     private List<float[]> sortBasedOnAttr(List<float[]> intData, final int attrIndex) { 
  9.          
  10.         float[][] tmpData = new float[intData.size()][]; 
  11.         intData.toArray(tmpData); 
  12.  
  13.         Arrays.sort(tmpData,new Comparator<float[]>(){ 
  14.             @Override 
  15.             public int compare(float[] o1, float[] o2) { 
  16.                 if(o1[attrIndex]==o2[attrIndex]){ 
  17.                     return 0
  18.                 } 
  19.                 return o1[attrIndex]>o2[attrIndex]?1:-1
  20.             } 
  21.              
  22.         }); 
  23.         List<float[]> returnList = new ArrayList<float[]>(); 
  24.         for (int i = 0; i < tmpData.length; i++) { 
  25.             returnList.add(tmpData[i]); 
  26.         } 
  27.         return returnList; 
  28.     } 

同时,在递归构建孩子节点时,生成节点规则时,针对数值型和离散型其生成方式也是不同的,如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. double[] newSplitVals = splitVals.clone(); 
  2.             byte[] newTests = tests.clone(); 
  3.             newSplitVals[attrStateSup.getAttrIndex()] = attrStateSup 
  4.                     .getStateIndex() + 1
  5.             newTests[attrStateSup.getAttrIndex()] = isNumeric[attrStateSup.getAttrIndex()]? 
  6.                 attrStateSup.isLessThan()?(byte)1:(byte)3:(byte2
  7.  
  8.             HotSpotHashKey key = new HotSpotHashKey(newSplitVals, newTests); 

在递归构建孩子节点时,使用的子数据集的生成方式也需要进行调整,如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.      * 获取和splitAttributeIndex相同下标的属性以及stateIndex的所有数据 
  3.      *  
  4.      * @param intData 
  5.      * @param splitAttributeIndex 
  6.      * @param splitValue 
  7.      * @return 
  8.      */ 
  9.     private List<float[]> getSubData(List<float[]> intData, 
  10.             int splitAttributeIndex, float splitValue,boolean lessThan) { 
  11.         List<float[]> subData = new ArrayList<float[]>(); 
  12.         for (float[] d : intData) { 
  13.             if(isNumeric[splitAttributeIndex]){ 
  14.                 if(lessThan){ 
  15.                     if (d[splitAttributeIndex] <= splitValue) { 
  16.                         subData.add(d); 
  17.                     } 
  18.                 }else
  19.                     if (d[splitAttributeIndex] > splitValue) { 
  20.                         subData.add(d); 
  21.                     } 
  22.                 } 
  23.             }else
  24.                 if (d[splitAttributeIndex] == splitValue) { 
  25.                     subData.add(d); 
  26.                 } 
  27.             } 
  28.         } 
  29.         return subData; 
  30.     } 


节点的toString 方法,用于打印HotSpot关联规则树

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /** 
  2.      * 格式化输出 
  3.      */ 
  4.     public String toString(){ 
  5.         String tmp = HSUtils.isNumeric(splitAttrIndex)?this.lessThan?" <= ":" > ":" = "
  6.         String attrState = HSUtils.isNumeric(splitAttrIndex)?String.valueOf(this.attrStateIndex): 
  7.             HSUtils.getAttrState(splitAttrIndex, (int)attrStateIndex); 
  8.         return HSUtils.getAttr(this.splitAttrIndex)+tmp 
  9.                 +attrState 
  10.                 +"  ("+HSUtils.formatPercent(this.support)+" ["+this.stateCount+"/"+this.allCount+"])"
  11.     } 


在打印关联规则树时,同样需要判断当前的属性是离散型还是连续型的。

代码输出为:

[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. 文件读取完成,且属性和属性的各种状态初始化完成! 
  2. 属性outlook的状态:   [sunny-->0,overcast-->1,rainy-->2,] 
  3. 属性temperature的状态:   [numeric] 
  4. 属性humidity的状态:  [numeric] 
  5. 属性windy的状态: [TRUE-->0,FALSE-->1,] 
  6. 属性play的状态:  [yes-->0,no-->1,] 
  7.  
  8. 规则树如下: 
  9.  
  10. play = no  (35.71% [5/14]) 
  11. |   temperature > 83.0  (100.00% [1/1]) 
  12. |   humidity > 90.0  (66.67% [2/3]) 
  13. |   |   temperature > 70.0  (100.00% [2/2]) 
  14. |   |   humidity <= 95.0  (100.00% [2/2]) 




分享,成长,快乐

脚踏实地,专注

转载请注明blog地址:http://blog.csdn.net/fansy1990





收藏 推荐 打印 | 录入:Cstor | 阅读:
相关新闻       关联规则算法 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数
点评:
       
评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款