【云计算】用Java实现的ID3算法
小标 2018-12-13 来源 : 阅读 939 评论 0

摘要:本文主要向大家介绍了【云计算】用Java实现的ID3算法,通过具体的内容向大家展现,希望对大家学习云计算有所帮助。

本文主要向大家介绍了【云计算】用Java实现的ID3算法,通过具体的内容向大家展现,希望对大家学习云计算有所帮助。


主要实现


import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class ID3 {
 public static GTree tree = new GTree<>();//一颗通用树
 public static String[] attribute;// 自变因素类别列表(outlook,temperature,humidity,windy)
 public String[] valuename;// 因变因素列表(play)
 public String[] value = new String[2];// 决策值(YES,NO)因变因素
 public static List data;// 数据
 public static List<set> clomnSetList;//自变因素
 
 //初始化数据

 {
  data = getData("src/com/wdx/test/test.txt");
  String[][] a = new String[data.size()][];
  int ii = 0;
  for (String[] s : data) {
   a[ii++] = s;
  }
  //初始化自变因素列表
  clomnSetList = getClomnValueSet(a);
 }

 // 获取数据
 /**
  * 获得数据
  * @param path 本地文件路径 (仅支持文本文件)
  * @return List
  */
 public List getData(String path) {
  List data = new ArrayList<>();
  File f = new File(path);
  FileReader fr;
  try {
   fr = new FileReader(f);
   BufferedReader bfr = new BufferedReader(fr);
   String[] firstLine = bfr.readLine().split(",");
   attribute = new String[firstLine.length - 1];
   valuename = new String[1];
   // 初始化自变因素列表
   for (int i = 0; i < firstLine.length - 1; i++) {
    attribute[i] = firstLine[i];
   }
   // 初始因变因素
   valuename[0] = firstLine[firstLine.length - 1];
   // 初始化数据
   String nextline;
   while ((nextline = bfr.readLine()) != null) {
    String[] d = nextline.split(",");
    if (value[0] != d[d.length - 1] && value[1] != d[d.length - 1]) {
     if (value[0] == null) {
      value[0] = d[d.length - 1];
     } else if (value[1] == null && (!d[d.length - 1].equals(value[0]))) {
      value[1] = d[d.length - 1];
     }
    }
    data.add(d);
   }
  } catch (Exception e) {
   
   e.printStackTrace();
  }

  return data;
 }

 // 获取自变因素一列数据项信息熵
 /**
  * 
  * @param data 数据源
  * @param cloumn 一列自变因素
  * @param index 列指针
  * @return 一类自变因素信息熵
  */
 public double getGainClomn(List data, Set cloumn, int index) {
  double result = 0;
  for (String s : cloumn) {
   double entropy = getGain(data, s, index);
   double probility = getpro(data, s, index);
   result = result + entropy * probility;
  }
  return result;
 }

 // 获取一列自变因素各因素熵值,并进行排序
 /**
  * 
  * @param data 数据源
  * @param cloumn 一列自变因素
  * @param index 列指针
  * @return key:value形式的二维矩阵
  */
 public String[][] getGainClomnEntropy(List data, Set cloumn, int index) {
  String[][] result = new String[cloumn.size()][2];
  int i = 0;
  for (String s : cloumn) {
   int j = 0;
   double value = getGain(data, s, index);
   result[i][j++] = s;
   result[i++][j] = "" + value;
  }

  // 排序

  return sort(result);
 }

 // key:value形式二维数组排序方法
 public String[][] sort(String[][] a) {
  Arrays.sort(a, new Comparator() {

   @Override
   public int compare(String[] o1, String[] o2) {
    
    return Double.compare(Double.parseDouble(o2[1]), Double.parseDouble(o1[1]));
   }
  });
  return a;

 }

 // 获取指定数据信息熵
 /**
  * 
  * @param data 数据源
  * @param one 要求取熵的一个自变因素
  * @param index 所在列指针
  * @return 熵
  */
 public double getGain(List data, String one, int index) {
  double count = 0;
  int count1 = 0;
  int count2 = 0;
  for (String[] d : data) {
   System.out.println(d[d.length - 1]);
   System.out.println(d[d.length - 1].equals(value[0]));
   // int
   if (d[index].trim().equals(one.trim())) {
    count++;
    if (d[d.length - 1].trim().equals(value[0].trim())) {
     count1++;
    }
    if (d[d.length - 1].trim().equals(value[1].trim())) {
     count2++;
    }
   }

  }
  double probability1 = Double.parseDouble("" + count1) / count;//决策1概率
  double probability2 = Double.parseDouble("" + count2) / count;//决策2概率
  if (probability1 == 0) {
   return 0;
  }
  if (probability1 == 1) {
   return 1;
  }
  double result = -probability1 * (Math.log(probability1) / Math.log(2))
    - probability2 * (Math.log(probability2) / Math.log(2));
  return result;
 }

 // 获取指定自变因素概率
 /**
  * 获取指定自变因素概率
  * @param data 数据源
  * @param one 自变因素
  * @param index 所在列指针
  * @return 概率
  */
 public double getpro(List data, String one, int index) {
  double count = data.size();
  int count1 = 0;
  for (String[] d : data) {
   System.out.println(d[d.length - 1]);
   System.out.println(d[d.length - 1].equals(value[0]));
   // int
   if (d[index].trim().equals(one.trim())) {
    count1++;

   }

  }
  return Double.parseDouble("" + count1) / count;

 }

 // 获取当前文件系统信息熵  
 /**
  * 获取当前文件系统信息熵  
  * @param data 数据源(原始数据)
  * @return 系统信息熵
  */
 public double getGain(List data) {
  double count = data.size();
  int count1 = 0;
  int count2 = 0;
  for (String[] d : data) {
   System.out.println(d[d.length - 1]);
   System.out.println(d[d.length - 1].equals(value[0]));
   if (d[d.length - 1].trim().equals(value[0].trim())) {
    count1++;
   }
   if (d[d.length - 1].trim().equals(value[1].trim())) {
    count2++;
   }
  }
  double probability1 = Double.parseDouble("" + count1) / count;
  double probability2 = Double.parseDouble("" + count2) / count;
  double result = -probability1 * (Math.log(probability1) / Math.log(2))
    - probability2 * (Math.log(probability2) / Math.log(2));
  return result;
 }

 // 获取信息增益
 /**
  * 
  * @param data 数据源
  * @param cloumn 一列自变因素
  * @param index 列指针
  * @return 信息增益
  */
 
 public Double getGainCreat(List data, Set cloumn, int index) {
  return getGain(data) - getGainClomn(data, cloumn, index);
 }

 // 获取当前列的数据有哪些
 /**
  * 初始化一列自变因素列表
  * @param a数据源
  * @return [{sunny, overcast, rainy},{.....},...]
  */
 public List<set> getClomnValueSet(String[][] a) {
  a = reverdraSort(a);
  print(a);
  List<set> list = new ArrayList<>();
  for (int i = 0; i < a.length - 1; i++) {
   Set set = new HashSet<>();
   for (int j = i; j < a[i].length; j++) {
    set.add(a[i][j]);
   }
   list.add(set);
  }
  return list;

 }
 // 二维数组列行倒置排序法

 public String[][] reverdraSort(String[][] a) {
  int l1 = a.length;
  int l2 = a[0].length;
  String[][] a1 = new String[l2][l1];
  for (int i = 0; i < l2; i++) {

   for (int j = 0; j < l1; j++) {

    a1[i][j] = a[j][i];
   }

  }
  return a1;
 }
 // 打印二维数组方法

 public static void print(String arr[][]) {

  for (int i = 0; i < arr.length; i++) {

   for (int j = 0; j < arr[i].length; j++) {

    System.out.print(arr[i][j] + "、");

   }

   System.out.println();

  }

  System.out.println();

 }

 // 构建树
 /**
  * 递归构建决策树
  * @param data1 数据源
  * @param root1 当前根节点
  * @param clomnSetList 自变因素矩阵
  * @param attribute 自变因素类别列表
  * @return
  */
 public TreeNode makeTree(List data1, TreeNode root1, List<set> clomnSetList,
   String[] attribute) {

  // 找信息熵最大的自变因素
  if (clomnSetList.size() > 1) {
   // System.out.println(root);
   Double max = 0D;
   int maxIndex = 0;// 信息熵最大因素下标
   for (int i = 0; i < clomnSetList.size(); i++) {
    double temp = getGainCreat(data1, clomnSetList.get(i), i);
    // if(temp==0) {
    // return;
    // }
    if (max < temp) {
     max = temp;
     maxIndex = i;
    }
   }

   if (root1 == null) {
    TreeNode n1 = new TreeNode<>(attribute[maxIndex], null);
    root1 = n1;
    tree.insert(null, root1);
    // 获取此自变因素的决策数组(熵数组)
    String[][] device = getGainClomnEntropy(data1, clomnSetList.get(maxIndex), maxIndex);
    for (int i = 0; i < device.length; i++) {
     TreeNode n = new TreeNode<>(device[i][0], null);
     tree.insert(root1, n);
     if (Double.parseDouble(device[i][1]) == 0) {
      TreeNode n2 = new TreeNode<>("YES", null);
      tree.insert(n, n2);
     } else if (Double.parseDouble(device[i][1]) == 1) {
      TreeNode n2 = new TreeNode<>("NO", null);
      tree.insert(n, n2);
     }

     else {
      // 重建数据
      String v = device[i][0];
      // List<set> clomnSetList1 = clomnSetList;
      // clomnSetList1.remove(clomnSetList.get(maxIndex));
      List ndata1 = new ArrayList<>();
      for (String[] s : data1) {
       if (s[maxIndex].trim().equals(v.trim())) {
        String[] nn = new String[s.length - 1];
        for (int j = 0; j < maxIndex; j++) {
         nn[j] = s[j];
        }
        for (int j = maxIndex; j < nn.length; j++) {
         nn[j] = s[j + 1];
        }
        ndata1.add(nn);
       }
      }

      String[] newa = new String[attribute.length - 1];
      for (int k = 0; k < maxIndex; k++) {
       newa[k] = attribute[k];
      }
      for (int k = maxIndex; k < newa.length; k++) {
       newa[k] = attribute[k + 1];
      }
      // attribute = newa;
      for (int m = 0; m < attribute.length; m++) {
       System.out.println(attribute[m]);
      }
      // 重构cloumnSetList
      List<set> clomnSetListnew = new ArrayList<>(clomnSetList);
      clomnSetListnew.remove(clomnSetListnew.get(maxIndex));
      System.out.println(clomnSetListnew);
      makeTree(ndata1, n, clomnSetListnew, newa);

     }
    }
   } else {
    TreeNode n1 = new TreeNode<>(attribute[maxIndex], null);
    tree.insert(root1, n1);

    // 获取此自变因素的决策数组
    String[][] device = getGainClomnEntropy(data1, clomnSetList.get(maxIndex), maxIndex);
    for (int i = 0; i < device.length; i++) {
     TreeNode n = new TreeNode<>(device[i][0], null);
     tree.insert(n1, n);
     if (Double.parseDouble(device[i][1]) == 0) {
      TreeNode n2 = new TreeNode<>("YES", null);
      tree.insert(n, n2);
     } else if (Double.parseDouble(device[i][1]) == 1) {
      TreeNode n2 = new TreeNode<>("NO", null);
      tree.insert(n, n2);
     }

     else {
      // 重建数据
      String v = device[i][0];
      TreeNode n2 = new TreeNode<>(v, null);
      tree.insert(root1, n2);
      List<set> clomnSetList1 = clomnSetList;
      clomnSetList1.remove(clomnSetList.get(maxIndex));
      List ndata1 = new ArrayList<>();
      for (String[] s : data1) {
       if (s[maxIndex].trim().equals(v.trim())) {
        String[] nn = new String[s.length - 1];
        for (int j = 0; j < maxIndex; j++) {
         nn[j] = s[j];
        }
        for (int j = maxIndex; j < nn.length; j++) {
         nn[j] = s[j + 1];
        }
        ndata1.add(nn);
       }
      }
     
      String[] newa = new String[attribute.length - 1];
      for (int k = 0; k < maxIndex; k++) {
       newa[k] = attribute[k];
      }
      for (int k = maxIndex; k < newa.length; k++) {
       newa[k] = attribute[k + 1];
      }
      List<set> clomnSetListnew = new ArrayList<>(clomnSetList);
      clomnSetListnew.remove(clomnSetList.get(maxIndex));

      makeTree(ndata1, n2, clomnSetListnew, newa);

     }
    }
   }
  }
  return root1;

 }
 

 public static void main(String[] args) {
  ID3 id3 = new ID3();
  TreeNode treenode = id3.makeTree(data, null, clomnSetList, attribute);

  tree.Travelsal(treenode, 1);
 }

}


