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")
  }

運行程序得到的實驗結果如下圖所示。
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章