相關源碼
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
應屬于哪一類呢?
[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}")
這裡要詳解管道概念
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)
6.1.1.1 DataFrame
-
此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
6.1.1.2 Transformer
-
Transformer是一種可以将一個DataFrame轉換為另一個DataFrame的算法.
例如,ML模型是變換器,其将具有特征的DataFrame轉換為具有預測的DataFrame.
Transformer 中文可以被翻譯成轉換器,是一個 PipelineStage,實作上也是繼承自 PipelineStage 類
主要是用來把 一個 DataFrame 轉換成另一個 DataFrame,比如一個模型就是一個 Transformer,因為它可以把 一個不包含預測标簽的測試資料集 DataFrame 打上标簽轉化成另一個包含預測标簽的 DataFrame,顯然這樣的結果集可以被用來做分析結果的可視化.
6.1.1.3 Estimator
-
Estimator是一種算法,可以适應DataFrame以生成Transformer.
例如,學習算法是Estimator,其在DataFrame上訓練并産生模型。
Estimator 中文可以被翻譯成評估器或擴充卡,在 Pipeline 裡通常是被用來操作 DataFrame 資料并生産一個 Transformer,如一個随機森林算法就是一個 Estimator,因為它可以通過訓練特征資料而得到一個随機森林模型。實作上 Estimator 也是繼承自 PipelineStage 類
6.1.1.4 Parameter
Parameter 被用來設定 Transformer 或者 Estimator 的參數。
要建構一個 Pipeline,首先我們需要定義 Pipeline 中的各個 PipelineStage,如名額提取和轉換模型訓練等。有了這些處理特定問題的 Transformer 和 Estimator,我們就可以按照具體的處理邏輯來有序的組織 PipelineStages 并建立一個 Pipeline,如 val pipeline = new Pipeline().setStages(Array(stage1,stage2,stage3,…))。然後就可以把訓練資料集作為入參并調用 Pipelin 執行個體的 fit 方法來開始以流的方式來處理源訓練資料,這個調用會傳回一個 PipelineModel 類執行個體,進而被用來預測測試資料的标簽,它是一個 Transformer。
6.1.1.5 Pipeline
管道:管道将多個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
- 分布式身高 - 體重散點圖
- 複制資料得到女生資料集
- 複制資料得到男生資料集
- 預測結果