1. 程式人生 > >Spark隨機森林演算法對資料分類(一)——計算準確率和召回率

Spark隨機森林演算法對資料分類(一)——計算準確率和召回率

1.召回率和正確率計算

對於一個K元的分類結果,我們可以得到一個KK的混淆矩陣,得到的舉證結果如下圖所示。
這裡寫圖片描述

從上圖所示的結果中不同的元素表示的含義如下:
mij :表示實際分類屬於類i,在預測過程中被預測到分類j

對於所有的mij可以概括為四種方式不同型別的資料:

TP(真正):真正的分類結果屬於i預測的結果也屬於i,此時對於 mij 而言i=j

FN(假負):真正的分類結果不屬於分類i預測的分類結果也屬於分類i

TN (真負) :真正的分類結果屬於分類i預測的結果不屬於分類i

FP (假正) :真正的分類結果不屬於分類i預測的結果屬於分類i
那麼召回率的計算公式如下:

recall=TPTP+TN
precision=TPTP+FP
其中:

TPp=mpp:表示對於類p而言預測正確的個體的數目。

TNp=ki=1,ipmpi:表示對本來屬於分類p,預測的結果不屬於分類p的個數。

FPp=ki=1,ipmip:表示對於本來不屬於分類p的個體,預測的結果屬於分類p的個數。

2 隨機森林中召回率和正確率的計算

