Weka中贝叶斯网络学习情况小结.docx

上传人:b****9 文档编号:26282736 上传时间:2023-06-17 格式:DOCX 页数:33 大小:29.67KB
下载 相关 举报
Weka中贝叶斯网络学习情况小结.docx_第1页
第1页 / 共33页
Weka中贝叶斯网络学习情况小结.docx_第2页
第2页 / 共33页
Weka中贝叶斯网络学习情况小结.docx_第3页
第3页 / 共33页
Weka中贝叶斯网络学习情况小结.docx_第4页
第4页 / 共33页
Weka中贝叶斯网络学习情况小结.docx_第5页
第5页 / 共33页
点击查看更多>>
下载资源
资源描述

Weka中贝叶斯网络学习情况小结.docx

《Weka中贝叶斯网络学习情况小结.docx》由会员分享,可在线阅读,更多相关《Weka中贝叶斯网络学习情况小结.docx(33页珍藏版)》请在冰豆网上搜索。

Weka中贝叶斯网络学习情况小结.docx

Weka中贝叶斯网络学习情况小结

Weka中贝叶斯网络学习情况小结

Weka中对于贝叶斯网络的学习,仅仅看相关的几个包几乎是不可能的,结果还是一叶障目不见泰山。

后来发现就那些代码死磕根本不行,还得采取灵活的方式方法。

一方面采用学习人家博客的总结,逐步梳理weka中那些类的组织和功能函数的情况。

一方面下载了一个weka源代码分析的中文翻译包,能够从更加宽的领域理解BN的相关重要函数以及操作。

随便找个类,比如instance和instances,比如evaluation,都是几百行,或者千余行,通读一遍都很费力,而且许多类有继承,许多地方用的是接口,很少有地方用抽象类。

各个类之间的关联较多,随便引用一下,在某个函数中出现一下,都是关系,本来以为UML图能够方便的解决问题,但是拖动以后发现,事情越高越多,线条也越来越多,实际上展示效力快速下降,到最后还是不能够说明问题。

刚开始研究原理,其实朴素贝叶斯和贝叶斯网络的基本原理并不复杂,小型网络手算是可以的,有点像矩阵,小矩阵加减乘除都没问题,但是大型矩阵就得想方设法用计算机、写代码来实现了。

数学上涉及的东西,写道计算机上就需要一些辅助的东西了。

特别是程序实现上。

事实上,学习概论的东西本身也要小心,一不留神还是会犯下各种错误。

在软件实现上,读入arff数据,构建ADTree,然后训练分类器,最后进行测试。

Analternatingdecisiontree(ADTree)isamachinelearningmethodforclassification.Itgeneralizesdecisiontreesandhasconnectionstoboosting.

Analternatingdecisiontreeconsistsofdecisionnodesandpredictionnodes.Decisionnodesspecifyapredicatecondition.Predictionnodescontainasinglenumber.ADTreesalwayshavepredictionnodesasbothrootandleaves.AninstanceisclassifiedbyanADTreebyfollowingallpathsforwhichalldecisionnodesaretrueandsumminganypredictionnodesthataretraversed.ThisisdifferentfrombinaryclassificationtreessuchasCART(Classificationandregressiontree)orC4.5inwhichaninstancefollowsonlyonepaththroughthetree.

http:

//en.wikipedia.org/wiki/ADTree这个网站给的例子可以好好理解一下、

weka在进行实例测试的时候也有许多术语和内容需要继续认识,比如recall,precision,confusionmatrix,以及其他指标。

评分函数(score),在软件中归在evaluation中。

CPT,也就是conditionalprobabilitytable也是建立网络的关键。

有一个说法:

Bays=Bs(DAG)+Bp(CPT)weka中的Beiyes有两个要求,一个是离散化的数据,另一个是数据的值不能是null整个学习的过程是先构建DAG在学习出CPT。

记录一点代码分析:

在buildClassifier函数中,重要的几行是:

//buildthenetworkstructure

initStructure();

 

//buildthenetworkstructure

buildStructure();

 

//buildthesetofCPTs

estimateCPTs();

       函数initStructure为初始化网络结构,buildStructure为构造网络结构,estimateCPTs为计算条件概率表(conditionalprobabilitytable)。

/**

 * Init structure initializes the structure to an empty graph

 * or a Naive Bayes graph (depending on the -N flag).

*/

