基于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

相关文章
相关标签/搜索