这一次讲的是Ensemble的东西,一位读者希望我讲一下Adaboost的内容,这种Ensemble看起来的确比较吓人,推荐一篇论文:Ensemble Based Systems in Decision Making. 在这里所有理论的东西我就不介绍了。
与以往一样,先看buildClassifier函数(我在函数中将不重要的代码全部去掉):
super.buildClassifier(data);
if ((!m_UseResampling)&& (m_Classifier instanceof WeightedInstancesHandler)) {
buildClassifierWithWeights(data);
} else {
buildClassifierUsingResampling(data);
}
Adaboost类继承自RandomizableIteratedSingleClassifierEnhancer类,再看一下这个类的buildClasssifier函数内容:
m_Classifiers = Classifier.makeCopies(m_Classifier, m_NumIterations);
这句话是产生m_NumIterations个基分类器。
接下来的是判断是否用Resampling方法,这个先不讲,直接看下面的函数,先讲buildClassifierWithWeights这个函数,代码太长了,我分开讲:
// Select instances to train the classifier on
if (m_WeightThreshold < 100) {
trainData = selectWeightQuantile(training,(double) m_WeightThreshold / 100);
} else {
trainData = new Instances(training, 0, numInstances);
}
最上面那个循环m_Classifiers.length次的循环没有粘,这一段话也没什么意思,就是说先多少样本训练,默认的是100,不是100的时候用selectWeightQuantile函数,这个函数是根据样本权重的比例来选择的,它先根据权重对样本进行排序,再选择样本。如果是默认值,那么当然是选择全部样本。
// Build the classifier
if (m_Classifiers[m_NumIterationsPerformed] instanceof Randomizable)
((Randomizable) m_Classifiers[m_NumIterationsPerformed])
.setSeed(randomInstance.nextInt());
m_Classifiers[m_NumIterationsPerformed].buildClassifier(trainData);
有的分类器是一个Randomizable实例,那么就给它设置种子,然后训练一个分类器。
// Evaluate the classifier
evaluation = new Evaluation(data);
evaluation.evaluateModel(m_Classifiers[m_NumIterationsPerformed],training);
epsilon = evaluation.errorRate();
// Stop if error too small or error too big and ignore this model
if (Utils.grOrEq(epsilon, 0.5) || Utils.eq(epsilon, 0)) {
if (m_NumIterationsPerformed == 0) {
// If we're the first we have to to use it
m_NumIterationsPerformed = 1;
}
break;
}
这一段,看过论文的人应该比较清楚是什么意思,这里也就不解释了。
// Determine the weight to assign to this model
m_Betas[m_NumIterationsPerformed] = Math.log((1 - epsilon)/ epsilon);
reweight = (1 - epsilon) / epsilon;
// Update instance weights
setWeights(training, reweight);
第一行代码对应我刚才讲的论文的图5中的公式15,第二句对应公式13,最后一句对应公式14,下面详细讲一下:
oldSumOfWeights = training.sumOfWeights();
Enumeration enu = training.enumerateInstances();
while (enu.hasMoreElements()) {
Instance instance = (Instance) enu.nextElement();
if (!Utils.eq(m_Classifiers[m_NumIterationsPerformed].
classifyInstance(instance), instance.classValue()))
instance.setWeight(instance.weight() * reweight);
}
// Renormalize weights
newSumOfWeights = training.sumOfWeights();
enu = training.enumerateInstances();
while (enu.hasMoreElements()) {
Instance instance = (Instance) enu.nextElement();
instance.setWeight(instance.weight() * oldSumOfWeights / newSumOfWeights);
}
这段代码也是adaboost的核心了,这个函数就是重新计算每个样本的权重,第一个if是判断是否分类错误,如果分类错误,就在原来的权重上乘上reweight(这地方我还有点不清楚,原论文上应该是分类正确了乘上reweight,公式14)。
底下的那部分代码就是重新归一化权重,没什么特别的。至于另一个函数buildClassifierUsingResampling,想想还是不讲了,与这个函数比较也没什么特别的地方。