這一次講的是Ensemble的東西,一位讀者但願我講一下Adaboost的內容,這種Ensemble看起來的確比較嚇人,推薦一篇論文:Ensemble Based Systems in Decision Making. 在這裏全部理論的東西我就不介紹了。dom
與以往同樣,先看buildClassifier函數(我在函數中將不重要的代碼所有去掉):函數
super.buildClassifier(data);ui
if ((!m_UseResampling)&& (m_Classifier instanceof WeightedInstancesHandler)) {this
buildClassifierWithWeights(data);lua
} else {spa
buildClassifierUsingResampling(data);orm
}排序
Adaboost類繼承自RandomizableIteratedSingleClassifierEnhancer類,再看一下這個類的buildClasssifier函數內容:繼承
m_Classifiers = Classifier.makeCopies(m_Classifier, m_NumIterations);ci
這句話是產生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,想一想仍是不講了,與這個函數比較也沒什麼特別的地方。