基于Spark的機器學習實踐 (八) - 分類算法
0 相關源碼
1 樸素貝葉斯算法及原理概述
1.1 樸素貝葉斯簡介
◆ 樸素貝葉斯算法是基于貝葉斯定理和特征條件獨立假設的一種分類方法
◆ 樸素貝葉斯算法是一種基于聯合概率分布的統計學習方法
◆ 樸素貝葉斯算法實現簡單,效果良好,是一種常用的機器學習方法
1.2 貝葉斯定理
◆ 樸素貝葉斯算法的一個基礎是貝葉斯定理
貝葉斯定理(英語:Bayes’ theorem)是[概率論]中的一個[定理],描述在已知一些條件下,某事件的發生概率。
比如,如果已知某癌癥與壽命有關,使用貝葉斯定理則可以通過得知某人年齡,來更加準確地計算出他罹患癌癥的概率。
通常,事件A在事件B已發生的條件下發生的概率,與事件B在事件A已發生的條件下發生的概率是不一樣的。
然而,這兩者是有確定的關系的,貝葉斯定理就是這種關系的陳述。
貝葉斯公式的一個用途,即通過已知的三個概率而推出第四個概率。貝葉斯定理跟[隨機變量]的[條件概率]以及[邊緣概率分布]有關。
作為一個普遍的原理,貝葉斯定理對于所有概率的解釋是有效的。這一定理的主要應用為[貝葉斯推斷],是[推論統計學]中的一種推斷法。這一定理名稱來自于[托馬斯·貝葉斯]。
1.2.1 陳述
貝葉斯定理是關于隨機事件A和B的條件概率的一則定理。
其中P(A|B)是指在事件B發生的情況下事件A發生的概率。
在貝葉斯定理中,每個名詞都有約定俗成的名稱:
P(A|B)是已知B發生后A的條件概率,也由于得自B的取值而被稱作A的后驗概率。
P(A)是A的先驗概率(或邊緣概率)。之所以稱為"先驗"是因為它不考慮任何B方面的因素。
P(B|A)是已知A發生后B的條件概率,也由于得自A的取值而被稱作B的后驗概率。
P(B)是B的先驗概率或邊緣概率。
按這些術語,貝葉斯定理可表述為:
后驗概率 = (似然性*先驗概率)/標準化常量
也就是說,后驗概率與先驗概率和相似度的乘積成正比。
另外,比例P(B|A)/P(B)也有時被稱作標準似然度(standardised likelihood),貝葉斯定理可表述為:
后驗概率 = 標準似然度*先驗概率
1.2.2 二中擇一的形式
貝氏定理通常可以再寫成下面的形式
其中AC是A的補集(即非A)。故上式亦可寫成:
在更一般化的情況,假設{Ai}是事件集合里的部分集合,對于任意的Ai,貝氏定理可用下式表示:
1.3 樸素貝葉斯算法
◆ 樸素葉斯算法的基本假設是條件獨立性,這是一一個較強的前提條件,因而樸素貝葉斯算法易于實現,但是分類性能可能不會很高
◆ 樸素貝葉斯算法要求輸入變量是條件獨立的,但是如果它們之間存在概率依存關系,就超出該算法范疇,屬于貝葉斯網絡
◆ 首先計算先驗概率及條件概率
其中
代表第j個特征可能取第I個值
◆ 對于每一個給定的特征向量X ,在不同類別中出現的概率為
◆ 那么,最終預測結果y自然是其中概率最大的那個:
1.4 樸素貝葉斯算法示例
那么某個特征[1,B]T應屬于哪一類呢?
2 實戰樸素貝葉斯分類
官方文檔指南
樸素貝葉斯分類器是一類簡單的概率多類分類器,它基于應用貝葉斯定理,在每對特征之間具有強(天真)獨立假設。
樸素貝葉斯可以非常有效地訓練。通過對訓練數據的單次傳遞,它計算給定每個標簽的每個特征的條件概率分布。
對于預測,它應用貝葉斯定理來計算給定觀察的每個標簽的條件概率分布。
MLlib支持多項式樸素貝葉斯和伯努利樸素貝葉斯。
輸入數據:這些模型通常用于文檔分類。在該上下文中,每個觀察是一個文檔,每個特征代表一個術語。特征值是術語的頻率(在多項式樸素貝葉斯中)或零或一個,表示該術語是否在文檔中找到(在伯努利樸素貝葉斯中)。要素值必須為非負值。使用可選參數“multinomial”或“bernoulli”選擇模型類型,默認為“multinomial”。對于文檔分類,輸入特征向量通常應該是稀疏向量。由于訓練數據僅使用一次,因此不必對其進行緩存。
通過設置參數λ(默認為1.0)可以使用加法平滑。
file.show
打亂順序 - data.show
在特征標簽形成vector數組
訓練集預測
都是正確的,完美預測!
[分類數據]是[機器學習]中的一項常見任務。
假設某些給定的數據點各自屬于兩個類之一,而目標是確定新數據點將在哪個類中。
對于支持向量機來說,數據點被視為
維向量,而我們想知道是否可以用
維[超平面]來分開這些點。這就是所謂的[線性分類器]。
可能有許多超平面可以把數據分類。最佳超平面的一個合理選擇是以最大間隔把兩個類分開的超平面。因此,我們要選擇能夠讓到每邊最近的數據點的距離最大化的超平面。如果存在這樣的超平面,則稱為最大間隔超平面,而其定義的線性分類器被稱為最大[間隔分類器],或者叫做最佳穩定性[感知器]
3 支持向量機算法
3.1 簡介
◆ 支持向量機(SVM)是一種用來分類的算法,當然,在這基礎上進行改進,也可以進行回歸分析(SVR)
◆ SVM是最優秀的分類算法之一,即便是在如今深度學習盛行的時代,仍然具有很廣泛的應用
◆ SVM被設計成一種二分類的算法, 當然,也有人提出了使用SVM進行多分類的方法,但是SVM依然主要被用在二分類中
在[機器學習]中,支持向量機(英語:support vector machine,常簡稱為SVM,又名支持向量網絡)是在[分類]與[回歸分析]中分析數據的監督式學習模型與相關的學習算法。
給定一組訓練實例,每個訓練實例被標記為屬于兩個類別中的一個或另一個,SVM訓練算法創建一個將新的實例分配給兩個類別之一的模型,使其成為非概率[二元][線性分類器]。
SVM模型是將實例表示為空間中的點,這樣映射就使得單獨類別的實例被盡可能寬的明顯的間隔分開。然后,將新的實例映射到同一空間,并基于它們落在間隔的哪一側來預測所屬類別。
除了進行線性分類之外,SVM還可以使用所謂的[核技巧]有效地進行非線性分類,將其輸入隱式映射到高維特征空間中。
當數據未被標記時,不能進行監督式學習,需要用[非監督式學習],它會嘗試找出數據到簇的自然聚類,并將新數據映射到這些已形成的簇。將支持向量機改進的聚類算法被稱為支持向量聚類,當數據未被標記或者僅一些數據被標記時,支持向量聚類經常在工業應用中用作分類步驟的預處理。
H1 不能把類別分開。H2 可以,但只有很小的間隔。H3 以最大間隔將它們分開。
3.2 簡單的分類
◆ 可能大家認為最簡單的一種分類方法大概就是劃分"閾值"了
◆ 例如判斷一一個人是否是禿頭:頭頂區域頭發數量小于100根則是禿頭
◆ 而SVM也是遵循這個道理,只不過它的"閾值”尋找過程更復雜,也更科學
3.3 SVM的基本思想
◆ SVM的主要思想是尋找能夠將數據進行分類的平面或超平面,在平面上的則是A類,在平面下的則是B類, 因此,SVM是一種二分類算法
◆ 因此,這個“閾值”更貼切地說應該稱為“邊界”, 而這個"邊界"恰恰就是通過向量來表示的,故而這個"邊界"我們就稱為支持向量
3.4 SVM處理非線性問題
◆ 在很多情況下,數據集并不是線性可分的,譬如:
3.5 SVM的核函數
◆ SVM雖然只能進行線性分類, 但是,可以通過引入核函數,將非線性的數據,轉化為另一個空間中的線性可分數據,這叫做支持向量機的核技巧,可以認為是支持向量機的精髓之一
##3.6 SVM的類別
◆ 基于硬間隔最大化的線性可分 支持向量機
◆ 基于軟間隔最大化的線性支持向量機
◆ 使用核函數的非線性支持向量機
3.7 線性支持向量機的數學原理
4 實戰SVM分類
官方文檔指南
支持向量機在高維或無限維空間中構造超平面或超平面集,其可用于分類,回歸或其他任務。 直觀地,通過與任何類的最近的訓練數據點具有最大距離的超平面(所謂的功能邊界)實現良好的分離,因為通常邊緣越大,分類器的泛化誤差越低。
Spark ML中的LinearSVC支持使用線性SVM進行二進制分類。 在內部,它使用OWLQN優化器優化鉸鏈損耗
代碼
iris數據集特征三列,所以報錯
只是用2列
計算結果
5 決策樹算法
5.1 決策樹介紹
◆ 決策樹因其進行決策判斷的結構與數據結構中的樹相同,故而得名
◆ 決策樹算法既可以實現分類,也可以實現回歸, 一-般用作分類的比較多
例如if-then就是一種簡單的決策樹
◆ 決策樹的解法有很多
例如ID3,C4.5等,其使用了信息論中熵的概念
5.2 決策樹的缺點
◆ 對輸入特征要求較高,很多情況下需要作預處理
◆ 識別類別過多時,發生錯誤的概率較大
5.3 決策樹示例
◆ 如圖展示了一個能否批準貸款的決策樹
5.4 決策樹的特征選擇
◆ 輸入變量的特征有很多,選擇特征作為分類判斷的依據之一便是能夠具有很好的區分度
◆ 那么也就是說,選擇出的變量能夠更具有代表性,以至于區分程度更高,作為決策樹的判斷節點
##5.5 信息增益
◆ 定義隨機變量X的信息熵
◆ 已知隨機變量X ,對于變量Y的不確定性,使用條件熵來衡量
◆ 當得知X而使得Y的不確定性減少的程度即為信息增益
5.6 決策樹生成 - ID3算法
◆ ID3算法是一種決策樹生成算法,其對于決策樹各個節點應用信息增益準則從而選取特征,在樹的每一層進行遞歸,從而構建整棵樹
◆ 從根節點開始 ,在每層選擇信息增益最大的作為該節點的判斷特征
◆ 對所有節點進行相同操作,直到沒有特征選擇或者所有特征的信息增益均很小為止
5.7 決策樹的剪枝
◆ 決策樹是針對訓練集進行遞歸生成的,這樣對于訓練集效果自然非常好,但是對未知數據的預測結果可能并不會很好
◆ 即使用決策樹生成算法生成的決策樹模型過于復雜,對未知數據的泛化能力下降,即出現了過擬合現象
◆ 過擬合是因為樹的結構過于復雜,將樹的結構精簡,就能夠減輕過擬合現象,即決策樹的剪枝
◆ 決策樹從葉節點開始遞歸地向根節點剪枝
◆ 判斷一個節點能否被減掉,只需比較修剪后與修剪前的損失函數值大小即可
◆ 如果在修剪之后,損失函數值小于等于原先的損失函數值,則將該父節點變為新的葉節點即可
##5.8 CART算法
◆ CART即分類與回歸決策樹,其實是一棵二叉樹,根據判斷結果劃分為”是否”二分類
◆ 決策樹生成
基于訓練集生成 一個盡可能大的決策樹
◆ 決策樹剪枝
使用驗證集對生成的決策樹進行剪枝,以便使損失函數最小化
6 實戰基于決策樹的分類–案例1
官方文檔指南
決策樹是一種流行的分類和回歸方法。有關spark.ml實現的更多信息可以在決策樹的部分中找到。
示例
以下示例以LibSVM格式加載數據集,將其拆分為訓練和測試集,在第一個數據集上訓練,然后評估保持測試集。我們使用兩個特征變換器來準備數據;這些幫助標記和分類特征的索引類別,向決策樹算法可識別的DataFrame添加元數據。
import org.apache.spark.ml.Pipeline import org.apache.spark.ml.classification.DecisionTreeClassificationModel import org.apache.spark.ml.classification.DecisionTreeClassifier import org.apache.spark.ml.evaluation.MulticlassClassificationEvaluator import org.apache.spark.ml.feature.{IndexToString, StringIndexer, VectorIndexer} // Load the data stored in LIBSVM format as a DataFrame. val data = spark.read.format("libsvm").load("data/mllib/sample_libsvm_data.txt") // Index labels, adding metadata to the label column. // Fit on whole dataset to include all labels in index. val labelIndexer = new StringIndexer() .setInputCol("label") .setOutputCol("indexedLabel") .fit(data) // Automatically identify categorical features, and index them. val featureIndexer = new VectorIndexer() .setInputCol("features") .setOutputCol("indexedFeatures") .setMaxCategories(4) // features with > 4 distinct values are treated as continuous. .fit(data) // Split the data into training and test sets (30% held out for testing). val Array(trainingData, testData) = data.randomSplit(Array(0.7, 0.3)) // Train a DecisionTree model. val dt = new DecisionTreeClassifier() .setLabelCol("indexedLabel") .setFeaturesCol("indexedFeatures") // Convert indexed labels back to original labels. val labelConverter = new IndexToString() .setInputCol("prediction") .setOutputCol("predictedLabel") .setLabels(labelIndexer.labels) // Chain indexers and tree in a Pipeline. val pipeline = new Pipeline() .setStages(Array(labelIndexer, featureIndexer, dt, labelConverter)) // Train model. This also runs the indexers. val model = pipeline.fit(trainingData) // Make predictions. val predictions = model.transform(testData) // Select example rows to display. predictions.select("predictedLabel", "label", "features").show(5) // Select (prediction, true label) and compute test error. val evaluator = new MulticlassClassificationEvaluator() .setLabelCol("indexedLabel") .setPredictionCol("prediction") .setMetricName("accuracy") val accuracy = evaluator.evaluate(predictions) println(s"Test Error = ${(1.0 - accuracy)}") val treeModel = model.stages(2).asInstanceOf[DecisionTreeClassificationModel] println(s"Learned classification tree model:\n ${treeModel.toDebugString}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
這里要詳解管道概念
6.1 ML Pipeline
Spark ML Pipeline 的出現,是受到了?scikit-learn?項目的啟發,并且總結了 MLlib 在處理復雜機器學習問題上的弊端,旨在向用戶提供基于 DataFrame 之上的更加高層次的 API 庫,以更加方便的構建復雜的機器學習工作流式應用。一個 Pipeline 在結構上會包含一個或多個 PipelineStage,每一個 PipelineStage 都會完成一個任務,如數據集處理轉化,模型訓練,參數設置或數據預測等,這樣的 PipelineStage 在 ML 里按照處理問題類型的不同都有相應的定義和實現。接下來,我們先來了解幾個重要概念。
在本節中,我們將介紹ML管道的概念。 ML Pipelines提供了一組基于DataFrame構建的統一的高級API,可幫助用戶創建和調整實用的機器學習流程。
6.1.1 主要概念(Main concepts in Pipelines)
此ML API使用Spark SQL中的DataFrame作為ML數據集,它可以包含各種數據類型.
例如,DataFrame可以具有存儲文本,特征向量,真實標簽和預測的不同列.
它較之 RDD,包含了 schema 信息,更類似傳統數據庫中的二維表格。它被 ML Pipeline 用來存儲源數據。
DataFrame 可以被用來保存各種類型的數據,如我們可以把特征向量存儲在 DataFrame 的一列中,這樣用起來是非常方便的。
機器學習可以應用于各種數據類型,例如矢量,文本,圖像和結構化數據。 此API采用Spark SQL的DataFrame以支持各種數據類型。
DataFrame支持許多基本和結構化類型, 除了Spark SQL指南中列出的類型之外,DataFrame還可以使用ML Vector類型。
可以從常規RDD隱式或顯式創建DataFrame
Transformer是一種可以將一個DataFrame轉換為另一個DataFrame的算法.
例如,ML模型是變換器,其將具有特征的DataFrame轉換為具有預測的DataFrame.
Transformer 中文可以被翻譯成轉換器,是一個 PipelineStage,實現上也是繼承自 PipelineStage 類
主要是用來把 一個 DataFrame 轉換成另一個 DataFrame,比如一個模型就是一個 Transformer,因為它可以把 一個不包含預測標簽的測試數據集 DataFrame 打上標簽轉化成另一個包含預測標簽的 DataFrame,顯然這樣的結果集可以被用來做分析結果的可視化.
Estimator是一種算法,可以適應DataFrame以生成Transformer.
例如,學習算法是Estimator,其在DataFrame上訓練并產生模型。
Estimator 中文可以被翻譯成評估器或適配器,在 Pipeline 里通常是被用來操作 DataFrame 數據并生產一個 Transformer,如一個隨機森林算法就是一個 Estimator,因為它可以通過訓練特征數據而得到一個隨機森林模型。實現上 Estimator 也是繼承自 PipelineStage 類
Parameter 被用來設置 Transformer 或者 Estimator 的參數。
要構建一個 Pipeline,首先我們需要定義 Pipeline 中的各個 PipelineStage,如指標提取和轉換模型訓練等。有了這些處理特定問題的 Transformer 和 Estimator,我們就可以按照具體的處理邏輯來有序的組織 PipelineStages 并創建一個 Pipeline,如 val pipeline = new Pipeline().setStages(Array(stage1,stage2,stage3,…))。然后就可以把訓練數據集作為入參并調用 Pipelin 實例的 fit 方法來開始以流的方式來處理源訓練數據,這個調用會返回一個 PipelineModel 類實例,進而被用來預測測試數據的標簽,它是一個 Transformer。
管道:管道將多個Transformers和Estimators鏈接在一起以指定ML工作流程。
6.1.2 How It Works
管道被指定為階段序列,并且每個階段是變換器或估計器。 這些階段按順序運行,輸入DataFrame在通過每個階段時進行轉換。 對于Transformer階段,在DataFrame上調用transform()方法。 對于Estimator階段,調用fit()方法以生成Transformer(它成為PipelineModel或擬合管道的一部分),并在DataFrame上調用Transformer的transform()方法。
我們為簡單的文本文檔工作流說明了這一點。 下圖是管道的培訓時間使用情況。
上圖中,頂行表示具有三個階段的管道。前兩個(Tokenizer和HashingTF)是變形金剛(藍色),第三個(LogisticRegression)是Estimator(紅色)。底行表示流經管道的數據,其中柱面表示DataFrame。在原始DataFrame上調用Pipeline.fit()方法,該原始DataFrame具有原始文本文檔和標簽。 Tokenizer.transform()方法將原始文本文檔拆分為單詞,向DataFrame添加一個帶有單詞的新列。 HashingTF.transform()方法將單詞列轉換為要素向量,將包含這些向量的新列添加到DataFrame。現在,由于LogisticRegression是一個Estimator,因此Pipeline首先調用LogisticRegression.fit()來生成LogisticRegressionModel。如果Pipeline有更多的Estimators,它會在將DataFrame傳遞給下一個階段之前在DataFrame上調用LogisticRegressionModel的transform()方法。
管道是估算器。因此,在Pipeline的fit()方法運行之后,它會生成一個PipelineModel,它是一個Transformer。這個PipelineModel在測試時使用;下圖說明了這種用法。
在上圖中,PipelineModel具有與原始Pipeline相同的階段數,但原始Pipeline中的所有Estimators都變為Transformers。 當在測試數據集上調用PipelineModel的transform()方法時,數據將按順序通過擬合的管道傳遞。 每個階段的transform()方法都會更新數據集并將其傳遞給下一個階段。
Pipelines和PipelineModel有助于確保培訓和測試數據經過相同的功能處理步驟。
代碼
結果
7 實戰基于決策樹的分類–案例2
分布式身高 - 體重散點圖
復制數據得到女生數據集
復制數據得到男生數據集
代碼
預測結果
參考
貝葉斯定理
使用 ML Pipeline 構建機器學習工作流
Spark機器學習實踐系列
基于Spark的機器學習實踐 (一) - 初識機器學習
基于Spark的機器學習實踐 (二) - 初識MLlib
基于Spark的機器學習實踐 (三) - 實戰環境搭建
基于Spark的機器學習實踐 (四) - 數據可視化
基于Spark的機器學習實踐 (六) - 基礎統計模塊
基于Spark的機器學習實踐 (七) - 回歸算法
基于Spark的機器學習實踐 (八) - 分類算法
X 聯系我
Java交流Q群
博客
知乎
Github
spark 機器學習
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。