您的位置:首页 > 编程语言 > Java开发

数据挖掘贝叶斯(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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