数据挖掘贝叶斯(Bayes)算法java实现 带注释详解


注:本算法的实现仅仅适用于小规模数据集的实验与测试,不适合用于工程应用
<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>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值