数据结构支持




public class GTree {
 // 根节点
 public TreeNode root = null;

 // 插入
 public boolean insert(TreeNode parent, TreeNode node) {
  if (root == null) {
   root = node;
   return true;
  } else {
   if (findOne(root, parent)) {

    // 留待考虑
    // TODO 这里会不会直接修改节点的list,待考虑
    return parent.getChildlist().add(node);
   }
  }
  return false;
 }

 /**
  * 
  * @param tRoot要参照的根节点
  * @param one要查找的节点
  * @return 是否存在这个节点
  */
 public boolean findOne(TreeNode tRoot, TreeNode one) {
  boolean b = false;
  // 参照根结点为空,则该节点一定不存在
  if (tRoot == null) {
   return false;
  }
  //
  if (tRoot == one) {
   return true;
  }

  if (tRoot.getChildlist() != null) {
   int length = tRoot.getChildlist().size();
   for (int i = 0; i < length; i++) {
    TreeNode node = tRoot.getChildlist().get(i);
    if (node == one) {
     return true;
    } else {
     if (node.getChildlist().size() != 0) {
      b = b || findOne(node, one);
     }
    }
   }
  } else {
   return false;
  }

  return b;
 }

 // 遍历
 /**
  * 
  * @param root
  *            根节点
  * @param l
  *            层数
  */
 public void Travelsal(TreeNode root, int l) {
  int temp = l*10;

  if (root != null) {
   if (l == 1) {
    System.out.printf("|--%-10s--", root.getValue().toString());
   }

   if (root.getChildlist() != null && root.getChildlist().size() != 0) {
    l++;
    int length = root.getChildlist().size();
    for (int i = 0; i < length; i++) {
     TreeNode node = root.getChildlist().get(i);
     System.out.printf("|--%-10s--", node.getValue());
     if (node.getChildlist() != null && node.getChildlist().size() != 0) {
      Travelsal(node, l);

      System.out.println();
      int temp1 = temp;
      temp = temp + (temp / 10) * 5;
      System.out.printf("%-" + temp + "s", " ");
      temp = temp1;
     } else {
      System.out.println();

      System.out.printf("%" + (l-1)*15+ "s", "");
     }

    }
   }
  }
 }

}




import java.util.ArrayList;
import java.util.List;

//通用树的节点
public class TreeNode{
 private Object value;//数据区
 private List<treenode> childlist;//孩子节点指针集合
 public TreeNode(){ 
  value = null;
  childlist = new ArrayList<>();
 }
 
 public TreeNode(Object value,List<treenode> childList) {
  this.value = value;
  if(childList!=null) {
   this.childlist = childList;
  }else {
   this.childlist=new ArrayList<>();
  }
  
 }

 public Object getValue() {
  return value;
 }

 public void setValue(Object value) {
  this.value = value;
 }

 public List<treenode> getChildlist() {
  return childlist;
 }

 public void setChildlist(List<treenode> childlist) {
  this.childlist = childlist;
 }
 
 
}



本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标大数据云计算大数据安全频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved