首页 > 代码库 > Weka算法Classifier-meta-AdaBoostM1源码分析(二)
Weka算法Classifier-meta-AdaBoostM1源码分析(二)
三、基分类器
AdaBoostM1使用的默认基分类器是weka.classifiers.trees.DecisionStump,名字直译过来就是决策桩(这什么名字?!),其分类方法类似于ID3算法的节点分裂算法,如果是枚举型的,遍历所有属性,选出其中一个属性,使使用该属性进行分类后的熵增益最大,如果是数值型的,选择一个节点做二分,使分类后方差最小。
但和决策树不同的是,并不做递归的树生长,只做一次节点选择并分裂(所以叫桩而不是树)。
这个基分类器大体思路就是这样,代码较简单并且没有什么巧妙的算法思想,故不做具体分析。
四、buildClassifierWithWeight
上篇文章分析主流程的时候,可以看到最后主流程最后把训练过程委派给了buildClassifierWithWeight和buildClassifierUsingResampling,先来分析一下buildClassifierWithWeight
protected void buildClassifierWithWeights(Instances data) throws Exception { Instances trainData, training; double epsilon, reweight; Evaluation evaluation; int numInstances = data.numInstances(); Random randomInstance = new Random(m_Seed); // //初始化 m_Betas = new double [m_Classifiers.length]; m_NumIterationsPerformed = 0; // 从直观认识上讲,算法训练模型的时候,不应该改变训练数据或者把训练集弄脏,因此需要做一个Instances的深度拷贝。 training = new Instances(data, 0, numInstances); // 主循环,boosting使用的基分类器数量就是m_Classifiers数组长度。 for (m_NumIterationsPerformed = 0; m_NumIterationsPerformed < m_Classifiers.length; m_NumIterationsPerformed++) { if (m_Debug) { System.err.println("Training classifier " + (m_NumIterationsPerformed + 1)); } // 这里可以设置一个百分数,代表权重分位数,低于该分位数的实例会被过滤掉,这里是体现了boosting的“每次迭代着重考虑之前分错的实例”这种思想。 if (m_WeightThreshold < 100) { trainData = http://www.mamicode.com/selectWeightQuantile(training, >可以看到,此函数并没有对训练集根据权重进行重抽样,因为基分类器自身就是权重敏感的分类器。但是从设计的角度来吐个槽的话,个人认为这并不是一个非常好的设计,AdaBoostM1类作为一个基分类器的wrapper,必须对整个训练及分类结果负责,并不能因为基分类器“仅仅实现了权重敏感接口”就完全信任其权重敏感的操作,再从算法本身的角度来讲,实现“权重敏感”的逻辑本身就是AdaBoostM1算法的一部分,不应委派给基分类器去做。
五、buildClassifierUsingResampling
protected void buildClassifierUsingResampling(Instances data) throws Exception { Instances trainData, sample, training; double epsilon, reweight, sumProbs; Evaluation evaluation; int numInstances = data.numInstances(); Random randomInstance = new Random(m_Seed); int resamplingIterations = 0; // 初始化所有基分类器的权重数组,迭代次数等。 m_Betas = new double [m_Classifiers.length]; m_NumIterationsPerformed = 0; // 深度拷贝训练集 training = new Instances(data, 0, numInstances); sumProbs = training.sumOfWeights(); for (int i = 0; i < training.numInstances(); i++) { training.instance(i).setWeight(training.instance(i). weight() / sumProbs);//初始化权重为均值。 } // 主循环 for (m_NumIterationsPerformed = 0; m_NumIterationsPerformed < m_Classifiers.length; m_NumIterationsPerformed++) { if (m_Debug) { System.err.println("Training classifier " + (m_NumIterationsPerformed + 1)); } // 低权重过滤 if (m_WeightThreshold < 100) { trainData = http://www.mamicode.com/selectWeightQuantile(training, >六、总结
训练好了分类器之后,在针对具体instance分类时,会根据mBeta对各基分类器得到的结果进行算数加权,进而得到最终结果,相关代码叫见到不再分析。
总结实在不知道该写些啥,简单说两点吧
1、Weka的AdaBoostM1基本按照标准算法实现得来,唯一的不同之处就是部分权重resampling会委派给基分类器进行实现。
2、基分类器一定要选择弱分类器。
Weka算法Classifier-meta-AdaBoostM1源码分析(二)