这是我数据挖掘课的作业,也就是实现一个朴素贝叶斯算法。所用的训练数据集为加州大学计算机系提供的breast-cancer.data和segment.data。我得出的朴素贝叶斯算法对于离散型属性的预测准确度为0.72,对于连续型属性的预测准确度为0.79。
代码如下:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package auxiliary;
import java.beans.FeatureDescriptor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
*
* @author daq
*/
class Store{//用于标识离散属性的P(Xi|Cj)的类
int attr;//哪个属性
double attrValue;//属性对应的值
double lable;//与之对应的标签的值
@Override
public int hashCode() {//重写的hashCode方法
final int prime = 31;
int result = 1;
result = prime * result + attr;
long temp;
temp = Double.doubleToLongBits(attrValue);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(lable);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {//重写的equals方法
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Store other = (Store) obj;
if (attr != other.attr)
return false;
if (Double.doubleToLongBits(attrValue) != Double
.doubleToLongBits(other.attrValue))
return false;
if (Double.doubleToLongBits(lable) != Double
.doubleToLongBits(other.lable))
return false;
return true;
}
}
class Store2{//用于标识连续属性的P(Xi|Cj)的类
int attr;//哪个属性
double label;//标签的值
@Override
public int hashCode() {//重写的hashCode方法
final int prime = 31;
int result = 1;
result = prime * result + attr;
long temp;
temp = Double.doubleToLongBits(label);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {//重写的equals方法
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Store2 other = (Store2) obj;
if (attr != other.attr)
return false;
if (Double.doubleToLongBits(label) != Double
.doubleToLongBits(other.label))
return false;
return true;
}
}
public class NaiveBayes extends Classifier {
boolean []myIsCategory;
double [][]myFeatures;
double []myLabels;
ArrayList<Double> labelKinds=new ArrayList<Double>();//label的数组的种类的数组
HashMap<Double,Double> labelKindsProp=new HashMap<Double,Double>();//每种label的概率
HashMap<Store,Double> attrLabelsProp=new HashMap<Store,Double>();
HashMap<Integer,ArrayList<Double>> valueKinds=new HashMap<Integer,ArrayList<Double>>();
HashMap<Store2,Double> averageAttrs=new HashMap<Store2,Double>();
HashMap<Store2,Double>standDev=new HashMap<Store2,Double>();//attr,labelKind
public NaiveBayes() {
}
public void setLabelKinds(double[] labels){//计算标签种类并存储各个不同标签值
for(int i=0;i<labels.length;i++){
boolean flag=true;
for(int j=0;j<labelKinds.size();j++){
if(labelKinds.get(j)==labels[i]){
flag=false;
break;
}
}
if(flag==true)
this.labelKinds.add(labels[i]);
}
}
public void setLabelKindsProp(double[] labels){//计算不同标签的值占全部标签的比例
int sum=labels.length;
for(int i=0;i<labelKinds.size();i++){
double label=labelKinds.get(i);
int num=0;
for(int j=0;j<labels.length;j++){
if(labels[j]==label)
num++;
}
labelKindsProp.put(label,num*1.0/sum);
}
}
public void setValueKinds(double[][] features){//对于离散的属性,存储其不同的值
int lineNums=features.length;
for(int i=0;i<features[0].length;i++){
if(myIsCategory[i]){
for(int j=0;j<lineNums;j++){
ArrayList<Double> values=valueKinds.get(i);
if(values==null)
values=new ArrayList<Double>();
if(!values.contains(features[j][i])){
values.add(features[j][i]);
valueKinds.put(i,values);
}
}
}
}
}
public void setAttrLabelsProp(boolean[] isCategory, double[][] features){//对于离散的属性,计算不同的值占全部元祖的比例
for(int i=0;i<labelKinds.size();i++){
double label=labelKinds.get(i);
for(int j=0;j<features[0].length;j++){
if(myIsCategory[j]){
ArrayList<Double> values=valueKinds.get(j);
int num[]=new int[values.size()];
for(int k=0;k<features.length;k++){
for(int l=0;l<values.size();l++){
double value=values.get(l);
if(features[k][j]==value&&myLabels[k]==label)
num[l]++;
}
}
double labelNum=labelKindsProp.get(label)*features.length;
for(int k=0;k<num.length;k++){
double valuetmp=values.get(k);
double prop=num[k]*1.0/labelNum;
Store store=new Store();
store.attr=j;
store.attrValue=valuetmp;
store.lable=label;
attrLabelsProp.put(store,prop);
}
}
}
}
}
public double getAverage(double [][]data,int attr,double lable){//得到连续属性对于特定标签值的平均数
int lineNums=data.length;
double sum=0;
int k=0;
for(int i=0;i<lineNums;i++){
if(myLabels[i]==lable){
sum+=data[i][attr];
k++;
}
}
return sum*1.0/k;
}
public void setAverage(){//存储得到的连续属性的值得平均数
for(int i=0;i<labelKinds.size();i++){
double label=labelKinds.get(i);
for(int j=0;j<myFeatures[0].length;j++){
double ave=getAverage(myFeatures,j, label);
Store2 store=new Store2();
store.attr=j;
store.label=label;
averageAttrs.put(store,ave);
}
}
}
public double getStanDev(double [][]data,int attr,double lable){//得到连续属性对于特定标签值的标准差
int lineNums=data.length;
double sum=0;
int k=0;
for(int i=0;i<lineNums;i++){
if(myLabels[i]==lable){
sum+=Math.pow(data[i][attr],2);
k++;
}
}
double temp=sum*1.0/k;
double res2=temp-Math.pow(getAverage(data,attr,lable),2);
return Math.sqrt(res2);
}
public void setStanDev(){
for(int i=0;i<labelKinds.size();i++){
double label=labelKinds.get(i);
for(int j=0;j<myFeatures[0].length;j++){
double sd=getStanDev(myFeatures,j, label);
Store2 store=new Store2();
store.attr=j;
store.label=label;
standDev.put(store,sd);
}
}
}
public double getG(double x,double u,double m){//计算P(X|C),也就是高斯分布g
double t=-1*Math.pow((x-u),2)*1.0/(2*Math.pow(m,2));
return Math.pow(Math.E,t)*1.0/(Math.sqrt(2.0*Math.PI)*m);
}
public double getOverallAve(int attr){//得到某一个属性的整体平均值用于预处理,替换所有的NaN型数据
double sum=0;
for(int i=0;i<myFeatures.length;i++){
sum+=myFeatures[i][attr];
}
return sum*1.0/myFeatures.length;
}
public void preHandle(){//对数据进行预处理,替换掉NaN型数据
int length=myFeatures.length;
for(int i=0;i<myFeatures.length;i++){
double line[]=myFeatures[i];
for(int j=0;j<line.length;j++){
if(line[j]!=line[j]){
myFeatures[i][j]=this.getOverallAve(j);
}
}
}
}
@Override
public void train(boolean[] isCategory, double[][] features, double[] labels) {
this.myIsCategory=isCategory;
this.myFeatures=features;
this.myLabels=labels;
this.preHandle();
this.setLabelKinds(labels);
this.setLabelKindsProp(labels);
this.setValueKinds(features);
this.setAttrLabelsProp(isCategory,features);
this.setAverage();
this.setStanDev();
}
@Override
public double predict(double[] features) {
double resMax=0,resMaxIndex=0;
for(int i=0;i<this.labelKinds.size();i++){
double res=1;
double label=this.labelKinds.get(i);
double labelProp=this.labelKindsProp.get(label);
for(int j=0;j<features.length;j++){
double feature=features[j];
if(myIsCategory[j]){
Store store=new Store();
store.attr=j;
store.attrValue=feature;
store.lable=label;
if(attrLabelsProp.get(store)!=null){
double prop=attrLabelsProp.get(store);
res*=prop;
}else
res=0;
}else{
Store2 s1=new Store2();
s1.attr=j;
s1.label=label;
double ave=this.averageAttrs.get(s1);
double stanDev=this.standDev.get(s1);
if(stanDev==0)
continue;
double g=getG(features[j],ave,stanDev);
res*=g;
}
}
res*=labelProp;
if(res>resMax){
resMax=res;
resMaxIndex=label;
}
}
return resMaxIndex;
}
}
这段代码中,train函数用来训练数据,predict函数预测数据。train的参数isCategory数组是存储各个属性是连续的还是离散的,连续的话,值为0,离散的话,值为1。features[][]数组存放训练数据,label数组用来存储各个元组的标签值。
分享到:
相关推荐
内容包括朴素贝叶斯算法python实现代码,实现对iris分类,包含iris的txt格式的数据集。
基于朴素贝叶斯算法的社交网络数据挖掘技术研究.pdf
分类算法-朴素贝叶斯算法C语言实现
给定一个表格,里面存放了若干用户的年龄、身份、性别、收入等信息,作为训练样本集,最后给予一个人的信息,决策这个用户会不会买这个商品
针对朴素贝叶斯分类算法中缺失数据填补问题,提出一种基于改进EM(Expectation Maximization)算法的朴素贝叶斯分类算法。该算法首先根据灰色相关度对缺失数据一个估计,估计值作为执行EM算法的初始值,迭代执行E步M...
用C实现的朴素贝叶斯的算法实现,对于数据挖掘的贝叶斯算法的理解有一定的帮助
基于贝叶斯算法的分类实现,java源代码。下载后即可导入测试。
数据挖掘上机作业 实现朴素贝叶斯简单分类
树型朴素贝叶斯算法java数据挖掘算法源码
将一些随机爬下来的帖子进行分类,利用了朴素贝叶斯算法
该实验的的数据源是Wine recognition data,这是对在意大利同一地区生产的三种不同品种的酒,做大量分析所得出的数据。这些数据包括了三种酒中13种不同成分的数量。13种成分分别为:Alcohol,Malic acid,Ash,...
本节主要介绍数据挖掘中常见的分类方法决策树和朴素贝叶斯算法。 决策树算法 决策树(Decision Tree,DT)分类法是一个简单且广泛使用的分类技术。 决策树是一个树状预测模型,它是由结点和有向边组成的层次结构。...
朴素贝叶斯算法java数据挖掘算法源码 数据挖掘算法是根据数据创建数据挖掘模型的一组试探法和计算。 为了创建模型,算法将首先分析您提供的数据,并查找特定类型的模式和趋势。概念描述算法使用此分析的结果来定义...
华中科技大学 数据挖掘与检索 贝叶斯朴素算法 SVM支持向量机算法 java实现
数据挖掘算法之深入朴素贝叶斯分类
training data自己找咯 目前只支持分两类 有问题站内我
数据挖掘8:朴素贝叶斯分类算法原理与实践.doc
本章介绍如何用强大却出奇简单的朴素贝叶斯算法消除社会媒体用语的歧义。朴素贝叶斯算法在计算用于分类的概率时,为简化计算,假定各特征之间是相互独立的,因此名字中含有朴素二字。它稍经扩展就能用于对其他类型...
数据挖掘:基于朴素贝叶斯定理的文本分类实践(Java)