【JAVA实现】基于决策树的ID3算法

       在http://blog.csdn.net/c_son/article/details/43956585 这篇文章中,介绍了KNN算法,同时也指出它无法给出任何数据的基础数据结构信息,以及它不能保存训练结果,每次分类必须重写计算一遍,这样带来的一个问题是如果数据量非常的庞大,这会大大降低该算法的执行效率。而这次的ID3算法正好可以解决此问题。

       首先是数据集,这里和网上大多数例子一样,用了weka的weather数据集,如下:

@attribute outlook {sunny, overcast, rainy}
@attribute temperature {hot, mild, cool}
@attribute humidity {high, normal}
@attribute windy {TRUE, FALSE}
@attribute play {yes, no}

@data
sunny,hot,high,FALSE,no
sunny,hot,high,TRUE,no
overcast,hot,high,FALSE,yes
rainy,mild,high,FALSE,yes
rainy,cool,normal,FALSE,yes
rainy,cool,normal,TRUE,no
overcast,cool,normal,TRUE,yes
sunny,mild,high,FALSE,no
sunny,cool,normal,FALSE,yes
rainy,mild,normal,FALSE,yes
sunny,mild,normal,TRUE,yes
overcast,mild,high,TRUE,yes
overcast,hot,normal,FALSE,yes
rainy,mild,high,TRUE,no

       考虑到以后使用其他格式的数据集文件,我在这里使用了一个接口,便于以后的扩展。

public interface InitDataSetDao {
	
	/**
	 * @return 返回样本数据集中的每一条数据
	 */
	public List<String[]> getMeteDataSet();
	
	/**
	 * @return 返回数据集中属性的名字
	 */
	public List<String> getAttrbuteNames();
	
	/**
	 * @return map集合的键为每一个属性名称,值为属性值的集合
	 */
	public Map<String,List<String>> getAttrbuteOptions();
	
	/**
	 * @return 得到目标属性的名称与值,第一项为属性名称其余为值
	 */
	public List<String> getDestinaltion();

}
       建立好数据集之后,就是核心的创建决策树了。看到网上很多代码的例子都是针对上面的数据集进行硬编码式编程,为了以后代码的移植,我在这里花了些时间重构了下
private void buildDT(Element element, List<String[]> dataSet) {
		// 要创建的节点的名字
		String elementName = "";
		double min = Double.MAX_VALUE;

		// 计算每个属性熵值,选出最小值
		for (int i = 0; i < initDataSet.getAttrbuteNames().size() - 1; i++) {
			
			if (!skipAttrbuteList.contains(initDataSet.getAttrbuteNames().get(i))) {
				String attrbuteName = initDataSet.getAttrbuteNames().get(i);
				double sum = 0.0;
				// 计算每个属性的熵
				sum = calOptionEntropy(attrbuteName,dataSet);

				// 找最小值,确定节点
				if (sum < min) {
					min = sum;
					elementName = attrbuteName;
				}
			}
			
		}
		
		for (String attrbuteOption : initDataSet.getAttrbuteOptions().get(
				elementName)) {
			List<String[]> subDataSet = new ArrayList<String[]>();
			
			//使用set集合的无重复的特性来判断是否是叶节点,如果是叶节点,则set集合长度为一
			Set<String> set = new HashSet<String>();
			
			// 目标属性在数据集中的位置
			int decAttrbuteIndex = getValueIndex(initDataSet.getDestinaltion().get(
					0));
			
			for (String[] data : dataSet) {
				if (data[getValueIndex(elementName)].equals(attrbuteOption)) {
					subDataSet.add(data);
					set.add(data[decAttrbuteIndex]);
				}
			}
			
			// 创建节点
			Element subElement = element.addElement(elementName).addAttribute(	
					"value", attrbuteOption);
			
			//长度大于一则进行递归,否则输出
			if (set.size() > 1) {
				//将刚才生成的节点加入到已访问属性集合中
				skipAttrbuteList.add(elementName);
				//递归调用
				buildDT(subElement,subDataSet);
			} else {
				for (String string : set) {	
					subElement.setText(string);
				}
			}
			
		}
	}

       这里用到了信息熵的概念,来决定选取哪个特征作为分类基准,对于此算法这里不在深入。

       为了直观看到生成后决策树的形式,我这里将其输出到xml文件中,输出结果如下

<?xml version="1.0" encoding="UTF-8"?>

<root>
  <outlook value="sunny">
    <humidity value="high">no</humidity>
    <humidity value="normal">yes</humidity>
  </outlook>
  <outlook value="overcast">yes</outlook>
  <outlook value="rainy">
    <windy value="TRUE">no</windy>
    <windy value="FALSE">yes</windy>
  </outlook>
</root>
        细心的读者可能发现,怎么少了温度这一项,仔细想想就会发现因为在建立决策树考虑温度之前,整个决策树已经完成,可以进行决策。这也可以说是最好的情况,因为可能遇到当所有决策变量都使用上后,任然无法做出唯一决策(可能有点晕,请读者细想一下这种情形),这时就需要依照概率去做出决策。对于这一点,我在程序里没有体现,只考虑了最好情况。

       最后就是预测了,给定一种情形进行决策

public String pridictResult(Map<String, String> data) {
		
		Element element = document.getRootElement();
		List<Element> list = element.elements();
		
		while(true) {
			for (Element e : list) {
				if (data.get(e.getName()).equals(e.attributeValue("value"))) {
					list = e.elements();
					if (list.size() == 0) {
						return e.getText();
					}else {
						break;
					}
				}
			}
		}
	}
       整个程序的大致轮廓就是这样,如需详细代码请到如下下载地址进行下载。最后希望这篇文章可以给你带来帮助 微笑

点击打开链接

       算法不足:虽然决策树非常好地匹配了实验数据,然后这些匹配选项可能太多,我们将这种问题称之为过度匹配。为了减少过度匹配,我们可以裁剪决策树,去掉一些不必要的叶子节点。如果叶子节点只能增加少许信息,则我们可以删除该节点,将它并入到其他叶子节点中去。还有一个问题是ID3算法无法直接处理数值型数据,尽管我们可以通过量化的方法将数值型数据转化为标称性数据,但是如果存在过多的特征划分,ID3仍会面临其他问题。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值