public void initStructure() throws Exception{

    //reservememory

    m_ParentSets = new ParentSet[m_Instances.numAttributes()];

 

    for (int iAttribute=0;iAttribute m_Instances.numAttributes();

iAttribute++){

       m_ParentSets[iAttribute]= new ParentSet(m_Instances

              .numAttributes());

    }

} //initStructure

       m_ParentSets是记录下第i个属性(iAttribute)的父结点,ParentSet初始函数为:

public ParentSet(int nMaxNrOfParents){

    m_nParents = new int[nMaxNrOfParents];

    m_nNrOfParents =0;

    m_nCardinalityOfParents =1;

} //ParentSet

       不做什么,也就是一个空图。

接下来看buildStructure,它会调用SearchAlgorithm中的buildStructure:

/**

 * buildStructure determines the network structure/graph of the network.

 * The default behavior is creating a network where all nodes have

 * the first node as its parent (i.e., a BayesNet that behaves like

 * a naive Bayes classifier). This method can be overridden by derived

 * classes to restrict the class of network structures that are acceptable.

*/

public void buildStructure(BayesNetbayesNet,Instancesinstances) throws Exception{

    if (m_bInitAsNaiveBayes){

        int iClass=instances.classIndex();

        //initializeparentsetstohavearrowfromclassifiernodeto

        //eachoftheothernodes

        for (int iAttribute=0;iAttribute

iAttribute++){

            if (iAttribute!

=iClass){

                bayesNet.getParentSet(iAttribute).addParent(iClass,

instances);

            }

        }

    }

    search(bayesNet,instances);

    if (m_bMarkovBlanketClassifier){

        doMarkovBlanketCorrection(bayesNet,instances);

    }

} //buildStructure

       这里会判断是不是初始化成朴素贝叶斯,如果不初始化为朴素贝叶斯,那么就还是空图,如果初始为朴素贝叶斯,则对于每个属性将类别属性加为父结点。

addParent的代码如下:

public void addParent(int nParent,Instances_Instances){

    if (m_nNrOfParents ==10){

       //reservemorememory

       int[]nParents= new int[50];

       for (int i=0;i< m_nNrOfParents;i++){

           nParents[i]= m_nParents[i];

       }

       m_nParents =nParents;

    }

    m_nParents[m_nNrOfParents]=nParent;

    m_nNrOfParents++;

    m_nCardinalityOfParents *=_Instances.attribute(nParent)

                                       .numValues();

} //AddParent

       前面的if是预保留内存的代码,后面的是保存哪个属性是它的父结点,m_NrOfParent是父结点数,CardinalityOfParents是父结点所能取的所有属性值之和。

       search函数的实现有很多,这里看K2的代码实现:

int nOrder[]= new int[instances.numAttributes()];

nOrder[0]=instances.classIndex();

 

int nAttribute=0;

 

for (int iOrder=1;iOrder

    if (nAttribute==instances.classIndex()){

       nAttribute++;

    }

    nOrder[iOrder]=nAttribute++;

}

       nOrder中类别属性下标为0,其实它属性顺序还是一样的。

//determinebasescores

double[]fBaseScores= new double[instances.numAttributes()];

for (int iOrder=0;iOrder

    int iAttribute=nOrder[iOrder];

    fBaseScores[iAttribute]=calcNodeScore(iAttribute);

}

       计算basescores,调用calcNodeScore函数:

public double calcNodeScore(int nNode){

    if (m_BayesNet.getUseADTree()&& m_BayesNet.getADTree()!

= null){

       return calcNodeScoreADTree(nNode);

    } else {

       return calcNodeScorePlain(nNode);

    }

}

       ADTree就暂时不去理会了,看calcNodeScorePlain函数:

//estimatedistributions

EnumerationenumInsts=instances.enumerateInstances();

 

while (enumInsts.hasMoreElements()){

    Instanceinstance=(Instance)enumInsts.nextElement();

 

    //updateClassifier;

    double iCPT=0;

 

    for (int iParent=0;iParent

            iParent++){

       int nParent=oParentSet.getParent(iParent);

 

       iCPT=iCPT*instances.attribute(nParent).numValues()

                  +instance.value(nParent);

    }

 

    nCounts[numValues*((int)iCPT)+(int)instance.value(nNode)]++;

}

       这里的nCounts是文章BayesianNetworkClassifiersinWeka中第4页所提到的Nijk,这里是将i,j,k三维放到了一些,类别值是最后的instance.value(nNode)。

       在calcNodeScorePlain函数中最后调用了calcScoreOfCount函数:

