/*先把标题给写了、这样就能经常提醒自己*/
题记:今天下午去上厕所的一会儿时间,就把第四章给扫完了,说是扫完了主要是因为没有深入去看,对于某些证明都直接跳过了,看了一下里面的例子,大概懂个意思就行了
1. 朴素贝叶斯法
设输入空间
为
维向量的集合,输出空间为类标记集合
,输入特征向量
,输出类标记为
,
是
和
的联合概率分布,数据集
由
独立同分布产生。
朴素贝叶斯法就是通过训练集来学习联合概率分布
.具体怎么学习呢? 主要就是从先验概率分布和条件概率分布入手,俩个概率相乘即可得联合概率。
为什么称之为朴素呢,主要是其将条件概率的估计简化了,对条件概率分布作了条件独立性假设,这也是朴素贝叶斯法的基石,具体的假设如下
此公式在假设条件之下可以等价于
现在, 对于给定的输入向量
,通过学习到的模型计算后验概率分布P(Y=Ck|X=x),后验分布中最大的类作为的输出结果,根据贝叶斯定理可知后验概率为
上面的公式可能有点歧义,分母的Ck应该写成Cj才对,因为P(X=x)=E P(Y=Cj)*P(X=x|Y=Cj)
而
对于所有
都是相同的,即此可以将输出结果简化为
至此大概讲解了朴素贝叶斯的基本方法步骤了,关于参数估计还有具体实例下次再写了。夏天真热啊!
2. 参数估计
2.1 极大似然估计
上一小节讲了对于给定的输入向量
,其输出结果可表示为
对此可应用极大似然估计法来估计相应的概率,如先验概率
的极大似然估计是
设第个
特征
可能取值的集合为
,条件概率
的极大似然估计是
公式看起来可能有点不实在,还是直接上例子来说明吧!
例子:试由下表的训练数据学习一个朴素贝叶斯分类器并确定
的类标记,表中
为特征,
为类标记。
据此可算出
是
后验分布中值
最大的,也就是最终的类标记为-1
2.2 贝叶斯 估计
极大似然估计的一个可能是会出现所要估计的概率值为 0的情况,这时会影响到后验概率的计算结果,解决这一问题的方法是采用贝叶斯估计,具体的只需要在极大似然估计的基础上加多一个参数即可。懒得继续写公式了,不想写了,刚刚码完代码!!
有兴趣的可以看一下具体的代码实现
package
org.juefan.bayes;
import
java.util.ArrayList;
import
java.util.HashMap;
import
java.util.Map;
import
org.juefan.basic.FileIO;
/**
* 这是一个简易的贝叶斯分类器
* 只适用于离散数据,连续型数据的暂时请先绕道了^.^
*
@author
JueFan
*/
public
class
NaiveBayes{
//
平滑指数, 默认为拉普拉斯平滑,极大似然估计则为0
private
static
double
Lambda = 1
;
//
存储先验概率数据
private
Map<Object, Double> PriorProbability =
new
HashMap<>
();
//
存储条件概率数据
private
Map<Object, ArrayList<Map<Object, Double>>> ConditionProbability =
new
HashMap<>
();
/**
* 计算类别的先验概率
*
@param
datas
*/
public
void
setPriorPro(ArrayList<Data>
datas){
int
counts =
datas.size();
for
(Data data: datas){
if
(PriorProbability.containsKey(data.y)){
PriorProbability.put(data.y, PriorProbability.get(data.y)
+ 1
);
}
else
{
PriorProbability.put(data.y, (
double
) 1
);
}
}
for
(Object o: PriorProbability.keySet())
PriorProbability.put(o, (PriorProbability.get(o)
+ Lambda)/(counts + Lambda *
PriorProbability.size()));
}
/**
* 计算条件概率
*
@param
datas
*/
public
void
setCondiPro(ArrayList<Data>
datas){
Map
<Object, ArrayList<Data>> tmMap =
new
HashMap<>
();
//
按类别先将数据分类存放
for
(Data data: datas){
if
(tmMap.containsKey(data.y)){
tmMap.get(data.y).add(data);
}
else
{
ArrayList
<Data> tmDatas =
new
ArrayList<>
();
tmDatas.add(data);
tmMap.put(data.y, tmDatas);
}
}
//
条件概率主体
for
(Object o: tmMap.keySet()){
ArrayList
<Map<Object, Double>> tmCon =
new
ArrayList<>
();
int
LabelCount =
tmMap.get(o).size();
//
计算每个特征的相对频数
for
(Data data: tmMap.get(o)){
for
(
int
i = 0; i < data.x.size(); i++
){
if
(tmCon.size() < i + 1
){
Map
<Object, Double> tmMap2 =
new
HashMap<>
();
tmMap2.put(data.x.get(i), (
double
) 1
);
tmCon.add(tmMap2);
}
else
{
if
(tmCon.get(i).containsKey(data.x.get(i))){
tmCon.get(i).put(data.x.get(i), tmCon.get(i).get(data.x.get(i))
+ 1
);
}
else
{
tmCon.get(i).put(data.x.get(i), (
double
) 1
);
}
}
}
}
//
计算条件概率
for
(
int
i = 0; i < tmCon.size(); i++
){
for
(Object o1: tmCon.get(i).keySet()){
tmCon.get(i).put(o1, (tmCon.get(i).get(o1)
+ Lambda)/(LabelCount + Lambda *
tmCon.get(i).size()));
}
}
ConditionProbability.put(o, tmCon);
}
}
/**
* 判断实例的类别
*
@param
data
*
@return
判断结果
*/
public
Object getLabel(Data data){
Object label
=
new
Object();
double
pro =
0D;
for
(Object o: PriorProbability.keySet()){
double
tmPro = 1
;
tmPro
*=
PriorProbability.get(o);
for
(
int
i = 0; i < data.x.size(); i++
){
tmPro
*=
ConditionProbability.get(o).get(i).get(data.x.get(i));
}
if
(tmPro >
pro){
pro
=
tmPro;
label
=
o;
}
System.out.println(o.toString()
+ " :的后验概率为: " +
tmPro);
}
return
label;
}
public
static
void
main(String[] args) {
ArrayList
<Data> datas =
new
ArrayList<>
();
FileIO fileIO
=
new
FileIO();
fileIO.setFileName(
".//file//bayes.txt"
);
fileIO.FileRead();
for
(String data: fileIO.fileList){
datas.add(
new
Data(data));
}
NaiveBayes bayes
=
new
NaiveBayes();
bayes.setPriorPro(datas);
bayes.setCondiPro(datas);
Data data
=
new
Data("1\t2\tS"
);
System.out.println(data.toString()
+ "\t的判断类别为: " +
bayes.getLabel(data));
}
}
对代码有兴趣的可以上本人的GitHub查看: https://github.com/JueFan/StatisticsLearningMethod/

