導讀:無論你的工作內容是什麼,掌握一定的數據分析能力,都可以幫你更好的認識世界,更好的提升工作效率。數據分析除了包含傳統意義上的統計分析之外,也包含尋找有效特徵、進行機器學習建模的過程,以及探索數據價值、找尋數據本根的過程。
本文摘編自《Spark機器學習進階實戰》,如需轉載請聯繫我們
01 數據分析流程
數據分析可以幫助我們從數據中發現有用信息,找出有建設性的結論,並基於分析結論輔助決策。如圖1所示,數據分析流程主要包括業務調研、明確目標、數據準備、特徵處理、模型訓練與評估、輸出結論等六個關鍵環節。
▲圖1 數據分析流程
數據分析能力並非一朝一夕養成的,需要長期紮根業務進行積累,需要長期根據數據分析流程一步一個腳印分析問題,培養自己對數據的敏感度,從而養成用數據分析、用數據說話的習慣。當你可以基於一些數據,根據自己的經驗做出初步的判斷和預測,你就基本擁有數據思維了。
02 數據分析基本方法
數據分析是以目標為導向的,通過目標實現選擇數據分析的方法,常用的分析方法是
1. 彙總統計
統計是指用單個數或者數的小集合捕獲很大值集的特徵,通過少量數值來了解大量數據中的主要信息,常見統計指標包括:
分佈度量:概率分佈表、頻率表、直方圖頻率度量:眾數位置度量:均值、中位數散度度量:極差、方差、標準差多元比較:相關係數模型評估:準確率、召回率彙總統計對一個彈性分佈式數據集RDD進行概括統計,它通過調用Statistics的colStats方法實現。colStats方法可以返回RDD的最大值、最小值、均值、方差等,代碼實現如下:
import org.apache.spark.MLlib.linalg.Vector
import org.apache.spark.MLlib.stat.{MultivariateStatisticalSummary, Statistics}
// 向量[Vector]數據集
val data: RDD[Vector] = ...
// 彙總統計信息
val summary: statisticalSummary = Statistics.colStats(data)
// 平均值和方差
println(summary.mean)
println(summary.variance)
2. 相關性分析
相關性分析是指通過分析尋找不用商品或不同行為之間的關係,發現用戶的習慣,計算兩個數據集的相關性是統計中的常用操作。
在MLlib中提供了計算多個數據集兩兩相關的方法。目前支持的相關性方法有皮爾遜(Pearson)相關和斯皮爾曼(Spearman)相關。一般對於符合正態分佈的數據使用皮爾遜相關係數,對於不符合正態分佈的數據使用斯皮爾曼相關係數。
皮爾遜相關係數是用來反映兩個變量相似程度的統計量,它常用於計算兩個向量的相似度,皮爾遜相關係數計算公式如下:
其中X, Y表示兩組變量,X', Y'表示兩個變量的平均值,皮爾遜相關係數可以理解為對兩個向量進行歸一化以後,計算其餘弦距離(即使用餘弦函數cos計算相似度,用向量空間中兩個向量的夾角的餘弦值來衡量兩個文本間的相似度),皮爾遜相關大於0表示兩個變量正相關,小於0表示兩個變量負相關,皮爾遜相關係數為0時,表示兩個變量沒有相關性。
調用MLlib計算兩個RDD皮爾遜相關性的代碼如下,輸入的數據可以是RDD[Double]也可以是RDD[Vector],輸出是一個Double值或者相關性矩陣。
import org.apache.spark.SparkContext
import org.apache.spark.MLlib.linalg._
import org.apache.spark.MLlib.stat.Statistics
// 創建應用入口
val sc: SparkContext = ...
// X變量
val seriesX: RDD[Double] = ...
// Y變量,分區和基數同seriesX
val seriesY: RDD[Double] = ...
// 使用Pearson方法計算相關性,斯皮爾曼的方法輸入“spearman”
val correlation: Double = Statistics.corr(seriesX, seriesY, "pearson")
// 向量數據集
val data: RDD[Vector] = ...
val correlMatrix: Matrix = Statistics.corr(data, "pearson")
皮爾遜相關係數在機器學習的效果評估中經常使用,如使用皮爾遜相關係數衡量推薦系統推薦結果的效果。
3. 分層抽樣
分層抽樣先將數據分為若干層,然後再從每一層內進行隨機抽樣組成一個樣本。MLlib提供了對數據的抽樣操作,分層抽樣常用的函數是sampleByKey和sampleByKeyExact,這兩個函數是在key-value對的RDD上操作,用key來進行分層。
其中,sampleByKey方法通過擲硬幣的方式進行抽樣,它需要指定需要的數據大小;sampleByKeyExact抽取fkey·nkey個樣本,fkey表示期望獲取鍵為key的樣本比例,nkey表示鍵為key的鍵值對的數量。sampleByKeyExact能夠獲取更準確的抽樣結果,可以選擇重複抽樣和不重複抽樣,當withReplacement為true時是重複抽樣,false時為不重複抽樣。重複抽樣使用泊松抽樣器,不重複抽樣使用伯努利抽樣器。
分層抽樣的代碼如下:
import org.apache.spark.SparkContext
import org.apache.spark.SparkContext._
import org.apache.spark.rdd.PairRDDFunctions
val sc: SparkContext = ...
// RDD[(K, V)]形式的鍵值對
val data = ...
//指定每個鍵所需的份數
val fractions: Map[K, Double] = ...
//從每個層次獲取確切的樣本
val approxSample = data.sampleByKey(withReplacement = false, fractions)
val exactSample = data.sampleByKeyExact(withReplacement = false, fractions)
通過用戶特徵、用戶行為對用戶進行分類分層,形成精細化運營、精準化業務推薦,進一步提升運營效率和轉化率。
4. 假設檢驗
假設檢驗是統計中常用的工具,它用於判斷一個結果是否在統計上是顯著的、這個結果是否有機會發生。通過數據分析發現異常情況,找到解決異常問題的方法。
MLlib目前支持皮爾森卡方檢驗,對應的函數是Statistics類的chiSqTest,chiSqTest支持多種輸入數據類型,對不同的輸入數據類型進行不同的處理,對於Vector進行擬合優度檢驗,對於Matrix進行獨立性檢驗,對於RDD用於特徵選擇,使用chiSqTest方法進行假設檢驗的代碼如下:
import org.apache.spark.SparkContext
import org.apache.spark.MLlib.linalg._
import org.apache.spark.MLlib.regression.LabeledPoint
import org.apache.spark.MLlib.stat.Statistics._
val sc: SparkContext = ...
// 定義一個由事件頻率組成的向量
val vec: Vector = ...
// 作皮爾森擬合優度檢驗
val goodnessOfFitTestResult = Statistics.chiSqTest(vec)
println(goodnessOfFitTestResult)
// 定義一個檢驗矩陣
val mat: Matrix = ...
// 作皮爾森獨立性檢測
val independenceTestResult = Statistics.chiSqTest(mat)
// 檢驗總結:包括假定值(p-value)、自由度(degrees of freedom)
println(independenceTestResult)
// pairs(feature, label).
val obs: RDD[LabeledPoint] = ...
// 獨立性檢測用於特徵選擇
val featureTestResults: Array[ChiSqTestResult] = Statistics.chiSqTest(obs)
var i = 1
featureTestResults.foreach { result =>
println(s"Column $i:\n$result")
i += 1
}
03 簡單的數據分析實踐
為了更清楚的說明簡單的數據分析實現,搭建Spark開發環境,並使用gowalla數據集進行簡單的數據分析,該數據集較小,可在Spark本地模式下,快速運行實踐。
實踐步驟如下:
1)環境準備:準備開發環境並加載項目代碼;
2)數據準備:數據預處理及one-hot編碼;
3)數據分析:使用均值、方差、皮爾遜相關性計算等進行數據分析。
簡單數據分析實踐的詳細代碼參考:ch02\GowallaDatasetExploration.scala,本地測試參數和值如表1所示。
▲表1 本地測試參數和值
1. 環境準備
Spark程常用IntelliJ IDEA工具進行開發,下載地址:www.jetbrains.com/idea/,一般選擇Community版,當前版本:ideaIC-2017.3.4,支持Windows、Mac OS X、Linux,可以根據自己的情況選擇適合的操作系統進行安裝。
(1)安裝scala-intellij插件
啟動IDEA程序,進入“Configure”界面,選擇“Plugins”,點擊安裝界面左下角的“Install JetBrains plugin”選項,進入JetBrains插件選擇頁面,輸入“Scala”來查找Scala插件,點擊“Install plugin”按鈕進行安裝。(如果網絡不穩定,可以根據頁面提示的地址下載,然後選擇“Install plugin from disk”本地加載插件),插件安裝完畢,重啟IDEA。
(2)創建項目開發環境
啟動IDEA程序,選擇“Create New Project”,進入創建程序界面,選擇Scala對應的sbt選項,設置Scala工程名稱和本地目錄(以book2-master為例),選擇SDK、SBT、Scala版本(作者的開發環境:Jdk->1.8.0_162、sbt->1.1.2、scala->2.11.12),點擊“Finish”按鈕完成工程的創建。
導入Spark開發包,具體步驟為:File->Project Structure->Libraries->+New Project Library(Java),選擇spark jars(如:spark-2.3.0-bin-hadoop2.6/jars)和本地libs(如:\book2-master\libs,包括:nak_2.11-1.3、scala-logging-api_2.11-2.1.2、scala-logging-slf4j_2.11-2.1.2)。
(3)拷貝項目代碼
拷貝源代碼中的2rd_data、libs、output、src覆蓋本地開發項目目錄,即可完成開發環境搭建。
除此之外,也可以通過Maven方式Import Project。
2. 準備數據
我們提供的數據格式:
用戶[user] 簽到時間[check-in time] 維度[latitude] 精度[longitude] 位置標識[location id]
數據樣例如下:
準備數據的步驟如下。
(1)數據清洗
在數據清洗階段過濾掉不符合規範的數據,並將數據進行格式轉換,保證數據的完整性、唯一性、合法性、一致性,並按照CheckIn類填充數據,具體實現方法如下:
// 定義數據類CheckIn
case class CheckIn(user: String, time: String, latitude: Double, longitude: Double, location: String)
// 實例化應用程序入口
val conf = new SparkConf().setAppName(this.getClass.getSimpleName).setMaster(mode)
val sc = new SparkContext(conf)
val gowalla = sc.textFile(input).map(_.split("\t")).mapPartitions{
case iter =>
val format = DateTimeFormat.forPattern("yyyy-MM-dd\'T\'HH:mm:ss\'Z\'")
iter.map {
// 填充數據類
case terms => CheckIn(terms(0), terms(1).substring(0, 10), terms(2).toDouble, terms(3).toDouble,terms(4))
}
}
(2)數據轉換
在數據轉化階段,將數據轉換成Vectors的形式,供後面數據分析使用。
// 字段:user, checkins, checkin days, locations
val data = gowalla.map{
case check: CheckIn => (check.user, (1L, Set(check.time), Set(check.location)))
}.reduceByKey {
// 並集 union
case (left, right) =>(left._1 + right._1,left._2.union(right._2),left._3.union(right._3))
}.map {
case (user, (checkins, days:Set[String], locations:Set[String])) =>
Vectors.dense(checkins.toDouble,days.size.toDouble,
locations.size.toDouble)
}
3. 數據分析
通過簡單的數據分析流程,實現均值、方差、非零元素的目錄的統計,以及皮爾遜相關性計算,來實現對數據分析的流程和方法的理解。
簡單的數據分析代碼示例如下:
// 統計分析
val summary: MultivariateStatisticalSummary = Statistics.colStats(data)
// 均值、方差、非零元素的目錄
println("Mean"+summary.mean)
println("Variance"+summary.variance)
println("NumNonzeros"+summary.numNonzeros)
// 皮爾遜
val correlMatrix: Matrix = Statistics.corr(data, "pearson")
println("correlMatrix"+correlMatrix.toString)
簡單數據分析應用運行結果如下:
均值:[60.16221566503564,25.30645613117692,37.17676390393301]
方差:[18547.42981193066,1198.630729157736,7350.7365871949905]
非零元素:[107092.0,107092.0,107092.0]
皮爾遜相關性矩陣:
1.0 0.7329442022276709 0.9324997691135504
0.7329442022276709 1.0 0.5920355112372706
0.9324997691135504 0.5920355112372706 1.0
本文摘編自《Spark機器學習進階實戰》,經出版方授權發佈。
延伸閱讀《Spark機器學習進階實戰》