基於Spark的機器學習實踐 (八) - 分類算法

0 相關源碼

1 樸素貝葉斯算法及原理概述

1.1 樸素貝葉斯簡介

◆ 樸素貝葉斯算法是基於貝葉斯定理特徵條件獨立假設的一種分類方法html

◆ 樸素貝葉斯算法是一種基於聯合機率分佈的統計學習方法git

◆ 樸素貝葉斯算法實現簡單,效果良好,是一種經常使用的機器學習方法github

1.2 貝葉斯定理

◆ 樸素貝葉斯算法的一個基礎是貝葉斯定理算法

貝葉斯定理(英語:Bayes' theorem)是[機率論]中的一個[定理],描述在已知一些條件下,某事件的發生機率。 好比,若是已知某癌症與壽命有關,使用貝葉斯定理則能夠經過得知某人年齡,來更加準確地計算出他罹患癌症的機率。數據庫

一般,事件A在事件B已發生的條件下發生的機率,與事件B在事件A已發生的條件下發生的機率是不同的。 然而,這二者是有肯定的關係的,貝葉斯定理就是這種關係的陳述。 貝葉斯公式的一個用途,即經過已知的三個機率而推出第四個機率。貝葉斯定理跟[隨機變量]的[條件機率]以及[邊緣機率分佈]有關。apache

做爲一個廣泛的原理,貝葉斯定理對於全部機率的解釋是有效的。這必定理的主要應用爲[貝葉斯推斷],是[推論統計學]中的一種推斷法。這必定理名稱來自於[托馬斯·貝葉斯]。數組

1.2.1 陳述

貝葉斯定理是關於隨機事件A和B的條件機率的一則定理。 緩存

其中P(A|B)是指在事件B發生的狀況下事件A發生的機率。bash

在貝葉斯定理中,每一個名詞都有約定俗成的名稱:網絡

  • 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}")
複製代碼

這裏要詳解管道概念

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

參考

貝葉斯定理 使用 ML Pipeline 構建機器學習工做流

Spark機器學習實踐系列

X 聯繫我

圖片標題

Java交流Q羣

博客

知乎

Github

相關文章
相關標籤/搜索