weka中的J48

这段代码展示了Weka中J48决策树算法如何处理数值型属性。它首先创建一个分布来存储实例,然后遍历已排序的实例,将非缺失值的实例分配到分布的其中一个袋中。接着,它寻找最优的分裂点,通过比较信息增益来确定最佳划分。如果找不到满足最小样本数的分裂点,则不进行划分。最后,根据分裂点更新分布并计算信息增益和增益率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<pre name="code" class="java">private void handleNumericAttribute(Instances trainInstances)  
<span style="white-space:pre">	</span>throws Exception {  
		   
	int firstMiss;//最后一个有效instance的下标  
	int next = 1;//下一个instance的index  
	int last = 0;//当前instance的index  
	int splitIndex = -1;//分裂点  
	double currentInfoGain;//当前信息增益  
	double defaultEnt;//分割之前的信息熵  
	double minSplit;  
	Instance instance;  
	int i;  
		
	//首先新建一个分布,数值型默认处理为2维分布,也就可以理解为小于某个值放到一个Bag里,其余的放到另外一个Bag里 
	m_distribution = new Distribution(2,trainInstances.numClasses());  
	Enumeration enu = trainInstances.enumerateInstances();  
	i = 0;  
	//注意instances传入的时候是排好序的,这个排序保证了missingValue放在最后面,所以读到了missingValue其之后肯定都是miss//ingValue,换言之,firstMiss在循环之后代表了最后一个有效的instance的下标。  
	while (enu.hasMoreElements()) { 
	<span style="white-space:pre">	</span>instance = (Instance) enu.nextElement(); 
		if (instance.isMissing(m_attIndex))
		<span style="white-space:pre">	</span>break; 
		m_distribution.add(1,instance);
		i++; 
	} 
	firstMiss = i;//循环结束后,m_distribution里放入了所有的有效instance,并全放入了bag1里。
	
<span style="white-space:pre">	</span>//minSplit是最后分类好每个Bag里最小的数据的量,也就是0.1*每个类的均值。  
	minSplit =  0.1*(m_distribution.total())/  
	<span style="white-space:pre">	</span>((double)trainInstances.numClasses());  
	if (Utils.smOrEq(minSplit,m_minNoObj))   
		minSplit = m_minNoObj;  
	else if (Utils.gr(minSplit,25))   
		minSplit = 25;  
		      
	//如果有效数据总量不到2*minSplit,换言之无论怎么分均不能保证2个bag里的数量大于minSplit,就直接返回。  
	if (Utils.sm((double)firstMiss,2*minSplit))  
		return;  
		      
	//defaultEnt代表旧的信息熵,也就是对该属性进行分类之前,Indexclass对应的信息熵。   
	defaultEnt = infoGainCrit.oldEnt(m_distribution);  
		
	while (next < firstMiss) {  
		if (trainInstances.instance(next-1).value(m_attIndex)+1e-5 <   
				trainInstances.instance(next).value(m_attIndex)) {   
		//Instances里的记录是升序排列的,加上这个条件默认把值相差很小的Instance就当做同一个instance处理了  
		    
		<span style="white-space:pre">	</span>//last代表当前,next代表下一个,默认next=1,last=0,所以shiftRange可以理解成把当前记录从bag1移动到bag0中  
			//注意一开始初始化时候所有的都是在bag1里面的。
			m_distribution.shiftRange(1,0,trainInstances,last,next);
				
			//如果两个bag都满足最小数据集的数量minSplit
			if (Utils.grOrEq(m_distribution.perBag(0),minSplit) && 
			Utils.grOrEq(m_distribution.perBag(1),minSplit)) { 
					
				//算一下信息增益
				currentInfoGain = infoGainCrit. splitCritValue(m_distribution,m_sumOfWeights,defaultEnt);
				if (Utils.gr(currentInfoGain,m_infoGain)) { 
					m_infoGain = currentInfoGain;//如果信息增益比当前最大的要大,则替换当前最大的值,并记录splitIndex  
					splitIndex = next-1;  
				}  
				m_index++;  
			}  
			last = next;  
		}  
		next++;  
	}  
	    
	if (m_index == 0)  
		return; //执行到这里说明没找到一个合适的分裂点,直接返回。  
		
	// 计算最佳信息增益  
	m_infoGain = m_infoGain-(Utils.log2(m_index)/m_sumOfWeights);  
	if (Utils.smOrEq(m_infoGain,0))  
		return; //如果信息增益是0也说明没找到合适的分裂点,直接返回。  
		     
	//剩下的就是根据分裂点进行属性的划分。  
	m_numSubsets = 2;  
	m_splitPoint =  (trainInstances.instance(splitIndex+1).value(m_attIndex)+  
			trainInstances.instance(splitIndex).value(m_attIndex))/2;  
		  
	// In case we have a numerical precision problem we need to choose the  
	// smaller value  
	if (m_splitPoint == trainInstances.instance(splitIndex + 1).value(m_attIndex)) {  
	<span style="white-space:pre">	</span>m_splitPoint = trainInstances.instance(splitIndex).value(m_attIndex);  
	}  
		  
	// Restore distributioN for best split.  
	m_distribution = new Distribution(2,trainInstances.numClasses());  
	m_distribution.addRange(0,trainInstances,0,splitIndex+1);  
	m_distribution.addRange(1,trainInstances,splitIndex+1,firstMiss);  
		  
	// Compute modified gain ratio for best split.  
	m_gainRatio = gainRatioCrit.  
	splitCritValue(m_distribution,m_sumOfWeights,  
	m_infoGain);  
}



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值