Java机器学习库ML之五样本不均衡
樣本不均衡的問題是指訓練集中類別之間的樣本數據量比例失衡。有研究表明,部分學習任務,在類別出現1∶35比例時就會使某些分類學習方法無效,甚至1∶10比例也會。樣本不均衡導致的問題有:
1)少數類所包含的信息就會很有限,從而難以確定少數類數據的分布,即在其內部難以發現規律,進而造成少數類的識別率低;
2)數據碎片,很多分類算法采用分治法,樣本空間的逐漸劃分會導致數據碎片問題,這樣只能在各個獨立的子空間中尋找數據的規律,對于少數類來說每個子空間中包含了很少的數據信息,一些跨空間的數據規律就不能被挖掘出來;
3)不恰當的歸納偏置,許多歸納推理系統在存在不確定時往往傾向于把樣本分類為多數類。
一般解決方法有:
1、擴大數據集:當遇到類別不均衡問題時,增加樣本數據是一個最簡單的思路,有沒有那么多樣本就很難說了。
2、對數據進行重采樣:對小類的數據樣本進行采樣來增加小類的數據樣本個數,即過采樣(over-sampling ,采樣的個數大于該類樣本的個數)。對大類的數據樣本進行采樣來減少該類數據樣本的個數,即欠采樣(under-sampling,采樣的次數少于該類樣本的個數)。
1)過抽樣是抽樣處理不平衡數據的最常用方法,基本思想就是通過改變訓練數據的分布來消除或減小數據的不平衡。通過抽樣方法通過增加少數類樣本來提高少數類的分類性能,最簡單的辦法是簡單復制少數類樣本,缺點是可能導致過擬合,沒有給少數類增加任何新的信息。改進的過抽樣方法通過在少數類中加入隨機高斯噪聲或產生新的合成樣本等方法。對svm作用待觀察。
2)欠抽樣方法通過減少多數類樣本來提高少數類的分類性能,最簡單的方法是通過隨機地去掉一些多數類樣本來減小多數類的規模,缺點是會丟失多數類的一些重要信息,不能夠充分利用已有的信息。
3、嘗試不同的分類學習算法
強烈建議不要對待每一個分類都使用自己喜歡而熟悉的分類算法。應該使用不同的算法對其進行比較,因為不同的算法使用于不同的任務與數據。決策樹往往在類別不均衡數據上表現不錯。它使用基于類變量的劃分規則去創建分類樹,因此可以強制地將不同類別的樣本分開。目前流行的決策樹算法有:C4.5、C5.0、CART和Random Forest等。
?
這里通過ML庫作了一個Bagging法的思想來處理樣本不均衡。bagging使用bootstrap抽樣,其基本思想是:將一個弱學習算法使用多次(每次使用一個放回的重復抽樣),并對結果進行投票,最后選取投票多的結果作為最終的結果(也可以通過得票的平均值用于連續值的預測)。bagging對使用的分類算法有要求,必須為不穩定的算法(不穩定是指數據集的小的變動能夠使分類結果顯著的變動)比如:決策樹,神經網絡算法、svm等。本文這里直接用KNN來做案例,參考代碼如下:
?
/*** This file is part of the Java Machine Learning Library* * The Java Machine Learning Library is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.* * The Java Machine Learning Library is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.* * You should have received a copy of the GNU General Public License* along with the Java Machine Learning Library; if not, write to the Free Software* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA* * Copyright (c) 2006-2012, Thomas Abeel* * Project: http://java-ml.sourceforge.net/* */ package com.gddx;import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map;import be.abeel.util.Pair; import net.sf.javaml.classification.Classifier; import net.sf.javaml.classification.KNearestNeighbors; import net.sf.javaml.core.Dataset; import net.sf.javaml.core.DefaultDataset; import net.sf.javaml.core.DenseInstance; import net.sf.javaml.core.Instance; import net.sf.javaml.sampling.Sampling; import net.sf.javaml.tools.data.FileHandler;/*** This tutorial show how to use a the k-nearest neighbors classifier.* * @author Thomas Abeel* */ public class TutorialKNN {/*** Shows the default usage of the KNN algorithm.*/public static void main(String[] args)throws Exception {/* Load a data set */Dataset data = FileHandler.loadDataset(new File("D:\\tmp\\javaml-0.1.7-src\\UCI-small\\iris\\iris.data"), 4, ",");Sampling s = Sampling.SubSampling;int iretSam=10;//有放回重復采樣10次List<String> lOut=new ArrayList<String>();while (iretSam>0){Pair<Dataset, Dataset> sam_data = s.sample(data, (int) (data.size() * 0.8));Classifier knn = new KNearestNeighbors(5);knn.buildClassifier(sam_data.x());/* Counters for correct and wrong predictions. */int correct = 0, wrong = 0;/* Classify all instances and check with the correct class values */for (Instance inst : sam_data.y()) {Object predictedClassValue = knn.classify(inst);Object realClassValue = inst.classValue();if (predictedClassValue.equals(realClassValue))correct++;elsewrong++;}System.out.println("Correct predictions " + correct);System.out.println("Wrong predictions " + wrong);//預測Dataset pre_data = FileHandler.loadDataset(new File("D:\\tmp\\javaml-0.1.7-src\\UCI-small\\iris\\pre_iris.data"),",");for(Instance inst:pre_data){double[] values = new double[4]; for(int i=0;i<4;i++) values[i]=inst.value(i);Instance pre_inst = new DenseInstance(values); //無標記,4列特征參與訓練Object pre_classvalue = knn.classify(pre_inst);//預測結果Object id=(int)inst.value(4);lOut.add(id+"|"+pre_classvalue);//輸出id+標記}iretSam--;} //重復采樣和訓練后,用投票法決定類別Map<String,Integer> mISe=new HashMap<String,Integer>();//Iris-setosaMap<String,Integer> mIVe=new HashMap<String,Integer>();//Iris-versicolorMap<String,Integer> mIVi=new HashMap<String,Integer>();//Iris-virginicafor(String sout:lOut){ String id=sout.split("\\|")[0];String classvalue=sout.split("\\|")[1];if(classvalue.equals("Iris-setosa")){if(mISe.containsKey(id)){int value=mISe.get(id);value++;mISe.put(id, value);}else mISe.put(id, 1);}else if (classvalue.equals("Iris-versicolor")){if(mIVe.containsKey(id)){int value=mIVe.get(id);value++;mIVe.put(id, value);}else mIVe.put(id, 1);}else if (classvalue.equals("Iris-virginica")){if(mIVi.containsKey(id)){int value=mIVi.get(id);value++;mIVi.put(id, value);}else mIVi.put(id, 1);} }for(int i=1;i<=12;i++){ String key=String.valueOf(i);int mISe_value=0;if (mISe.containsKey(key)) mISe_value= mISe.get(key); int mIVe_value=0;if (mIVe.containsKey(key)) mIVe_value= mIVe.get(key); int mIVi_value=0;if (mIVi.containsKey(key)) mIVi_value = mIVi.get(key); if(mISe_value>=mIVe_value && mISe_value>=mIVi_value)System.out.println("樣本:"+key+"的類別是:Iris-setosa");else if(mIVe_value>=mISe_value && mIVe_value>=mIVi_value)System.out.println("樣本:"+key+"的類別是:Iris-versicolor");else if(mIVi_value>=mISe_value && mIVi_value>=mIVe_value)System.out.println("樣本:"+key+"的類別是:Iris-virginica");} }}?數據集到ML庫官方下載:http://java-ml.sourceforge.net/content/databases
總結
以上是生活随笔為你收集整理的Java机器学习库ML之五样本不均衡的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java机器学习库ML之四模型训练和预测
- 下一篇: Java机器学习库ML之六关于模型迭代训