Weka演算法Classifier-meta-Bagging原始碼分析
一、Bagging演算法
嚴格來看Bagging並不能算是一種分類演算法,Bagging和Boosting一樣,是一種組合基本分類器的方法,也就是使用多個基分類器來獲取更為強大的分類器,其核心思想是有放回的抽樣。
Bagging演算法的訓練流程:
1、從樣本集中有放回的抽樣M個樣本。
2、用這M個樣本訓練基分類器C。
3、重複這個過程X次,得到若干個基分類器。
Bagging演算法的預測流程:
1、對於新傳入例項A,用這X個新分類器得到一個分類結果的列表。
2、若待分類屬性是數值型(迴歸),求這個列表的算數平均值作為結果返回。
3、若待分類屬性是列舉型別(分類),按這個列表對分類結果進行投票,返回票數最高的。
二、Weka程式碼實現
(1)基分類器
Weka中的預設基分類器使用的是REPTree,也就是Fast decision tree learner,至於這個具體是個什麼,後面我再寫文章進行分析。
- public Bagging() {
- m_Classifier = new weka.classifiers.trees.REPTree();
- }
整個BuildClassifier都是圍繞標m_CalcOutOfBag來展開的,這個m_CalcOutOfBag標識的意思是:是否計算OutofBag的錯誤比例。
假如我們對訓練集M進行抽樣,抽樣的數量和M的數量是一樣的,那麼肯定會有一些樣本並沒有被抽到(為什麼?因為是有放回的抽樣),這個標識就是用來評測這些沒抽到的樣本的準確率,如果沒有這個標,那麼這個準確率到後面就不會被計算了。
- if (m_CalcOutOfBag && (m_BagSizePercent != 100)) {
- thrownew IllegalArgumentException("Bag size needs to be 100% if "
- + "out-of-bag error is to be calculated!");
- }
- int bagSize = data.numInstances() * m_BagSizePercent / 100;
-
Random random = new Random(m_Seed);
- boolean[][] inBag = null;
- if (m_CalcOutOfBag)
- inBag = newboolean[m_Classifiers.length][];
- for (int j = 0; j < m_Classifiers.length; j++) {
- Instances bagData = null;
- // create the in-bag dataset
- if (m_CalcOutOfBag) {
- inBag[j] = newboolean[data.numInstances()];
- // bagData = resampleWithWeights(data, random, inBag[j]);
- bagData = data.resampleWithWeights(random, inBag[j]);
- } else {
- bagData = data.resampleWithWeights(random);
- if (bagSize < data.numInstances()) {
- bagData.randomize(random);
- Instances newBagData = new Instances(bagData, 0, bagSize);
- bagData = newBagData;
- }
- }
其次算出要抽樣的大小。
inBag陣列是用來記錄Instances中哪些樣本被抽到了哪些沒被抽到。
data.resampleWithWeight就是進行有放回的抽樣。
- if (m_Classifier instanceof Randomizable) {
- ((Randomizable) m_Classifiers[j]).setSeed(random.nextInt());
- }
- // build the classifier
- m_Classifiers[j].buildClassifier(bagData);
最後是計算OutOfBag的過程,程式碼我已寫註釋。
- if (getCalcOutOfBag()) { //如果有這個標就計算
- double outOfBagCount = 0.0; //錯誤的權重和
- double errorSum = 0.0;//錯誤的偏差值的和
- boolean numeric = data.classAttribute().isNumeric();//是否是連續數值
- for (int i = 0; i < data.numInstances(); i++) {
- double vote;//代表投票結果
- double[] votes;//代表投票
- if (numeric)
- votes = newdouble[1];//如果是數值,則取平均數,計算平均數的過程一個數組單元就夠了
- else
- votes = newdouble[data.numClasses()];//否則則要進行投票
- // determine predictions for instance
- int voteCount = 0;
- for (int j = 0; j < m_Classifiers.length; j++) {
- if (inBag[j][i])
- continue;//如果已經被取樣,就忽略,因為要計算的是OutOfBag
- voteCount++;//記錄有多少樣本被計算
- if (numeric) {
- votes[0] = m_Classifiers[j].classifyInstance(data.instance(i));//數值型則直接把預測結果累加
- } else {
- double[] newProbs = m_Classifiers[j].distributionForInstance(data
- .instance(i));
- for (int k = 0; k < newProbs.length; k++) {
- votes[k] += newProbs[k]; //列舉型則要把所有列舉概率進行累加
- }
- }
- }
- // "vote"
- if (numeric) {
- vote = votes[0];
- if (voteCount > 0) {
- vote /= voteCount; // 數值型取均值
- }
- } else {
- if (Utils.eq(Utils.sum(votes), 0)) {
- } else {
- Utils.normalize(votes);//歸一化
- }
- vote = Utils.maxIndex(votes); // 選出最大的index
- }
- outOfBagCount += data.instance(i).weight();//累加權重
- if (numeric) {
- errorSum += StrictMath.abs(vote - data.instance(i).classValue())
- * data.instance(i).weight();//累加錯誤偏差
- } else {
- if (vote != data.instance(i).classValue())
- errorSum += data.instance(i).weight();//如果是列舉就對出錯進行計數
- }
- }
- m_OutOfBagError = errorSum / outOfBagCount;//最後取個平均值
- } else {
- m_OutOfBagError = 0;//如果沒有那個標就不計算了
- }
也就是 data.resampleWithWeights(random, inBag[j]);這個方法,感覺看了一下還挺有意思的,就放上來剖析一下。
過載形式有3個,前兩個都會呼叫第三個:
- public Instances resampleWithWeights(Random random, double[] weights) {
- return resampleWithWeights(random, weights, null);
- }
- public Instances resampleWithWeights(Random random, boolean[] sampled) {
- double[] weights = newdouble[numInstances()];
- for (int i = 0; i < weights.length; i++) {
- weights[i] = instance(i).weight();
- }
- return resampleWithWeights(random, weights, sampled);
- }
- public Instances resampleWithWeights(Random random, double[] weights,
- boolean[] sampled) {
- if (weights.length != numInstances()) {
- thrownew IllegalArgumentException("weights.length != numInstances.");
- }
- Instances newData = new Instances(this, numInstances());
- if (numInstances() == 0) {
- return newData;
- }
- // Walker's method, see pp. 232 of "Stochastic Simulation" by B.D. Ripley
- double[] P = newdouble[weights.length];
- System.arraycopy(weights, 0, P, 0, weights.length);
- Utils.normalize(P);
- double[] Q = newdouble[weights.length];
- int[] A = newint[weights.length];
- int[] W = newint[weights.length];
- int M = weights.length;
- int NN = -1;
- int NP = M;
- for (int I = 0; I < M; I++) {
- if (P[I] < 0) {
- thrownew IllegalArgumentException("Weights have to be positive.");
- }
- Q[I] = M * P[I];
- if (Q[I] < 1.0) {
- W[++NN] = I;
- } else {
- W[--NP] = I;
- }
-
相關推薦
Weka演算法Classifier-meta-Bagging原始碼分析
一、Bagging演算法 嚴格來看Bagging並不能算是一種分類演算法,Bagging和Boosting一樣,是一種組合基本分類器的方法,也就是使用多個基分類器來獲取更為強大的分類器,其核心思想是有放回的抽樣。 Bagging演算法的訓練流程: 1、從樣本集中有放回的抽樣M個樣本。 2、用這M
Weka演算法Classifier-trees-RandomTree原始碼分析
一、RandomTree演算法 在網上搜了一下,並沒有找到RandomTree的嚴格意義上的演算法描述,因此我覺得RandomTree充其量只是一種構建樹的思路,和普通決策樹相比,RandomTree會隨機的選擇若干屬性來進行構建而不是選取所有的屬性。
Weka演算法Classifier-tree-J48原始碼分析(一)演算法和基本資料結構
大概一年沒打理部落格了,重新拿起筆不知道該從哪裡寫起,想來想去就從最近手頭用的Weka寫起吧。 Weka為一個Java基礎上的機器學習工具,上手簡單,並提供圖形化介面,提供如分類、聚類、頻繁項挖掘等工具,本篇文章主要寫一下分類器演算法中的J48演算法及其實現。 一、演算
區塊鏈教程Fabric1.0原始碼分析流言演算法Gossip服務端二
區塊鏈教程Fabric1.0原始碼分析流言演算法Gossip服務端二 Fabric 1.0原始碼筆記 之 gossip(流言演算法) #GossipServer(Gossip服務端) 5.2、commImpl結構體方法 //conn.serviceConnection(),啟動連線服務 func (
區塊鏈教程Fabric1.0原始碼分析流言演算法Gossip服務端一
區塊鏈教程Fabric1.0原始碼分析流言演算法Gossip服務端一,2018年下半年,區塊鏈行業正逐漸褪去發展之初的浮躁、迴歸理性,表面上看相關人才需求與身價似乎正在回落。但事實上,正是初期泡沫的漸退,讓人們更多的關注點放在了區塊鏈真正的技術之上。 Fabric 1.0原始碼筆記 之 gossip(流
OpenCV學習筆記(31)KAZE 演算法原理與原始碼分析(五)KAZE的原始碼優化及與SIFT的比較
KAZE系列筆記: 1. OpenCV學習筆記(27)KAZE 演算法原理與原始碼分析(一)非線性擴散濾波 2. OpenCV學習筆記(28)KAZE 演算法原理與原始碼分析(二)非線性尺度空間構建 3. Op
OpenCV學習筆記(30)KAZE 演算法原理與原始碼分析(四)KAZE特徵的效能分析與比較
KAZE系列筆記: 1. OpenCV學習筆記(27)KAZE 演算法原理與原始碼分析(一)非線性擴散濾波 2. OpenCV學習筆記(28)KAZE 演算法原理與原始碼分析(二)非線性尺度空間構
SURF演算法原理與原始碼分析
如果說SIFT演算法中使用DOG對LOG進行了簡化,提高了搜尋特徵點的速度,那麼SURF演算法則是對DoH的簡化與近似。雖然SIFT演算法已經被認為是最有效的,也是最常用的特徵點提取的演算法,但如果不借助於硬體的加速和專用影象處理器的配合,SIFT演算法以現有的計算機仍然很難達到實時的程度。對於需要
區塊鏈教程Fabric1.0原始碼分析ECDSA橢圓曲線數字簽名演算法
兄弟連區塊鏈教程Fabric1.0原始碼分析ECDSA橢圓曲線數字簽名演算法,2018年下半年,區塊鏈行業正逐漸褪去發展之初的浮躁、迴歸理性,表面上看相關人才需求與身價似乎正在回落。但事實上,正是初期泡沫的漸退,讓人們更多的關注點放在了區塊鏈真正的技術之上。 Fabric 1.0原始碼筆記 之 ECDS
64.ImageLoader原始碼分析-磁碟命名和圖片快取演算法
一. 前言 ImageLoader的圖片快取分成磁碟和記憶體兩種,這裡分析一下磁碟快取以及圖片檔名演算法的實現 預設是不儲存在磁碟上的,需要手動開啟開關 如下 DisplayImageOptions options = new DisplayImageOptions.Builder()
63.ImageLoader原始碼分析-記憶體快取演算法
一. 前言 圖片記憶體快取可以提高圖片顯示速度,但是有些問題,比如佔用記憶體,如果不加以控制,甚至可能會OOM 所以,需要提供各種各樣的演算法來控制記憶體的使用,以適應不同的使用場景,目前,ImageLoader提供了若干記憶體管理演算法。 預設記憶體快取是關閉的,需要手動開啟 二. 繼承關係圖
java併發之原子操作類(AtomicLong原始碼分析)和非阻塞演算法
背景 近年來,在併發演算法領域的大多數研究都側重於非阻塞演算法,這種演算法用底層的原子機器指令(例如比較併發交換指令)代替鎖來確保資料在併發訪問中的一致性。非阻塞演算法被廣泛的用於在作業系統和JVM中實現執行緒/程序排程機制、垃圾回收機制以及鎖和其他併發資料結構。 與基於鎖
【轉】【java原始碼分析】Map中的hash演算法分析
全網把Map中的hash()分析的最透徹的文章,別無二家。 2018年05月09日 09:08:08 閱讀數:957 你知道HashMap中hash方法的具體實現嗎?你知道HashTable、ConcurrentHashMap中hash方法
DAGScheduler原始碼分析stage劃分演算法,task最佳位置計算演算法
在DAGScheduler類中的HandleJobSubmitted是job排程的核心入口 進入了newStage()方法它會建立一個stage物件 進入submitStage()方法 進入getMissingParentStages方法() 進入s
STL原始碼分析之copy演算法
前言 在前面分析順序容器和關聯容器時, 總會遇到copy這個函式, 當時並沒有去分析這個函式, 畢竟都能知道他是什麼功能, 本節就來揭開它面紗. copy分析 copy函式原始碼在stl_algobase.h中, 該結構中還有很多其他的演算法實現, 我只是從中挑選出了copy
Openck_Swift原始碼分析——新增、刪除裝置時演算法詳細的實現過程
1 初始加入裝置後、上傳Object的詳細流程 前幾篇部落格中,我們講到環的基本原理即詳細的實現過程,加入我們在初始建立Ring是執行例如以下幾條命令: •swift-ring-builder object.builder 
105 - kube-scheduler原始碼分析 - predicate演算法註冊
一、predicate註冊過程 今天我們來聊聊predicate函式是怎麼被註冊進去的,也就是要執行的一堆predicate是怎麼成為“選中的孩子”。 程式碼位置:pkg/scheduler/factory/plugins.go:111
Android版資料結構與演算法(五):LinkedHashMap核心原始碼徹底分析
上一篇基於雜湊表實現HashMap核心原始碼徹底分析 分析了HashMap的原始碼,主要分析了擴容機制,如果感興趣的可以去看看,擴容機制那幾行最難懂的程式碼真是花費了我很大的精力。 好了本篇我們分析一下HashMap的兒子LinkedHashMap的核心原始碼,提到LinkedHashMap做安卓的同學肯
redis原始碼分析與思考(三)——字典中鍵的兩種hash演算法
在Redis字典中,得到鍵的hash值顯得尤為重要,因為這個不僅關乎到是否字典能做到負載均衡,以及在效能上優勢是否突出,一個良好的hash演算法在此時就能發揮出巨大的作用。而一個良好的has
【Go 原始碼分析】從 sort.go 看排序演算法的工程實踐
go version go1.11 darwin/amd64file: src/sort/sort.go 排序演算法有很多種類,比如快排、堆排、插入排序等。各種排序演算法各有其優劣性,在實際生產過程中用到的排序演算法(或者說 Sort 函式)通常是由幾種排序演算法組