for (int iParent=0;iParent

    switch (m_nScoreType){

 

    case (Scoreable.BAYES):

{

       double nSumOfCounts=0;

 

       for (int iSymbol=0;iSymbol

          if (m_fAlpha +nCounts[iParent*numValues+iSymbol]!

=0){

              fLogScore+=Statistics.lnGamma(m_fAlpha

                     +nCounts[iParent*numValues+iSymbol]);

              nSumOfCounts+= m_fAlpha

                     +nCounts[iParent*numValues+iSymbol];

           }

       }

 

       if (nSumOfCounts!

=0){

           fLogScore-=Statistics.lnGamma(nSumOfCounts);

       }

 

       if (m_fAlpha !

=0){

           fLogScore-=numValues*Statistics.lnGamma(m_fAlpha);

           fLogScore+=Statistics.lnGamma(numValues* m_fAlpha);

       }

    }

       可以看BayesianNetworkClassifiersinWeka第6页中的Bayesianmetric中的公式,第一个for是计算Gamma(Nijk prime+Nijk)。

接下来是计算Gamma(Nijk prime+Nij),再将下来是计算Gamma(Nij prime)/Gamma(Nij prime+Nij)。

case (Scoreable.MDL):

case (Scoreable.AIC):

case (Scoreable.ENTROPY):

{

    double nSumOfCounts=0;

 

    for (int iSymbol=0;iSymbol

       nSumOfCounts+=nCounts[iParent*numValues+iSymbol];

    }

 

    for (int iSymbol=0;iSymbol

       if (nCounts[iParent*numValues+iSymbol]>0){

           fLogScore+=nCounts[iParent*numValues+iSymbol]

                  *Math.log(nCounts[iParent*numValues

                         +iSymbol] /nSumOfCounts);

       }

    }

}

       这里相应于BayesianNetworkClassifiersinWeka第5页的公式

(2)不同之处是没有N,因为它可以消掉。

switch (m_nScoreType){

case (Scoreable.MDL):

{

    fLogScore-=0.5*nCardinality*(numValues-1)

           *Math.log(instances.numInstances());

}

    break;

 

case (Scoreable.AIC):

{

    fLogScore-=nCardinality*(numValues-1);

}

    break;

}

       公式中的K=nCardinality*(numValues-1),N=instances.numInstances()。

见公式(3),MDL和AIC的计算见公式(5)。

// K2algorithm:

greedysearchrestrictedbyordering

for (int iOrder=1;iOrder

    int iAttribute=nOrder[iOrder];

    double fBestScore=fBaseScores[iAttribute];

 

    boolean bProgress=(bayesNet.getParentSet(iAttribute)

           .getNrOfParents()

    while (bProgress){

       int nBestAttribute=-1;

       for (int iOrder2=0;iOrder2

           int iAttribute2=nOrder[iOrder2];

           double fScore=calcScoreWithExtraParent(iAttribute,

                  iAttribute2);

           if (fScore>fBestScore){

              fBestScore=fScore;

              nBestAttribute=iAttribute2;

           }

       }

       if (nBestAttribute!

=-1){

           bayesNet.getParentSet(iAttribute).addParent(

nBestAttribute, instances);

           fBaseScores[iAttribute]=fBestScore;

           bProgress=(bayesNet.getParentSet(iAttribute)

                  .getNrOfParents()

       } else {

           bProgress= false;

       }

    }

}

       bProgress是判断iAttribute结点的父结点是否超过最大父结点数,代码逻辑大致是:

对每个属性(iOrder)得到它的父结点,找它的父结点是在[0-iOrder]中找,不然就循环了。

对于每个属性调用calcScoreWithExtraParent函数计算得到,如果它比以前的结分高,那它成为最好的属性,调用addParent加入。

public double calcScoreWithExtraParent(int nNode, int nCandidateParent){

    ParentSetoParentSet= m_BayesNet.getParentSet(nNode);

 

    //sanitycheck:

nCandidateParentshouldnotbeinparentsetalready

    if (oParentSet.contains(nCandidateParent)){

       return -1e100;

    }

 

    //setupcandidateparent

    oParentSet.addParent(nCandidateParent, m_BayesNet.m_Instances);

 

    //calculatethescore

    double logScore=calcNodeScore(nNode);

 

    //deletetemporarilyaddedparent

    oParentSet.deleteLastParent(m_BayesNet.m_Instances);

 

    return logScore;

} //Ca

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 经管营销 > 人力资源管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1