博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ID3算法详解
阅读量:4658 次
发布时间:2019-06-09

本文共 7622 字,大约阅读时间需要 25 分钟。

这学期hadoop的作业是实现ID3算法,在网上找到了一篇非常好的资料,但是代码没有详细介绍。研究一番之后写出了自己ID3算法的普通实现和线程模拟分布式实现。

先附上原文地址:

博主写的非常好,基本上简单易懂的描述了ID3算法的原理。

问题

统计了14天的气象数据(指标包括outlook,temperature,humidity,windy),并已知这些天气是否打球(play)。如果给出新一天的气象指标数据:sunny,cool,high,TRUE,判断一下会不会去打球。

ID3原理

直接看博客链接,非常详细

代码实现

别忘了放入输入文件,按我的程序保存在指定位置,保存名为weather.arff

@relation weather.symbolic@attribute outlook {sunny, overcast, rainy}@attribute temperature {hot, mild, cool}@attribute humidity {high, normal}@attribute windy {
TRUE, FALSE}@attribute play {yes, no}@datasunny,hot,high,FALSE,nosunny,hot,high,TRUE,noovercast,hot,high,FALSE,yesrainy,mild,high,FALSE,yesrainy,cool,normal,FALSE,yesrainy,cool,normal,TRUE,noovercast,cool,normal,TRUE,yessunny,mild,high,FALSE,nosunny,cool,normal,FALSE,yesrainy,mild,normal,FALSE,yessunny,mild,normal,TRUE,yesovercast,mild,high,TRUE,yesovercast,hot,normal,FALSE,yesrainy,mild,high,TRUE,no
package com.coderfish.id3;import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.util.ArrayList;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;import org.dom4j.Document;import org.dom4j.DocumentHelper;import org.dom4j.Element;import org.dom4j.io.OutputFormat;import org.dom4j.io.XMLWriter;/** * date:2015年6月15日
* description: * 统计了14天的气象数据(outlook天气状况,temperature温度,humidity湿度,windy风力),并已知这些天气是否打球(play) * 如果给出新一天的气象指标数据:sunny,cool,high,TRUE,判断一下会不会去打球。
* * @author 周凌宇
* */public class ID3 {
/** * 存储属性的名称 */ private ArrayList
attribute = new ArrayList
(); /** * 存储每个属性的取值 */ private ArrayList
> attributeValue = new ArrayList
>(); /** * 原始数据 */ private ArrayList
data = new ArrayList
(); /** * 决策变量在属性集中的索引 */ int decisionIndex; /** * ARFF格式 */ public static final String patternString = "@attribute(.*)[{](.*?)[}]"; /** * XML文件对象 */ Document xmldoc; /** * 根节点 */ Element root; /** * 构造方法
* 新建xml
*
*
*
*
*/ public ID3() { xmldoc = DocumentHelper.createDocument(); root = xmldoc.addElement("root"); root.addElement("DecisionTree").addAttribute("value", "null"); } public static void main(String[] args) { ID3 inst = new ID3(); inst.readARFF(new File("f:\\id3temp\\weather.arff")); inst.setDec("play"); // conditionList存放条件个数 LinkedList
conditionNumList = new LinkedList
(); for (int i = 0; i < inst.attribute.size(); i++) { // 如果i!=决策变量索引(实际5) if (i != inst.decisionIndex) conditionNumList.add(i); } // dataList存放data的个数 ArrayList
dataNumList = new ArrayList
(); for (int i = 0; i < inst.data.size(); i++) { dataNumList.add(i); } inst.buildDT("DecisionTree", "null", dataNumList, conditionNumList); inst.writeXML("f:\\id3temp\\dt.xml"); return; } /** * 读取arff文件,给attribute、attributevalue、data赋值 * * @param file * 要读取的文件 */ public void readARFF(File file) { try { FileReader fr = new FileReader(file); BufferedReader br = new BufferedReader(fr); String line; // 设置arff模式 Pattern pattern = Pattern.compile(patternString); // 读取数据 while ((line = br.readLine()) != null) { // 判断合规 Matcher matcher = pattern.matcher(line); // 尝试查找与该模式匹配的输入序列的下一个子序列 if (matcher.find()) { // 返回匹配到的子字符串 attribute.add(matcher.group(1).trim()); String[] values = matcher.group(2).split(","); ArrayList
al = new ArrayList
(values.length); for (String value : values) { al.add(value.trim()); } // 存入attributevalue对象中 attributeValue.add(al); } // 判断开头 else if (line.startsWith("@data")) { while ((line = br.readLine()) != null) { if (line == "") continue; String[] row = line.split(","); data.add(row); } } else { continue; } } br.close(); } catch (IOException e1) { e1.printStackTrace(); } } /** * 设置决策变量索引 * * @param n */ public void setDec(int n) { if (n < 0 || n >= attribute.size()) { System.err.println("决策变量指定错误。"); System.exit(2); } decisionIndex = n; } /** * 设置决策变量 * * @param name */ public void setDec(String name) { // 获取下标 int n = attribute.indexOf(name); setDec(n); } /** * 计算熵 * * @param arr * yes or no个数 * @return 熵 */ public double getEntropy(int[] arr) { double entropy = 0.0; int sum = 0; for (int i = 0; i < arr.length; i++) { entropy -= arr[i] * Math.log(arr[i] + Double.MIN_VALUE) / Math.log(2); sum += arr[i]; } // log(N)/log(2) entropy += sum * Math.log(sum + Double.MIN_VALUE) / Math.log(2); entropy /= sum; return entropy; } /** * 判断节点值是否全部相同 * * @param subset * 给定子集 * @return 全部相同返回true,有不相同返回false */ public boolean infoPure(ArrayList
subset) { // yes or no String value = data.get(subset.get(0))[decisionIndex]; for (int i = 1; i < subset.size(); i++) { String next = data.get(subset.get(i))[decisionIndex]; // 如果该结点值和第一个节点值不同 if (!value.equals(next)) return false; } return true; } /** * 给定原始数据的子集(subset中存储行号),当以第index个属性为节点时计算它的信息熵 * * @param subset * 给定子集 * @param index * 属性下标 * @return */ public double calNodeEntropy(ArrayList
subset, int index) { int sum = subset.size(); double entropy = 0.0; // 长度为属性个数 存放每种可能的决策情况 int[][] info = new int[attributeValue.get(index).size()][]; for (int i = 0; i < info.length; i++) // 决策个数 info[i] = new int[attributeValue.get(decisionIndex).size()]; // 长度为属性个数 int[] count = new int[attributeValue.get(index).size()]; for (int i = 0; i < sum; i++) { // 子集遍历下标 int n = subset.get(i); String nodeValue = data.get(n)[index]; int nodeIndex = attributeValue.get(index).indexOf(nodeValue); count[nodeIndex]++; // 决策结果 String decValue = data.get(n)[decisionIndex]; int decIndex = attributeValue.get(decisionIndex).indexOf(decValue); info[nodeIndex][decIndex]++; } for (int i = 0; i < info.length; i++) { // 加权求值 entropy += getEntropy(info[i]) * count[i] / sum; } return entropy; } /** * 构建决策树 第一次给定值为"DecisionTree", "null", al, ll * * @param name * 节点名称 * @param value * 节点值 * @param subset * 子集 * @param conditionList */ public void buildDT(String name, String value, ArrayList
dataNumList, LinkedList
conditionNumList) { Element ele = null; // 从任意位置的节点上选择名称为 name 的节点。 List
list = root.selectNodes("//" + name); Iterator
iter = list.iterator(); while (iter.hasNext()) { ele = iter.next(); // 节点匹配value跳出循环 if (ele.attributeValue("value").equals(value)) break; } // 如果子决策全部相同 直接放入决策 跳出递归 if (infoPure(dataNumList)) { ele.setText(data.get(dataNumList.get(0))[decisionIndex]); return; } int minIndex = -1; double minEntropy = Double.MAX_VALUE; for (int i = 0; i < conditionNumList.size(); i++) { if (i == decisionIndex) continue; // 给定子集计算熵 double entropy = calNodeEntropy(dataNumList, conditionNumList.get(i)); if (entropy < minEntropy) { minIndex = conditionNumList.get(i); minEntropy = entropy; } } // 找出最小熵的节点属性名(作为要加入节点名) String nodeName = attribute.get(minIndex); conditionNumList.remove(new Integer(minIndex)); // 拿出对应属性的所有值 ArrayList
attvalues = attributeValue.get(minIndex); for (String val : attvalues) { ele.addElement(nodeName).addAttribute("value", val); ArrayList
al = new ArrayList
(); for (int i = 0; i < dataNumList.size(); i++) { // 找出开头为val的数据行 if (data.get(dataNumList.get(i))[minIndex].equals(val)) { al.add(dataNumList.get(i)); } } buildDT(nodeName, val, al, conditionNumList); } } /** * xml输出 * * @param filename */ public void writeXML(String filename) { try { File file = new File(filename); if (!file.exists()) file.createNewFile(); FileWriter fw = new FileWriter(file); OutputFormat format = OutputFormat.createPrettyPrint(); // 美化格式 XMLWriter output = new XMLWriter(fw, format); output.write(xmldoc); output.close(); } catch (IOException e) { System.out.println(e.getMessage()); } }}

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://www.cnblogs.com/coderfish/p/4875468.html

你可能感兴趣的文章
MySQL---正确使用索引、limit分页、执行计划、慢日志查询
查看>>
【转】互联网时代的社会语言学:基于SNS的文本数据挖掘
查看>>
SEO (Search Engine Optimization)优化以及品牌知名度提升方法
查看>>
.Net Core Web Api 上传女朋友的照片到微软云Azure Storage
查看>>
【hdu 2176】取(m堆)石子游戏
查看>>
【u114】旅行计划(12月你好)
查看>>
JavaFX:禁止TableView的列拖拽功能
查看>>
6、ns-3数据跟踪
查看>>
java_js_避免无意义的条件判断
查看>>
Java并发程序设计(一) 基础概念
查看>>
Linux命令date日期时间和Unix时间戳互转
查看>>
LightOJ - 1297 Largest Box LightOJ(一元三次方程求极大值)
查看>>
883H - Palindromic Cut(思维+STL)
查看>>
.NET FTP上传文件
查看>>
操作系统中的调度算法
查看>>
JVM方法调用栈
查看>>
目标跟踪之Lukas-Kanade光流法
查看>>
python基础(第二课)
查看>>
C语言预处理条件语句的 与或运算
查看>>
D1图论最短路专题
查看>>