Weka學習三(ensemble演算法)
前兩次我們講了資料探勘中比較常見的兩類方法。這次我來介紹一下ensemble(整合技術),總的來說,ensemble技術是歸類在分類中的。它的主要原理是通過整合多個分類器的效果來達到提高分類效果的目的。簡單我們可以通過兩張圖片來看看整合的效果
圖一為多個基分類器單獨工作時的分類效果圖。圖二為整合分類器的分類效果。我們可以看到整合分類器的分類曲線明顯會平滑的多。來個比喻,在一件事情的表決上面,一個人的意見與多個人的意見相比,往往是多個人的意見來的準確一些。這是為什麼我們要提倡民主決策的原因。
Ensemble技術在資料探勘方向主要在以下三個方向做工作:
1. 在樣本上做文章,基分類器為同一個分類演算法,主要的技術有bagging,boosting;
2. 在分類演算法上做工作,即用於訓練基分類器的樣本相同,基分類器的演算法不同,這是本文采用的方法;
3. 在樣本屬性集上做文章,即在不同的屬性空間上構建基分類器,比較出名的是randomforestTree演算法,這個在weka中也有實現。
現在我們來看看ensemble技術在weka中的實現過程。
package com.csdn;
import java.io.File;
import weka.classifiers.Classifier;
import weka.classifiers.Evaluation;
import weka.classifiers.meta.Vote;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.SelectedTag;
import weka.core.converters.ArffLoader;
publicclass SimpleEnsemble {
/**
*@paramargs
*/
publicstaticvoid main(String[] args) {
// TODO Auto-generated method stub
Instances trainIns = null;
Instances testIns =
Classifier cfs1 = null;
Classifier cfs2 = null;
Classifier cfs3 = null;
Classifier[] cfsArray = new Classifier[3];
try{
/*
* 1.讀入訓練、測試樣本
* 在此我們將訓練樣本和測試樣本是由weka提供的segment資料集構成的
*/
File file= new File("C://Program Files//Weka-3-6//data//segment-challenge.arff");
ArffLoader loader = new ArffLoader();
loader.setFile(file);
trainIns = loader.getDataSet();
file = new File("C://Program Files//Weka-3-6//data//segment-test.arff");
loader.setFile(file);
testIns = loader.getDataSet();
//在使用樣本之前一定要首先設定instances的classIndex,否則在使用instances物件是會丟擲異常
trainIns.setClassIndex(trainIns.numAttributes()-1);
testIns.setClassIndex(testIns.numAttributes()-1);
/*
* 2.初始化基分類器
* 具體使用哪一種特定的分類器可以選擇,請將特定分類器的class名稱放入forName函式
* 這樣就構建了一個簡單的分類器
*/
//貝葉斯演算法
cfs1 = (Classifier)Class.forName("weka.classifiers.bayes.NaiveBayes").newInstance();
//決策樹演算法,是我們常聽說的C45的weka版本,不過在我看程式碼的過程中發現有一些與原始演算法有點區別的地方。
//即在原始的C45演算法中,我們規定沒有一個屬性節點在被使用(即被作為一個分裂節點以後,他將被從屬性集合中去除掉)。
//但是在J48中沒有這樣做,它依然在下次分裂點前,使用全部的屬性集合來探測一個合適的分裂點。這樣做好不好?
cfs2 = (Classifier)Class.forName("weka.classifiers.trees.J48").newInstance();
//什麼東東,不知道做什麼用,平常很少用。本想要用LibSVM的,但是由於要載入一些包,比較麻煩。
cfs3 = (Classifier)Class.forName("weka.classifiers.rules.ZeroR").newInstance();
/*
* 3.構建ensemble分類器
*/
cfsArray[0] = cfs1;
cfsArray[1] = cfs2;
cfsArray[2] = cfs3;
Vote ensemble = new Vote();
/*
* 訂製ensemble分類器的決策方式主要有:
* AVERAGE_RULE
* PRODUCT_RULE
* MAJORITY_VOTING_RULE
* MIN_RULE
* MAX_RULE
* MEDIAN_RULE
* 它們具體的工作方式,大家可以參考weka的說明文件。
* 在這裡我們選擇的是多數投票的決策規則
*/
SelectedTag tag1 = new SelectedTag(
Vote.MAJORITY_VOTING_RULE, Vote.TAGS_RULES);
ensemble.setCombinationRule(tag1);
ensemble.setClassifiers(cfsArray);
//設定隨機數種子
ensemble.setSeed(2);
//訓練ensemble分類器
ensemble.buildClassifier(trainIns);
/*
* 4.使用測試樣本測試分類器的學習效果
* 在這裡我們使用的訓練樣本和測試樣本是同一個,在實際的工作中需要讀入一個特定的測試樣本
*/
Instance testInst;
/*
* Evaluation: Class for evaluating machine learning models
* 即它是用於檢測分類模型的類
*/
Evaluation testingEvaluation = new Evaluation(testIns);
int length = testIns.numInstances();
for (int i =0; i < length; i++) {
testInst = testIns.instance(i);
//通過這個方法來用每個測試樣本測試分類器的效果
testingEvaluation.evaluateModelOnceAndRecordPrediction(
ensemble, testInst);
}
/*
* 5.列印分類結果
* 在這裡我們列印了分類器的正確率
* 其它的一些資訊我們可以通過Evaluation物件的其它方法得到
*/
System.out.println( "分類器的正確率:" + (1- testingEvaluation.errorRate()));
}catch(Exception e){
e.printStackTrace();
}
}
}
在weka中主要是通過weka.classifiers.meta.Vote來實現,基分類器是通過基分類器陣列來設定的。同時我們可以自己設定整合分類器的決策方法,較為常用的是多數投票演算法。
我在寫下這篇文章是對ensemble分類器在segment資料集上的分類效果做了一個小小的測試,它對測試集segement-test的分類效果是0.8309的正確率。而我在使用單個分類器NaiveBayes,J48, ZeroR時它們的分類效果分別為0.7704、0.9617、0.1106 這樣我們可以看到,ensemble分類器是可以矯正弱分類器的分類效果的。
總的來說,我在做實驗的過程中,大部分的實驗結果都表明ensemble技術確實是可以提高分類效果。當然這也是有國際上大牛的證明的,可不是我一個人這樣說的。