Spark高階資料分析
第一章 大資料分析
1.資料科學麵臨的挑戰
1)資料分析絕大部分工作是資料預處理包括清洗,處理,融合,挖掘以及其他操作,即使模型調優階段,特徵提取和選擇上花費的時間比選擇和實現演算法時間更多
2)迭代與資料科學緊密相關,比如模型優化時採用的隨機梯度下降和最大似然估計,構建模型時需要選擇正確特徵,挑選合適演算法,執行顯著性測試,找到合適超引數
3)構建完表現卓越的模型不等於大功告成,模型需要定期甚至實時重建
第二章 用Scala和Spark進行資料分析
資料清洗是資料分析的第一步,資料分析工具語言Scala能完成所有事情
資料清洗一般包括身份解析,記錄去重,合併-清除,列表清洗,統稱為記錄關聯
記錄關聯問題描述:
需要從一個或者多個源系統的記錄中,根據記錄的屬性判斷記錄是否是相同實體
由於RDD都是臨時存在的,因此如果後面仍然需要用到此RDD,則需要在當前就快取此RDD,這樣再次使用此RDD時可直接從記憶體中獲取,節約計算開銷
2.1 聚合
mds為RDD[MatchData]
val grouped=mds.groupBy(md=>md.matched)//根據matched來聚合分為true,false兩類
grouped.mapValues(x=>x.size) //grouped中每個元素Key=true or false,Values則為多行記錄
2.2 概要統計
Parsed.map(md=>md.score(0)).filter(!isNaN(_)).stats() //可以獲得
2.3 直方圖
parsed.map(md=>md.matched).countByValue().toSeq.sortBy(_._1)
2.4zip
val nas1=Array(1.0,Double.NaN).map(d=>NAStatCounter(d)) //nas1=Array(NAStatCounter(1.0),NAStatCounter(NaN))
val nas2=Array(Double.NaN,2.0).map(d=>NAStatCounter(d)) //同理nas2
val nas3=nas1.zip(nas2)//Array((NAStatCounter(1.0),NAStatCounter(NaN)),(NAStatCounter(NaN),NAStatCounter(2.0)))
nas3.map(case(a,b)=>a.merge(b))//相當於Array((NAStatCounter(1.0).merge(NAStatCounter(NaN)),NAStatCounter(NaN).merge(NAStatCounter(2.0)))
第三章 音樂推薦和Audioscrobbler資料集
隱式反饋資料:Audioscrobbler資料集覆蓋了大量使用者和藝術家,同時包含了更多總體資訊,而單條記錄資訊較少,這類資料稱為隱式反饋資料
user_artist_data.txt 使用者ID-藝術家ID-播放次數
artist_data.txt 藝術家ID-藝術家名
artist-alias.txt 將拼寫錯誤的藝術家ID或者ID變體對應到該藝術家的規範ID 錯誤ID-規範ID
3.1 交替最小二乘法推薦
根據兩個使用者播放過許多相同的歌曲來判斷他們可能都喜歡某首歌,稱為協同過濾
利用user_artist_data.txt可構建一個稀疏矩陣,有m個使用者,和n個藝術家,則此稀疏矩陣為m*n,(i,j)的值表示第i個使用者播放第j個藝術家的作品次數,此稀疏矩陣A=X*YT
使用者-特徵矩陣和特徵-藝術家矩陣的乘積結果約等於稠密使用者-藝術家相互關係矩陣的完整估計,求解X,Y可採用交替最小二乘法
AiY(YTY)-1=XI(X的每一行可分別計算,因此並行化),目標是最小化|AiY(YTY)-1-XI|,或者最小化兩個矩陣的平方誤差,實際會藉助QR分解
ALS演算法特徵是稀疏的輸入資料、可以用簡單的線性代數運算求最優解、資料本身可並行化這三點導致大資料計算非常快
Spark Mllib的ALS演算法要求使用者和產品的ID必須為整數型,而且是32位非負整數
1)資料清洗,過濾掉不合規範的資料
2)構建訓練集和模型
mkString()常用作把集合元素表示成某種形式分隔的字串
userFraction 使用者特徵矩陣
productFraction 商品特徵矩陣
3)核查推薦結果
看實際使用者點選過得藝術家和推薦的藝術家是否一致
4)評價推薦質量
AUC(BinaryClassificationMetrics):隨機選擇的好推薦高於壞推薦的概率,作為普遍和總和的測量整體模型質量的手段
AUC的輸入為檢驗集CV(每個使用者對應的“正面的”或者“好的”藝術家)和預測函式(每個使用者-藝術家對轉換成預測Rating)
MAP(RankingMetrics):準確率,召回率,平均準確度,更強調最前面的推薦質量
選擇模型並評估模型準確度是通用做法,資料通常分為訓練集(訓練模型)、檢驗集(評估模型)、測試集
5)選擇超引數
ALS.trainImplicit()引數包括:
rank=10模型的潛在因素個數,即“使用者-特徵”和“產品-特徵”矩陣的列數(rank影響不明顯)
Iterations=5 迭代次數
lambda=0.01標準的過擬合引數,值越大越不容易產生過擬合,但值太大會降低分解的準確性(lambda越大模型效果越好)
alpha=1.0 被觀察到的“使用者-產品”互動相對沒被觀察到的互動的權重(模型知道使用者聽過什麼時比不知道使用者聽過什麼時要好)
可以將推薦引擎得到的結果儲存在HBase便於快速查詢,且對於推薦模型可以儲存在檔案中
第四章 用決策樹演算法預測森林植被
趨均數迴歸:父代豌豆大,子代豌豆也大,但比父代小;父代豌豆小,子代豌豆也小,但比父代大,因此斜率為正但小於1
何謂迴歸:根據某個值預測另外一個值的思想,迴歸通常用作預測,迴歸通常一側數值型數量,比如大小,收入和溫度;分類則只預測標號或者類別
監督學習:需要告訴其類別,然後訓練出預測規則,分類(支援向量機,邏輯迴歸,樸素貝葉斯,神經網路,深度學習),預測
非監督學習:比如聚類
4.1向量和特徵
維度、預測指標或者變數都稱為特徵,特徵分為類別型特徵和數值型特徵,可將目標作為附加特徵
比如當天天氣的特徵向量為12.5,15.5,0.10,晴朗,0,17,2,其中17.2作為目標是當天天氣的附加特徵
迴歸問題的目標是數值型特徵,分類問題的目標是類別型特徵
4.2 決策樹和決策森林
基於決策樹的優點:
1)容易並行化,對資料中的離散點具有魯棒性
2)演算法可以接受不同型別和量綱的資料,對資料型別和尺度不相同的情況不需要做預處理或者規範化
3)理解和推理起來相對直觀
決策樹類似於多重if語句判斷
4.3 Covtype資料集
由於Vector+Label=LabeledPoint,Vector為特徵值,Label為目標,由於Spark Mllib庫中Vector只能是Double型別,因此若資料中存在類別特徵需要編碼轉換成數值特徵
1)採用one-hot編碼可以將N個類別特徵->N個數值特徵,比如多雲,有雨,晴朗->(1,0,0),(0,1,0),(0,0,1)
2)採用直接對映比如規定多雲=1.0,有雨=2.0,晴朗=3.0
4.4 構建決策樹模型
val model=DecisionTree.trainClassifier(trainData,7,Map[Int,Int](),”gini”,4,100)
除了第一個引數外,其餘均為超引數
第二個引數為資料集中目標的取值個數7個,即目標可能取值為7種
第三個引數為Map儲存類別型特徵的資訊
第四個引數gini ,補償函式
第五個引數4為最大深度
第六個引數為最大桶數100
MulticlassMetrics計算分類器預測質量的標準指標
BinaryclassficationMetrics提供類似的評價指標,但只適用於類別型目標只有兩個可能取值
所謂的混淆矩陣的每個行對應實際的正確類別值;每一列對應預測值,第i行第j列元素代表正確類別為i的樣本被預測為類別為j的次數,對角線上的元素表示預測正確的次數,剩餘的為預測錯誤的次數
準確度:預測正確的樣本數佔整個樣本的比例
召回率:被分類器標記為“正”而且確實為“正”的樣本與所有本來為“正”的樣本比例
每種類別在訓練集所佔比例*每種類別在檢驗集所佔比例=每種類別的總體準確度,將每種類別的總體準確度累加所得即為整體的準確度
4.5決策樹的超引數
包括最大深度,最大桶數,不純性度量
1)最大深度:對決策樹的最大層數限制,避免過擬合
決策樹演算法為每層生成可能的決策規則,對於數值型特徵,決策採用特徵>=值的形式;對於類別型特徵,決策採用在(值1,值2,...)中的形式;決策規則的集合稱為“桶”,桶的數目越多,需要處理的時間越多但找到決策規則可能更優;好規則可把訓練集資料的目標值分為相對是同類或者純的子集,最好的規則意味著最小化規則對應的兩個子集的不純性;不純性的度量方式:Gini不純度或者熵
Gini不純度直接與隨機猜測分類器的準確度相關(1-每個類別的比例與自身的乘積之和)
熵不純度來源於資訊理論中熵的計算,Spark的實現預設採用Gini不純度
4.6決策樹調優
最大桶數越多越好,會減慢模型構造過程且增加記憶體的使用量
最大深度能提高準確度,但有個拐點,超過它之後就沒有用
在所有情況下都應該試試兩種不純性度量,有時候gini表現好點,有時候熵表現好點
檢驗集評估適合訓練集的引數,測試集評估適合檢驗集的超引數,測試集保證了對最終選定超引數即模型準確度的無偏估計
最後一步需要利用測試集評估檢驗集選定的超引數和(訓練集+檢驗集)下構造的模型,若得到的準確率與CV集所得的準確率差不多,則估計可靠
整體過程大致為:
1)利用trainData訓練得到決策樹模型
2)利用cvData找到最優的超引數組合
3)利用trainData&cvData以及最優的超引數組合訓練出新的決策樹模型
4)利用testData評估該模型的準確度,並與以trainData作為訓練集,cvData作為測試集時的準確度比較,若相差不大,則估計可靠
4.7重談類別型特徵
直接使用類別型特徵
空Map(),不把任何特徵當做類別型
Map()中的key指輸入向量Vector的下標,value指類別型特徵的不同取值個數
通過吧類別型特徵真正當做類別型,分類器的準確度提高近3%
4.8 隨機決策森林
隨機森林的關鍵在於所及的構建多顆決策樹,多顆決策樹的平均預測作為最終的結果
val forest=RandomForest.trainClassifier(trainData,7,Map(10->4,11->40),20,”auto”,”entropy”,30,300)
20為隨機森林由20個獨立的決策樹組成
auto特徵決策樹每層的評估特徵選擇策略,決策規則只考慮全部特徵的一個子集,往往不會產生過擬合現象
第五章 基於K均值聚類的網路流量異常檢測
K-Means演算法是最經典的無監督學習演算法嗎,K值即為該聚類模型的超引數
點與點相似代表其距離小,這裡的距離只歐式距離,簇群的中心為質心,它是簇群中所有點的算術平均值,資料點實際上等同於特徵向量
5.1資料準備
每個連線佔一行,共38個特徵,包括髮送位元組數,登入次數,TCP錯誤數
由資料分析可知smurf與neptune型別的連線攻擊較多
資料清洗:刪除類別型列和最後的標識列
5.2K值選擇
隨著K值的增加,平均質心距離先減少後增加,但只能取得區域性最優情況,Spark Mllib採用K均值||
setRuns()設定給定K值時執行次數,每次隨機選擇初始質心,然後從多次聚類結果中選擇最優的情況
setEpsilon()增加迭代時間可以優化聚類結果,控制聚類過程中簇質心進行有效移動的最小值
5.3特徵的規範化
第六章 基於潛在語義分析演算法分析維基百科
潛在語義分析:是一種自然語言處理和資訊檢索技術,目的是更好地理解文件語料庫以及文件中詞項的關係,它將語料庫提煉成一組相關概念,每個概念捕捉資料中一個不同主題,且通常與語料庫討論的主題相符,每個概念分為三個屬性:1)語料庫中文件的相關度2)語料庫中詞項的相關度3)概念對描述主題的重要性評分;它可以計算詞項與詞項,文件與文件,詞項與文件之間的相似度評分,這些相似度度量方法適合根據詞項查詢相關文件,按主題將文件分組和找到相關詞項等任務
LSA在降維過程中採用奇異值分解的線性代數技術,首先根據詞項在文件中出現的次數構造一個詞項-文件矩陣,每個文件對應一列,每個詞項對應一行,矩陣中的每個元素代表某個詞項在對應文件中的重要性(權重),接著SVD可將矩陣分解為三個子矩陣,其中一個矩陣代表文件出現的概念,兩一個代表詞項對應的概念,還有一個代表每個概念的重要度
6.1 詞項-文件矩陣
每一行代表詞項,每一列代表文件,每個值代表詞項在文件中的權重,其中權重的計算規則為TF-IDF
需要對原始的維基百科到處檔案轉換成詞項-文件矩陣需要進行許多預處理:
1)輸入XML檔案,每個文件由<page>標籤分隔
2)將純文字拆成詞條(token)
3)將詞條的不同曲折詞綴還原成詞根,稱為詞形歸併
4)詞條用於計算詞項頻率和文件頻率
6.2 獲取資料
1)需要利用XmlInputFormat讀取HDFS上的每個page的內容
2)利用wikipedia提供的API將每個page的內容->(page.getTitle,page.getContent)
6.3詞形合併
1)像the和is之類的常用詞不會為模型提供有用資訊,因此要去掉這些停用詞
2)相同意思的詞項可能存在不同詞形,比如monkey和monkeys不能算作不同詞項,再比如nationalize和nationalization,將這些不同曲折詞綴合併成單個詞項的過程稱為詞幹還原或者詞形歸併
6.5 計算TF-IDF
1)得到每個文件中每個詞項出現的頻次
2)得到每個文件中總的頻次
3)得到總的文件數
4)docTermFreqs.flatMap(_.keySet).map((_,1)).reduceByKey(_+_) 得到每個item在多少個文件出現過
5)由於spark Mllib只能處理數值型特徵,因此需要將item=>id,idfs.keys.zipWithIndex.toMap
6.6 奇異值分解
M=USVT
U為m*k維矩陣,U中的列是文件空間的正交基,m個文件和k個概念
S為k*k對角矩陣,每個對角代表概念的強度
V為n*k型矩陣,V中的列是詞項空間的正交基,k個概念和n個詞項
m為文件個數,n為詞項個數,k為要保留的概念個數
計算奇異值分解的過程:
1)val mat=new RowMatrix(termDocMatrix)
2)val k=1000
3)val svd=mat.computeSVD(k,computeU=true)
6.7找出重要概念
Val v=svd.V //V矩陣,詞項對概念的重要度
val topTerms=new ArrayBuffer[Seq(String,Double)]()
val arr=v.toAttay //將矩陣轉換成陣列
for(i<-0 until numConcepts){
val offs=i*v.numRows
val termWeights=arr.slice(offs,offs+v.numRows).zipWithIndex //求每個term的權重
val sorted=termWeights.sortBy((-)_._1)
topTerms+=sorted.take(numTerms).map{
case(score,id) =>(termIds(id,score))
}
}
topTerms
得到每個概念(主題)相關的詞項和文件
6.8 基於低維近似的查詢和評分
餘弦相關度度量可以明確的標識兩個詞項的相關度得分,餘弦相似度可以通過點乘除以向量的長度得到,廣泛使用餘弦相關度度量作為文件和詞項相似度的指標
6.9詞項-詞項相關度
LSA演算法背後的思想是低階矩陣對資料更有用的表示
1)合併相關詞項處理同義詞
2)對詞項的不同含義賦予低的權重處理多義詞
3)過濾噪聲
如何得到詞項-詞項之間的相似度
1)V點乘s=>Vs,然後對Vs進行歸一化
2)根據normalizedVS和查詢詞項termId得到查詢詞項所在行向量rowVec
3)查詢詞項行向量rowVec*normalizedVS->termScores //得到每次詞項與查詢詞項的相似度
4)按照相似度從大到小排序->得到與查詢詞項最相關的N個詞項
6.10 文件-文件相關度
1)建立US
Val US=mutiplyByDiagonalMatrix(svd.U,svd.s) //建立US
2)歸一化US
Val normalizedUS=rowsNormalized(US)
3)根據查詢文件ID即docId與歸一化矩陣normalizedUS得到docRowArr
val docRowArr=row(normalizedUS,docId) //在US中查詢給定docId對應的行
4)將文件行->文件行向量
Val docRowVec=Matrices.dense(docRowArr.length,1,docRowArr)
5)文件行向量與歸一化US相乘
Val docScores=normalizedUS.multiply(docRowVec) //每個文件與查詢文件的相關度
6)找出相關度最高的前N個文件
Val allDocWeights=docScores.rows.map(_.toArray(0)).zipWithUniqueId().filter(!_._1.isNaN)
6.11 詞項-文件相關度
1)在V中根據termId找到查詢詞對應的行<以及行向量
Val rowArr=row(V,termId).toArray //找到termId所對應的行向量
Val rowVec=Matrics.dense(termRowArr.length,1,termRowArr)
2)找到查詢詞相關的文件
Val docScores=US.multiply(termRowVec)
3)找到查詢詞最相關的前N個文件
Val allDocWeights=docScores.rows.map(_.toArray(0)).zipWithUniqueId().top(10)
6.12 多項詞查詢
1)構造查詢詞的稀疏向量
new BSparseVector[Double](indices,values,idTerms.size) //indices查詢詞的ID,values為查詢詞對應的逆文件頻率
2)得到查詢詞對應的行向量
val termRowArr=(breezeV.t*query).toArray
val termRowVec=Matrices.dense(termRowArr.length,1,termRowArr)
3)US點乘行向量得到查詢詞對應的文件得分
Val docScores=US.multiply(termRowVec)
4)取得查詢詞最相關的N個文件
docScores.rows.map(_.toArray(0)).zipWithUniqueId().top(10)
第七章 用GraphX分析伴生網路
Spark之上執行的GraphX並行圖計算框架,支援Pregel,Graph,GraphLab可分析使用者-商品購買關係圖,社交網路等
7.1對MEDLINE文獻引用索引的網路分析
基本思路:
1)研究資料集中的主要主題和它們的伴生關係
2)找到資料集中的連通元件
3)圖的度分佈,描述了主題的相關度變化並有助於找到那些與其他主題相關聯最多的主題
4)計算圖的統計量:聚類係數和平均路徑長度
7.2獲取資料
樣本問價那種的每條記錄是MedlineCitation型別的記錄,該記錄包括雜誌名稱、發行期號、發行日期、作者姓名、摘要、MeSH關鍵字集合
7.3用Scala XML工具解析XML文件
通過scala.xml工具能快速方便的解析XML檔案
7.4分析MeSH主要主題和伴生關係
高頻topic佔少數,低頻topic佔多數,因此呈現出長尾
7.5用GraphX來建立一個伴生網路
把伴生網路真正當做網路分析,主題作為圖的頂點,連線兩個主題的引用記錄看作圖的邊
VertexRDD[VD]是RDD[(VertexId,VD)]的特殊實現,VertexId為頂點標識,VD為頂點屬性;EdgeRDD[ED]是RDD[Edge[ED]]的特殊實現,每個Edge包含兩個VertexId和一個ED邊屬性
1)由於每個主題都是字串型,因此需要將其轉換成64位的Long型
2)利用Hashing雜湊演算法將每個topic->唯一的vertexId,即生成頂點
3)利用伴生頻率計數生成邊,保證左邊的vertexId(src)比右邊的vertexId(dst)小
4)準備好頂點和邊後便可以建立GraphX例項,GraphX可以自動完成頂點的去重,但不會進行邊去重,這樣Graph可以為我們生成多圖
7.6理解網路結構
判斷該圖是否連通圖,若不是連通圖,則可以進一步劃分成子圖研究其特性,GraphX內建了連通部件
val connectedComponentGraph[VertexId,Int]=topicGraph.connectedComponents()//VertexId是每個頂點所屬連通元件的唯一識別符號
7.7度分佈
注意點
1)degrees RDD中條目個數比概念圖中的頂點數少,這是由於部分頂點沒有連線邊,只有一個主題詞
2)度的均值很小,意味著大部分頂點只連線少數的其他節點,當然也存在度很高的頂點
7.8過濾噪聲邊