数据挖掘贝叶斯(Bayes)算法java实现 带注释详解
2015-01-17 14:09
861 查看
注:本算法的实现仅仅适用于小规模数据集的实验与测试,不适合用于工程应用
<span style="font-family: Arial, Helvetica, sans-serif;"> 算法假定训练数据各属性列的值均是离散类型的。若是非离散类型的数据,需要首先进行数据的预处理,将非离散型的数据离散化。</span>
import java.util.HashMap; import java.util.Map; /** * 贝叶斯主体类 * @author Rowen * @qq 443773264 * @mail luowen3405@163.com * @blog blog.csdn.net/luowen3405 * @date 2011.03.15 */ public class Bayes { /** * 将原训练元组按类别划分 * @param datas 训练元组 * @return Map<类别,属于该类别的训练元组> */ Map<String, ArrayList<ArrayList<String>>> datasOfClass(ArrayList<ArrayList<String>> datas){ //用于存放某类别 与 该类别对应的训练数据 Map<String, ArrayList<ArrayList<String>>> map = new HashMap<String, ArrayList<ArrayList<String>>>(); for(int i = 0 ; i < datas.size() ; i++){ //用于表示第i条训练数据 ArrayList<String> trainData = datas.get(i); //类别 String type = null; //第i条数据的类别 type = datas.get(i).get(datas.get(i).size() - 1); //如果不是第一次遇到type类型 if(map.containsKey(type)){ //将整个第i条训练数据放入到type类型{Key}对应的{value}中 map.get(type).add(trainData); }else{//如果是第一次遇到type类型 ArrayList<ArrayList<String>> typeTrainDatas = new ArrayList<ArrayList<String>>(); //将第i条数据放入到type类型对应的训练集typeTrainDatas中 typeTrainDatas.add(trainData); //将 类型 与 相应训练集加入到map中 map.put(type,typeTrainDatas); } } return map; } /** * 在训练数据的基础上预测测试元组的类别 * @param datas 训练元组 * @param testT 测试元组 * @return 测试元组的类别 */ public String predictClass(ArrayList<ArrayList<String>> datas, ArrayList<String> testT) { //拿到分好类的训练集 Map<String, ArrayList<ArrayList<String>>> doc = this.datasOfClass(datas); //分类的种类集 Object[] classes = doc.keySet().toArray(); double maxP = 0.00; int maxPIndex = -1; //Vnb =arg max P( Vj ) Π i P ( ai | Vj ) Vj 代表第j种分类 for(int i = 0 ; i < doc.size() ; i ++ ){//doc.size() 表示类别数 //得到第i种分类 String type = classes[i].toString(); //求P( Vj ) //1、求训练集中分类type的条数d.size() ArrayList<ArrayList<String>> d = doc.get(type); //2、求训练数据的总条数 //datas.size(); //3、求出P( Vi ) //pOfC表示P( Vi ) : 种类为type的训练元组的组数/训练元组的组数 Vi表示第i种分类 double pOfC = DecimalCalculate.div(d.size(), datas.size(), 3); //一条测试数据 testT //Π i P ( aj | Vi ) = p(a0|vi)*p(a1|vi)*p(a2|vi)*...*p() for(int j = 0 ; j < testT.size() ; j++){ //pv是p(aj|vi) double pv = pOfV(d,testT.get(j),j); pOfC = DecimalCalculate.mul(pOfC, pv); } if(pOfC > maxP){ maxP = pOfC; maxPIndex = i; } } return classes[maxPIndex].toString(); } /** * 计算指定属性列上指定值出现的概率 * @param d 属于某一类的训练元组 * @param value 列值 * @param index 属性列索引 * @return 概率 */ private double pOfV(ArrayList<ArrayList<String>> d, String value, int index) { double p = 0.0; int count = 0; int total = d.size(); for(int i = 0 ; i < d.size(); i++){ if(d.get(i).get(index).equals(value)){ count++; } } p = DecimalCalculate.div(count, total, 3); return p; } }
</pre><pre name="code" class="java"> import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.StringTokenizer; /** * 贝叶斯算法测试类 * @author Rowen * @qq 443773264 * @mail luowen3405@163.com * @blog blog.csdn.net/luowen3405 * @data 2011.03.15 */ public class TestBayes { <span style="white-space:pre"> </span>/** <span style="white-space:pre"> </span> * 读取测试元组 <span style="white-space:pre"> </span> * @return 一条测试元组 <span style="white-space:pre"> </span> * @throws IOException <span style="white-space:pre"> </span> */ <span style="white-space:pre"> </span>public ArrayList<String> readTestData() throws IOException{ <span style="white-space:pre"> </span>ArrayList<String> candAttr = new ArrayList<String>(); <span style="white-space:pre"> </span>BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); <span style="white-space:pre"> </span>String str = ""; <span style="white-space:pre"> </span>while (!(str = reader.readLine()).equals("")) { <span style="white-space:pre"> </span>StringTokenizer tokenizer = new StringTokenizer(str); <span style="white-space:pre"> </span>while (tokenizer.hasMoreTokens()) { <span style="white-space:pre"> </span>candAttr.add(tokenizer.nextToken()); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return candAttr; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>/** <span style="white-space:pre"> </span> * 读取训练元组 <span style="white-space:pre"> </span> * @return 训练元组集合 <span style="white-space:pre"> </span> * @throws IOException <span style="white-space:pre"> </span> */ <span style="white-space:pre"> </span>public ArrayList<ArrayList<String>> readData() throws IOException { <span style="white-space:pre"> </span>ArrayList<ArrayList<String>> datas = new ArrayList<ArrayList<String>>(); <span style="white-space:pre"> </span>BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); <span style="white-space:pre"> </span>String str = ""; <span style="white-space:pre"> </span>while (!(str = reader.readLine()).equals("")) { <span style="white-space:pre"> </span>StringTokenizer tokenizer = new StringTokenizer(str); <span style="white-space:pre"> </span>ArrayList<String> s = new ArrayList<String>(); <span style="white-space:pre"> </span>while (tokenizer.hasMoreTokens()) { <span style="white-space:pre"> </span>s.add(tokenizer.nextToken()); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>datas.add(s); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return datas; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public static void main(String[] args) { <span style="white-space:pre"> </span>TestBayes tb = new TestBayes(); <span style="white-space:pre"> </span>ArrayList<ArrayList<String>> datas = null; <span style="white-space:pre"> </span>ArrayList<String> testT = null; <span style="white-space:pre"> </span>Bayes bayes = new Bayes(); <span style="white-space:pre"> </span>try { <span style="white-space:pre"> </span>System.out.println("请输入训练数据"); <span style="white-space:pre"> </span>datas = tb.readData(); <span style="white-space:pre"> </span>while (true) { <span style="white-space:pre"> </span>System.out.println("请输入测试元组"); <span style="white-space:pre"> </span>testT = tb.readTestData(); <span style="white-space:pre"> </span>String c = bayes.predictClass(datas, testT); <span style="white-space:pre"> </span>System.out.println("The class is: " + c); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} catch (IOException e) { <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} }
import java.math.BigDecimal; public class DecimalCalculate { private static final int DEF_DIV_SCALE = 10; //这个类不能实例化 private DecimalCalculate(){ } /** * 提供精确的加法运算。 * @param v1 被加数 * @param v2 加数 * @return 两个参数的和 */ public static double add(double v1,double v2){ BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); } /** * 提供精确的减法运算。 * @param v1 被减数 * @param v2 减数 * @return 两个参数的差 */ public static double sub(double v1,double v2){ BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.subtract(b2).doubleValue(); } /** * 提供精确的乘法运算。 * @param v1 被乘数 * @param v2 乘数 * @return 两个参数的积 */ public static double mul(double v1,double v2){ BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.multiply(b2).doubleValue(); } /** * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 * 小数点以后10位,以后的数字四舍五入。 * @param v1 被除数 * @param v2 除数 * @return 两个参数的商 */ public static double div(double v1,double v2){ return div(v1,v2,DEF_DIV_SCALE); } /** * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 * 小数点以后10位,以后的数字四舍五入。 * @param v1 被除数 * @param v2 除数 * @return 两个参数的商 */ public static double div(double v1,double v2,int scale){ if(scale<0){ throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } /** * 提供精确的小数位四舍五入处理。 * @param v 需要四舍五入的数字 * @param scale 小数点后保留几位 * @return 四舍五入后的结果 */ public static double round(double v,int scale){ if(scale<0){ throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b = new BigDecimal(Double.toString(v)); BigDecimal one = new BigDecimal("1"); return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } /** * 提供精确的类型转换(Float) * @param v 需要被转换的数字 * @return 返回转换结果 */ public static float convertsToFloat(double v){ BigDecimal b = new BigDecimal(v); return b.floatValue(); } /** * 提供精确的类型转换(Int)不进行四舍五入 * @param v 需要被转换的数字 * @return 返回转换结果 */ <span style="white-space:pre"> </span> /** * 精确对比两个数字 * @param v1 需要被对比的第一个数 * @param v2 需要被对比的第二个数 * @return 如果两个数一样则返回0,如果第一个数比第二个数大则返回1,反之返回-1 */ public static int compareTo(double v1,double v2){ BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); return b1.compareTo(b2); } }
</pre><pre name="code" class="java">训练数据:
youth high no fair no youth high no excellent no middle_aged high no fair yes senior medium no fair yes senior low yes fair yes senior low yes excellent no middle_aged low yes excellent yes youth medium no fair no youth low yes fair yes senior medium yes fair yes youth medium yes excellent yes middle_aged medium no excellent yes middle_aged high yes fair yes senior medium no excellent no
</pre><pre name="code" class="java">
对原训练数据进行测试,测试如果如下:
</pre><pre name="code" class="java">请输入测试元组 youth high no fair The class is: no 请输入测试元组 youth high no excellent The class is: no 请输入测试元组 middle_aged high no fair The class is: yes 请输入测试元组 senior medium no fair The class is: yes 请输入测试元组 senior low yes fair The class is: yes 请输入测试元组 senior low yes excellent The class is: yes 请输入测试元组 middle_aged low yes excellent The class is: yes 请输入测试元组 youth medium no fair The class is: no 请输入测试元组 youth low yes fair The class is: yes 请输入测试元组 senior medium yes fair The class is: yes 请输入测试元组 youth medium yes excellent The class is: yes 请输入测试元组 middle_aged medium no excellent The class is: yes 请输入测试元组 middle_aged high yes fair The class is: yes 请输入测试元组 senior medium no excellent The class is: no<span style="font-family:Arial, Helvetica, sans-serif;"><span style="white-space: normal;"> </span></span>
相关文章推荐
- 数据挖掘-基于贝叶斯算法及KNN算法的newsgroup18828文档分类器的JAVA实现(上)
- 数据挖掘-基于贝叶斯算法及KNN算法的newsgroup18828文本分类器的JAVA实现(上)
- 数据挖掘-基于贝叶斯算法及KNN算法的newsgroup18828文本分类器的JAVA实现(上)
- 数据挖掘-基于贝叶斯算法及KNN算法的newsgroup18828文本分类器的JAVA实现(下)
- 数据挖掘-基于贝叶斯算法及KNN算法的newsgroup18828文本分类器的JAVA实现(上)
- 数据挖掘-基于贝叶斯算法及KNN算法的newsgroup18828文本分类器的JAVA实现(上)
- 数据挖掘-基于贝叶斯算法及KNN算法的newsgroup18828文本分类器的JAVA实现(下)
- 数据挖掘-基于贝叶斯算法及KNN算法的newsgroup18828文档分类器的JAVA实现(下)
- 数据挖掘各种算法JAVA的实现方法
- 数据挖掘-基于Kmeans算法、MBSAS算法及DBSCAN算法的newsgroup18828文本聚类器的JAVA实现(下)
- 数据挖掘-基于Kmeans算法、MBSAS算法及DBSCAN算法的newsgroup18828文本聚类器的JAVA实现(上)
- 数据挖掘:K最近邻(KNN)算法的java实现
- 数据挖掘十大经典算法之Apriori算法以及Java实现
- Java数据结构与算法—及实现 线性表 顺序表、链表、栈、队列详解
- 数据挖掘之Apriori算法详解和Python实现代码分享
- 数据挖掘-基于Kmeans算法、MBSAS算法及DBSCAN算法的newsgroup18828文本聚类器的JAVA实现(上)
- 机器学习与数据挖掘-K最近邻(KNN)算法的实现(java和python版)
- 数据挖掘10大算法(6)-K最近邻(KNN)算法的实现(java和python版)
- 数据挖掘之Apriori算法详解和Python实现代码分享
- 数据挖掘(二)——Knn算法的java实现