import org.apache.log4j.{Level, Logger}
import org.apache.spark.mllib.evaluation.MulticlassMetrics
import org.apache.spark.mllib.regression.LabeledPoint
import
org.apache.spark.{SparkConf, SparkContext} import org.apache.spark.mllib.tree.RandomForest import org.apache.spark.mllib.tree.model.RandomForestModel import org.apache.spark.mllib.util.MLUtils import org.apache.spark.rdd.RDD /** * Created by august on 17-6-1. */ object Main { var beg = System.currentTimeMillis() //設定日誌檔案為錯誤顯示
Logger.getLogger("org").setLevel(Level.ERROR) //設定application名稱,並建立入口物件 val conf = new SparkConf().setAppName("rf") val sc = new SparkContext(conf) //載入hadoop中的資料資訊,這裡將IP地址資訊隱去 val data = MLUtils.loadLibSVMFile(sc,"hdfs://***.***.***.***:8020/august/random_forest/Day2.txt") // 將資料資訊劃分為70%的測試集和30%的訓練集 val splits = data.randomSplit(Array(0.7, 0.3)) val (trainingData, testData) = (splits(0), splits(1)) //將資料一共分成12個類 val numClasses = 13 val categoricalFeaturesInfo = Map[Int, Int]() val numTrees = 100 val featureSubsetStrategy = "auto" // Let the algorithm choose. val impurity = "entropy" val maxDepth = 10 val maxBins = 32 val model = RandomForest.trainClassifier(trainingData, numClasses, categoricalFeaturesInfo, numTrees, featureSubsetStrategy, impurity, maxDepth, maxBins) val metrics = getMetrics(model,testData) //計算精確度(樣本比例) val precision = metrics.accuracy; //計算每個樣本的準確度(召回率) val recall = (1 to 11).map( //DecisionTreeModel模型的類別號從1開始 cat => (metrics.precision(cat), metrics.recall(cat)) ) val end = System.currentTimeMillis() //耗時時間 var castTime = end - beg def main(args: Array[String]) { println("========================================================================================") //精確度(樣本比例) println("精確度: " + precision) println("========================================================================================") //準確度(召回率) println("準確度: ") recall.foreach(println) println("========================================================================================") println(" 執行程式耗時: " + castTime/1000 + "s") } def getMetrics(model: RandomForestModel, data: RDD[LabeledPoint]): MulticlassMetrics = { val predictionsAndLabels = data.map(example => (model.predict(example.features), example.label)) new MulticlassMetrics(predictionsAndLabels) } }

在上述程式碼中,實現了對於隨機森林分類後的結果計算召回率和每一個類的準確率。

2.1 資料獲取並生成訓練集和測試集

在下述程式碼中我們主要進行了以下工作:

(1)設定spark日誌輸出資訊為Level.ERROR,在錯誤狀態下輸出日誌資訊。

(2)設定Application的入口物件。

(3)從Hadoop中獲取資料資訊,值的注意的是這裡的資料資訊的資料格式為libsvm格式,從一般資料格式轉換到libsvm格式的轉換方式可以參考另一篇文章。

(4)將所有的資料資訊劃分為traingingData訓練集和testData測試集,其中trainingData佔資料集中的70%,testData佔30%。

Logger.getLogger("org").setLevel(Level.ERROR)
val conf = new SparkConf().setAppName("rf")
val sc = new SparkContext(conf)
val data = MLUtils.loadLibSVMFile(sc, "hdfs://***.***.***.***:8020/august/random_forest/Day2.txt")
val splits = data.randomSplit(Array(0.7, 0.3))
val (trainingData, testData) = (splits(0), splits(1))

2.2 設定隨機森林引數並訓練模型

在RandomForest.trainClassifier中對隨機森林模型進行訓練,將訓練後模型的結果返回到model裡面。在訓練隨機森林模型前對引數的設定如下:

numClasses:表示一共分為多少個類。
categoricalFeaturesInfo:為空,表示所有的特徵為連續型變數
numTrees:表示隨機森林裡麵包含的決策樹的個數
featureSubsetStrategy:表示特徵子集的選取方式。
impurity:“entropy”表示純度的計算方式採用資訊熵的方式計算。
maxDepth:表示數的最大深度為10
maxBins:表示最大裝箱數為32

val numClasses = 13
val categoricalFeaturesInfo = Map[Int, Int]()
val numTrees = 100
val featureSubsetStrategy = "auto" // Let the algorithm choose.
val impurity = "entropy"
val maxDepth = 10
val maxBins = 32
val model = RandomForest.trainClassifier(trainingData, numClasses, categoricalFeaturesInfo,
  numTrees, featureSubsetStrategy, impurity, maxDepth, maxBins)

2.3 計算正確率和召回率

函式功能:在Spark API中給出的MulticlassMetrics文件顯示,建立一個MulticlassMetrics使用RDD作為引數傳入,在RDD中是儲存了一個兩個Double型別的資料,其中第一個表示預測的結果,第二個表示標籤的結果。

傳入引數:model: RandomForestModel, data: RDD[LabeledPoint]其中model表示訓練出來的隨機森林模型,data用來表示測試資料集合。

返回結果:返回一個MulticlassMetrics的例項物件,用來計算整個資料集合的準確度和不同類的準確度。

  def getMetrics(model: RandomForestModel, data: RDD[LabeledPoint]): MulticlassMetrics = {
    val predictionsAndLabels = data.map(example => (model.predict(example.features), example.label))
    new MulticlassMetrics(predictionsAndLabels)
  }

在下述的程式碼中,我們通過對每一個類求出precision的值recall的值存放在recall中。

  val metrics = getMetrics(model,testData)
  //計算精確度(樣本比例)
  val precision = metrics.accuracy;
  //計算每個樣本的準確度(召回率)
  val recall = (1 to 11).map(     //DecisionTreeModel模型的類別號從0開始
    cat => (metrics.precision(cat), metrics.recall(cat))
  )

3. 實驗結果

我們通過下述程式碼輸出實驗結果。

def main(args: Array[String]) {
    println("========================================================================")
    //精確度(樣本比例)
    println("精確度: " + precision)
    println("========================================================================")
    //準確度(召回率)
    println("準確度: ")
    recall.foreach(println)
    println("========================================================================")
    println(" 執行程式耗時: " + castTime/1000 + "s")
  }

執行程式得到的實驗結果如下圖所示。
這裡寫圖片描述