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


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

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

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

    @attribute outlook {sunny, overcast, rainy}
    @attribute temperature numeric
    @attribute humidity numeric
    @attribute windy {TRUE, FALSE}
    @attribute play {yes, no}
    sunny,85,85,FALSE,no
    sunny,80,90,TRUE,no
    overcast,83,86,FALSE,yes
    rainy,70,96,FALSE,yes
    rainy,68,80,FALSE,yes
    rainy,65,70,TRUE,no
    overcast,64,65,TRUE,yes
    sunny,72,95,FALSE,no
    sunny,69,70,FALSE,yes
    rainy,75,80,FALSE,yes
    sunny,75,70,TRUE,yes
    overcast,72,90,TRUE,yes
    overcast,81,75,FALSE,yes
    rainy,71,91,TRUE,no
    此数据參考weka自带数据weather.arff,并且数据格式,比方写上@attribute 等都是參考weka的数据格式来的。以下代码中使用的数据格式如上所述,其格式描写叙述例如以下:1)前m行以@attribute开头,代码m个属性。当中最后一个为目标属性;2)假设属性是数值型,则在attribute后面空格跟属性名,再空格跟numeric;假设是离散型。那么attribute后面空格跟属性名。再空格使用大括号把离散值括起来,离散值用逗号分隔;3)目标属性必须是离散型的(关于目标属性应该一定要属于离散型的这点要求,事实上仅仅是我代码里面这样说而已,一般的HotSpot算法并没有这个要求。

    假设目标属性一定要求是连续型的,能够在lz代码基础上进行改动)。

    2. 数据读取

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

    其读代替码例如以下所看到的:

    while ((tempString = reader.readLine()) != null) {
    				// 第一行数据是标题
    				if (tempString.indexOf(HSUtils.FILEFORMAT) == 0) {
    
    					String attr = "";
    					String[] attrStates = null;
    					if (tempString.contains("{")) {
    						attr = tempString.substring(
    								HSUtils.FILEFORMAT.length(),
    								tempString.indexOf("{")).trim();
    						attrStates = tempString.substring(
    								tempString.indexOf("{") + 1,
    								tempString.indexOf("}")).split(",");
    						for (int i = 0; i < attrStates.length; i++) {
    							attrStates[i] = attrStates[i].trim();
    						}
    						numericList.add(false);
    						this.attributeStates.put(attr, attrStates);// 在这里加入就可以
    					} else {// numeric
    						if (tempString.contains("numeric")) {
    							attr = tempString.substring(
    									HSUtils.FILEFORMAT.length(),
    									tempString.indexOf("numeric")).trim();
    							numericList.add(true);
    						} else {
    							// error 数据格式错误
    							throw new Exception("数据格式错误,请检查!");
    						}
    
    					}
    					attrList.add(attr);
    					line++;
    
    					continue;
    				}
    				if (flag) {
    					this.attributes = new String[line];
    					this.isNumeric = new Boolean[line];
    					attrList.toArray(this.attributes);// 复制值到数组中
    					numericList.toArray(this.isNumeric);
    					flag = false;
    				}
    				String[] tempStrings = tempString.split(splitter);
    				lists.add(strArr2IntArr(tempStrings));
    			}
    这里仅仅贴了while循环里面的代码,这里的代码即针对前面描写叙述的数据格式规则进行变量初始化(事实上,这里使用List存储转换后的数据。通常是能够使用数组来存储的。把List的数据转为数组就可以。这样在后面的操作中能够更快。假设要优化。能够从这方面入手)。

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

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

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

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

    /**
    	 * 依据attrIndex进行排序,attrIndex必须是numeric的 此方法可能须要优化
    	 * List 使用数组是否更快? 能够考虑使用数组
    	 * @param intData
    	 * @param attrIndex
    	 * @return
    	 */
    	private List<float[]> sortBasedOnAttr(List<float[]> intData, final int attrIndex) {
    		
    		float[][] tmpData = new float[intData.size()][];
    		intData.toArray(tmpData);
    
    		Arrays.sort(tmpData,new Comparator<float[]>(){
    			@Override
    			public int compare(float[] o1, float[] o2) {
    				if(o1[attrIndex]==o2[attrIndex]){
    					return 0;
    				}
    				return o1[attrIndex]>o2[attrIndex]?1:-1;
    			}
    			
    		});
    		List<float[]> returnList = new ArrayList<float[]>();
    		for (int i = 0; i < tmpData.length; i++) {
    			returnList.add(tmpData[i]);
    		}
    		return returnList;
    	}
    同一时候,在递归构建孩子节点时,生成节点规则时,针对数值型和离散型其生成方式也是不同的。例如以下:

    double[] newSplitVals = splitVals.clone();
    			byte[] newTests = tests.clone();
    			newSplitVals[attrStateSup.getAttrIndex()] = attrStateSup
    					.getStateIndex() + 1;
    			newTests[attrStateSup.getAttrIndex()] = isNumeric[attrStateSup.getAttrIndex()]?
    				attrStateSup.isLessThan()?(byte)1:(byte)3:(byte) 2;
    
    			HotSpotHashKey key = new HotSpotHashKey(newSplitVals, newTests);
    在递归构建孩子节点时,使用的子数据集的生成方式也须要进行调整,例如以下:

    /**
    	 * 获取和splitAttributeIndex相同下标的属性以及stateIndex的全部数据
    	 * 
    	 * @param intData
    	 * @param splitAttributeIndex
    	 * @param splitValue
    	 * @return
    	 */
    	private List<float[]> getSubData(List<float[]> intData,
    			int splitAttributeIndex, float splitValue,boolean lessThan) {
    		List<float[]> subData = new ArrayList<float[]>();
    		for (float[] d : intData) {
    			if(isNumeric[splitAttributeIndex]){
    				if(lessThan){
    					if (d[splitAttributeIndex] <= splitValue) {
    		                subData.add(d);
    		            }
    				}else{
    					if (d[splitAttributeIndex] > splitValue) {
    		                subData.add(d);
    		            }
    				}
    			}else{
    				if (d[splitAttributeIndex] == splitValue) {
    					subData.add(d);
    				}
    			}
    		}
    		return subData;
    	}
    

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

    /**
    	 * 格式化输出
    	 */
    	public String toString(){
    		String tmp = HSUtils.isNumeric(splitAttrIndex)?this.lessThan?

    " <= ":" > ":" = "; String attrState = HSUtils.isNumeric(splitAttrIndex)?

    String.valueOf(this.attrStateIndex): HSUtils.getAttrState(splitAttrIndex, (int)attrStateIndex); return HSUtils.getAttr(this.splitAttrIndex)+tmp +attrState +" ("+HSUtils.formatPercent(this.support)+" ["+this.stateCount+"/"+this.allCount+"])"; }


    在打印关联规则树时。相同须要推断当前的属性是离散型还是连续型的。


    代码输出为:

    文件读取完毕。且属性和属性的各种状态初始化完毕!
    属性outlook的状态:	[sunny-->0,overcast-->1,rainy-->2,]
    属性temperature的状态:	[numeric]
    属性humidity的状态:	[numeric]
    属性windy的状态:	[TRUE-->0,FALSE-->1,]
    属性play的状态:	[yes-->0,no-->1,]
    
    规则树例如以下:
    
    play = no  (35.71% [5/14])
    |	temperature > 83.0  (100.00% [1/1])
    |	humidity > 90.0  (66.67% [2/3])
    |	|	temperature > 70.0  (100.00% [2/2])
    |	|	humidity <= 95.0  (100.00% [2/2])
    



    分享。成长,快乐

    脚踏实地,专注

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



  • 相关阅读:
    【JavaScript】关于javascript原型的深入理解
    【JavaScript】关于JS中的constructor与prototype
    【JavaScript】关于prototype
    【JavaScript】重温Javascript继承机制
    【JavaScript】新浪微博ajax请求后改变地址栏url,但页面不跳转的方案解析
    【JavaScript】JavaScript函数的参数
    【JavaScript】页面加载性能优化
    HTML5 修改浏览器url而不刷新页面
    【339】matplotlib based on python3
    【338】Pandas.DataFrame
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5094984.html
Copyright © 2020-2023  润新知