From e56cef8078f471e6d48bf7d3154677a4cd041870 Mon Sep 17 00:00:00 2001 From: planet <985981442@qq.com> Date: Wed, 6 Nov 2019 17:17:39 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E6=9C=BA=E5=99=A8=E5=AD=A6=E4=B9=A0?= =?UTF-8?q?=E9=AA=A8=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chapter5/5.1Spark机器学习实战.md | 45 ++++++++++++++++++++++ chapter5/5Spark机器学习实战简介.md | 18 +++++++++ 2 files changed, 63 insertions(+) diff --git a/chapter5/5.1Spark机器学习实战.md b/chapter5/5.1Spark机器学习实战.md index e69de29..55b2d30 100644 --- a/chapter5/5.1Spark机器学习实战.md +++ b/chapter5/5.1Spark机器学习实战.md @@ -0,0 +1,45 @@ + +## 5.1 Spark机器学习实战 + + +### 5.1.1 数据类型 + +`MLlib`支持存储在一台机器上的局部向量和矩阵以及由一个或多个`RDD`支持的分布式矩阵。局部向量和局部矩阵是提供公共接口的简单数据模型。 + +### 5.1.1.1 局部向量 + +`MLlib`支持两种局部向量类型:密集向量(`dense`)和稀疏向量(`sparse`)。密集向量由`double`类型的数组支持,而稀疏向量则由两个平行数组支持。例如,向量`(1.0,0.0,3.0)`由密集向量表示的格式为`[1.0,0.0,3.0]`,由稀疏向量表示的格式为`(3,[0,2],[1.0,3.0])`。 + +注意:这里对稀疏向量做些解释。`3`是向量`(1.0,0.0,3.0)`的长度,除去`0`值外,其他两个值的索引和值分别构成了数组`[0,2]`和数组`[1.0,3.0]`。 + +**密集向量** + +示例: + +``` +from pyspark.ml.linalg import Vectors + +dense = Vectors.dense(1.0, 0.0, 3.0) +print(dense) +``` + +输出: +``` +[1.0,0.0,3.0] +``` + +**稀疏向量** + +示例: + +``` +from pyspark.ml.linalg import Vectors + +sparse = Vectors.sparse(3, [0, 2], [1.0, 3.0]) +print(sparse) +``` + +输出: +``` +(3,[0,2],[1.0,3.0]) +``` \ No newline at end of file diff --git a/chapter5/5Spark机器学习实战简介.md b/chapter5/5Spark机器学习实战简介.md index e69de29..e1cd91e 100644 --- a/chapter5/5Spark机器学习实战简介.md +++ b/chapter5/5Spark机器学习实战简介.md @@ -0,0 +1,18 @@ +# 第五章:Spark机器学习 + + +开始学习`spark`机器学习了,都知道`spark`是继`hadoop`后的大数据利器,很多人都在使用`spark`的分布式并行来处理大数据。`spark`中也提供了机器学习的包,就是`MLlib`。 + +`MLlib` 是 `Spark` 的机器学习(`ML`)库。其目标是使实用的机器学习可扩展且容易。在较高级别,它提供了以下工具: + +- `ML`算法:常见的学习算法,例如分类,回归,聚类和协作过滤; + +- 特征化:特征提取,变换,降维和选择; + +- 管道:用于构建,评估和调整`ML`管道的工具; + +- 持久性:保存和加载算法,模型和管道; + +- 实用程序:线性代数,统计信息,数据处理等。 + +接下来我们就进入`spark`机器学习的世界吧! From 48bce7cb08d56ac8a9b9d6656f81cb9006a09b7a Mon Sep 17 00:00:00 2001 From: planet <985981442@qq.com> Date: Wed, 6 Nov 2019 17:26:12 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SUMMARY.md | 3 ++- chapter5/5.1Spark机器学习入门.md | 0 ...park机器学习实战.md => 5.2Spark机器学习实战.md} | 0 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 chapter5/5.1Spark机器学习入门.md rename chapter5/{5.1Spark机器学习实战.md => 5.2Spark机器学习实战.md} (100%) diff --git a/SUMMARY.md b/SUMMARY.md index 55898c5..5277a22 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -18,7 +18,8 @@ * [第四章 Spark图数据计算与分析实战](/chapter4/4Spark图数据计算简介.md) * [4.1 SparkGraphX计算生成最短路径](/chapter4/4.1SparkGraphX计算生成最短路径.md) * [第五章 Spark机器学习实战](/chapter5/5Spark机器学习实战简介.md) - * [5.1 Spark机器学习](/chapter5/5.1Spark机器学习实战.md) + * [5.1 Spark机器学习](/chapter5/5.1Spark机器学习入门.md) + * [5.2 Spark机器学习](/chapter5/5.2Spark机器学习实战.md) diff --git a/chapter5/5.1Spark机器学习入门.md b/chapter5/5.1Spark机器学习入门.md new file mode 100644 index 0000000..e69de29 diff --git a/chapter5/5.1Spark机器学习实战.md b/chapter5/5.2Spark机器学习实战.md similarity index 100% rename from chapter5/5.1Spark机器学习实战.md rename to chapter5/5.2Spark机器学习实战.md From e5642ef96c0a3e157a18b1f589fc19003b8552d6 Mon Sep 17 00:00:00 2001 From: planet <985981442@qq.com> Date: Thu, 7 Nov 2019 10:44:00 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E6=9C=BA=E5=99=A8=E5=AD=A6=E4=B9=A0?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chapter5/5.1Spark机器学习入门.md | 52 ++++++ chapter5/5.2Spark机器学习实战.md | 201 +++++++++++++++++++-- chapter5/5Spark机器学习实战简介.md | 2 +- 3 files changed, 235 insertions(+), 20 deletions(-) diff --git a/chapter5/5.1Spark机器学习入门.md b/chapter5/5.1Spark机器学习入门.md index e69de29..b930464 100644 --- a/chapter5/5.1Spark机器学习入门.md +++ b/chapter5/5.1Spark机器学习入门.md @@ -0,0 +1,52 @@ +## 5.1 Spark 机器学习入门 + + +### 5.1.1 机器学习的定义 +在维基百科上对机器学习提出以下几种定义: + +- “机器学习是一门人工智能的科学,该领域的主要研究对象是人工智能,特别是如何在经验学习中改善具体算法的性能”。 + +- “机器学习是对能通过经验自动改进的计算机算法的研究”。 + +- “机器学习是用数据或以往的经验,以此优化计算机程序的性能标准。” + +可以看出机器学习强调三个关键词:算法、经验、性能,其处理过程如下图所示。 + +![](https://www.educoder.net/api/attachments/457570) + +上图表明机器学习是数据通过算法构建出模型并对模型进行评估,评估的性能如果达到要求就拿这个模型来测试其他的数据,如果达不到要求就要调整算法来重新建立模型,再次进行评估,如此循环往复,最终获得满意的经验来处理其他的数据。 + + +### 5.1.2 机器学习的基本任务 + +机器学习基于数据,并以此获取新知识、新技能。它的任务有很多,分类是其基本任务之一。 所谓分类,就是将新数据划分到合适的类别中,一般用于类别型的目标特征。如果目标特征为连续型,则往往采用回归方法。回归是对新目标特征进行预测 , 是机器学习中使用非常广泛的方法之一。 + +分类和回归,都是先根据标签值或目标值建立模型或规则,然后利用这些带有目标值 的数据形成的模型或规则 ,对新数据进行识别或预测。这两种方法都属于监督学习。与监督学习相对的 +是无监督学习,无监督学习不指定目标值或预先无法知道目标值,它可以把相似或相近的数据划分到相同的组里,聚类就是解决这一类问题的方法之一。 + +![](https://www.educoder.net/api/attachments/457573) + + + +### 5.1.3 如何选择合适的算法 + +当我们接到一个数据分析或挖掘的任务或需求时,如果希望用机器学习来处理,首先 要做的是根据任务或需求选择合适算法,选择算法一般步骤如下图所示: + +![](https://www.educoder.net/api/attachments/458857) + +充分了解数据及其特性,有助于我们更有效地选择机器学习算法。采用以上步骤在一定程度上可以缩小算法的选择范围,使我们少走些弯路,但在具体选择哪种算法方面,一般并不存在最好的算法或者可以给出最好结果的算法。在实际做项目的过程中,这个过程往往需要多次尝试,有时还要尝试不同算法。过先用一种简单熟悉的方法,然后,在这个基础上不断优化,时常能收获意想不到的效果。 + + +### 5.1.4 Spark 机器学习的步骤 + +关于机器学习,我们有一个几乎固定的“套路”,简单来分就四大步骤了。 + +1. 读取数据文件 + +2. 通过某种算法建立数据模型 + +3. 再用测试数据评估数据模型的准确性 + +4. 运行模型进行数据预测. + + diff --git a/chapter5/5.2Spark机器学习实战.md b/chapter5/5.2Spark机器学习实战.md index 55b2d30..2ec12c2 100644 --- a/chapter5/5.2Spark机器学习实战.md +++ b/chapter5/5.2Spark机器学习实战.md @@ -1,45 +1,208 @@ ## 5.1 Spark机器学习实战 +坦克图片识别分类 -### 5.1.1 数据类型 +### 5.1.1 数据集介绍 -`MLlib`支持存储在一台机器上的局部向量和矩阵以及由一个或多个`RDD`支持的分布式矩阵。局部向量和局部矩阵是提供公共接口的简单数据模型。 +三种坦克图片数据集,如下图所示: -### 5.1.1.1 局部向量 +![](https://www.educoder.net/api/attachments/458868) -`MLlib`支持两种局部向量类型:密集向量(`dense`)和稀疏向量(`sparse`)。密集向量由`double`类型的数组支持,而稀疏向量则由两个平行数组支持。例如,向量`(1.0,0.0,3.0)`由密集向量表示的格式为`[1.0,0.0,3.0]`,由稀疏向量表示的格式为`(3,[0,2],[1.0,3.0])`。 +![](https://www.educoder.net/api/attachments/458870) -注意:这里对稀疏向量做些解释。`3`是向量`(1.0,0.0,3.0)`的长度,除去`0`值外,其他两个值的索引和值分别构成了数组`[0,2]`和数组`[1.0,3.0]`。 +![](https://www.educoder.net/api/attachments/458871) -**密集向量** +以上有三种数据集,分别是以`bmp-2`开头的`BMP-2`步兵战车的图片、以`btr-70`开头的`BTR-70`装甲输送车的图片、以`t-72`开头的`T-72`主战坦克的图片。 + + +#### 5.1.2 数据集处理 + +##### 5.1.2.1 加载图片数据集 + + +我们可以使用`opencv_python`计算机视觉库来读取一幅图像。 + +在读取图像之前,我们需要对图像的构造有一定的理解,怎么理解呢? + +简单来说图像就是一个矩阵,在`OpenCV for Python`中,图像就是`NumPy`中的数组! + +我们知道图像就是一个矩阵了,之后我们通过代码来读取呢? + +示例: +``` +# 读入图像文件,返回numpy数组 +img = cv2.imread('/root/1.jpg', cv2.IMREAD_GRAYSCALE) +rows, columns = img.shape +# 将二维数组转一维数组 +img = img.reshape(rows*columns) +``` + + +##### 5.1.2.2 将一维数组转换成 Spark 中的向量 + +上一步我们将图片转换成一维的数组之后了,接下来我们将一维数组转换成 Spark 中的向量。 + +可能你会有疑问?为什么要将一维数组转换成 Spark 中的向量呢? + +简单来说就是类型不匹配了。 示例: ``` -from pyspark.ml.linalg import Vectors +import cv2 +img = cv2.imread("testing2\\bmp-2-1.jpg", cv2.IMREAD_GRAYSCALE) +rows, columns = img.shape +img = img.reshape(rows * columns) +print(type(img)) +``` -dense = Vectors.dense(1.0, 0.0, 3.0) -print(dense) +结果如下: +``` + ``` -输出: +我们都知道`numpy.ndarray`是`Python`中的类型,`Spark`是由`Scala`编写的,它怎么可能识别的了`numpy.ndarray`类型呢? + +那我们怎么将将一维数组转换成 Spark 中的向量呢? + +很简单,直接使用`from pyspark.ml.linalg import Vectors`中的`Vectors`来进行转换即可! + +在`pyspark`中,有两种向量,分别是稠密向量和稀疏向量。 + +`DenseVctor` :稠密向量 其创建方式 `Vector.dense(数据)` + +`SparseVector` :稀疏向量 其创建方式有两种: + +方法一:`Vector.sparse(向量长度,索引数组,与索引数组所对应的数值数组)` + +方法二:`Vector.sparse(向量长度,(索引,数值),(索引,数值),(索引,数值),...(索引,数值))` + +比如向量`(1,0,3,4)`的创建有三种方法: + +稠密向量:直接`Vectors.dense(1,0,3,4)` + +稀疏向量: + +方法一:`Vector.sparse(4,(0,2,3),(1,3,4))` + +表示该向量的第`0`个,第`2`个,第`3`个位置,`(1,3,4)` 表示`(0,2,3)`位置对应的数值分别为`1,3,4` + +方法二:`Vector.sparse(4,(0,1),(2,3),(3,4))` + +`(0,1)`就是`(索引,数值)`的形式。位置`0`的数值为`1`, 位置`2`的数值为`3`,位置`3`的数值为`4`。 + +一般我们会直接将数组转换成稠密向量。 + +##### 5.1.2.3 将向量与标签进行绑定并将其转换成Dataframe + +上面的两步,我们已经加载了图片数据并将其转换成`Spark`中的向量了,但是这样还远远不够,为什么呢? + +因为我将图片数据转换成向量之后,这样只能得出该图片的特征,但是我们还没有指定特征的标签。 + +我们回到最初加载图片数据那步,这里我们在读取图片数据的同时获取图片的文件名,我们通过文件名进行打标签,具体要求如下: + +- 如果文件名包含 `btr-70` ,`label` 设置为 `0` ; + +- 如果文件名包含 `t-72` ,`label` 设置为 `1`; + +- 其他的,`label` 设置为 `2`。 + +我们得到标签之后,我们将特征向量与该标签进行绑定,构建一个元组。 + +构建元组之后,我们使用`pandas`将元组数据加载成`Dataframe`并将特征向量列的列名设置为`features`,标签的列的列名设置为`label`。 + +为什么要这样做呢? + +我们查看下`LogisticRegression`算法的源码 + +构造函数源码如下: + ``` -[1.0,0.0,3.0] +@keyword_only + def __init__(self, featuresCol="features", labelCol="label", predictionCol="prediction", + maxIter=100, regParam=0.0, elasticNetParam=0.0, tol=1e-6, fitIntercept=True, + threshold=0.5, thresholds=None, probabilityCol="probability", + rawPredictionCol="rawPrediction", standardization=True, weightCol=None, + aggregationDepth=2, family="auto", + lowerBoundsOnCoefficients=None, upperBoundsOnCoefficients=None, + lowerBoundsOnIntercepts=None, upperBoundsOnIntercepts=None): + super(LogisticRegression, self).__init__() + self._java_obj = self._new_java_obj( + "org.apache.spark.ml.classification.LogisticRegression", self.uid) + self._setDefault(maxIter=100, regParam=0.0, tol=1E-6, threshold=0.5, family="auto") + kwargs = self._input_kwargs + self.setParams(**kwargs) + self._checkThresholdConsistency() ``` -**稀疏向量** +通过`__init__`函数中的参数,我们可以看到`featuresCol`的默认值为`features`,`labelCol`的默认值为`label`。 -示例: +通过`pandas`构建了 `Dataframe`之后指定了列名这样做的话,就可以不用设置`featuresCol`、`labelCol`了,同时增强了代码可读性。 + + +#### 5.1.3 Spark 加载数据集 + +上面我们已经把数据集处理完毕之后,然后我们可以通过`Spark`来加载数据集。 + +``` +spark = SparkSession.builder.master("local[*]").appName("demo").getOrCreate() +sparkDF = spark.createDataFrame(df) # df是我们通过pandas构建的Dataframe +``` + + +#### 5.1.4 将数据集拆分训练集和测试集 + +上面我们把图片数据集加载到`Spark`中了,之后我们要把数据集划分成两部分,一部分为训练集,另一部分为测试集。 + +简单来说,训练集就是用来训练模型的,测试集就是来评测这样模型的好与坏的。 + +关于训练集与测试集的比例问题,一般来说训练集越多越好,我们一般将训练集与测试集的比例调整为`8:2`或者`7:3`。 + +``` +train_df, test_df = sparkDF.randomSplit([0.7, 0.3]) +``` + + +#### 5.1.5 创建LR分类器 + +逻辑回归是一种用于预测分类响应的流行方法。这是广义线性模型的一种特殊情况,可以预测结果的可能性。在`spark.ml`逻辑回归中,可以通过使用二项式逻辑回归来预测二进制结果,或者在使用多项式逻辑回归时可以将其预测为多类结果。使用该`family` 参数在这两种算法之间进行选择,或者将其保留为未设置状态,`Spark`会推断出正确的变体。 + +- 通过将`family`参数设置为“多项式”,可以将多项式逻辑回归用于二进制分类。它将产生两组系数和两个截距。 + +- 当对具有恒定非零列的数据集进行`LogisticRegressionModel`拟合而没有截距时,`Spark MLlib`为恒定非零列输出零系数。 + + +创建`LR`分类器用来训练模型: ``` -from pyspark.ml.linalg import Vectors +lr = LogisticRegression(family="multinomial") +``` + +#### 5.1.6 训练模型 -sparse = Vectors.sparse(3, [0, 2], [1.0, 3.0]) -print(sparse) +上一步,我们已经把`LR`分类器构建好了并且我们把数据集划分成训练集与测试集了,接下来我们就是训练模型了。 + +``` +model = lr.fit(train_df) ``` -输出: +#### 5.1.7 评估模型 + +我们已经把模型训练好了,接下来就是评估模型了。 + ``` -(3,[0,2],[1.0,3.0]) -``` \ No newline at end of file +predict_df = model.transform(test_df) + +# 对测试集做predict, 生成(预测分类, 正确分类) +def build_predict_target(row): + return (float(row.prediction), float(row.label)) + +predict_and_target_rdd = predict_df.rdd.map(build_predict_target) + +# 统计模型效果 +metrics = BinaryClassificationMetrics(predict_and_target_rdd) +print(metrics.areaUnderROC) +``` + +以上代码就是统计模型效果了,由于我们使用的是逻辑回归,我们只要获取`AUC`的值了,`AUC`越大,模型的准确度越高。 \ No newline at end of file diff --git a/chapter5/5Spark机器学习实战简介.md b/chapter5/5Spark机器学习实战简介.md index e1cd91e..e336246 100644 --- a/chapter5/5Spark机器学习实战简介.md +++ b/chapter5/5Spark机器学习实战简介.md @@ -15,4 +15,4 @@ - 实用程序:线性代数,统计信息,数据处理等。 -接下来我们就进入`spark`机器学习的世界吧! +接下来我们就进入`spark`机器学习的世界吧! \ No newline at end of file From e7b623a82517cdbd17af1ee18401327c3bd355c6 Mon Sep 17 00:00:00 2001 From: planet <985981442@qq.com> Date: Thu, 7 Nov 2019 10:47:41 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SUMMARY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SUMMARY.md b/SUMMARY.md index 0b8997d..4e14e22 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -18,8 +18,8 @@ * [第四章 Spark图数据计算与分析实战](/chapter4/4Spark图数据计算简介.md) * [4.1 SparkGraphX计算生成最短路径](/chapter4/4.1SparkGraphX计算生成最短路径.md) * [第五章 Spark机器学习实战](/chapter5/5Spark机器学习实战简介.md) - * [5.1 Spark机器学习](/chapter5/5.1Spark机器学习入门.md) - * [5.2 Spark机器学习](/chapter5/5.2Spark机器学习实战.md) + * [5.1 Spark机器学习入门](/chapter5/5.1Spark机器学习入门.md) + * [5.2 Spark机器学习实战](/chapter5/5.2Spark机器学习实战.md) From 90c55c4ea071c15800921a9ff8a89713fb967f35 Mon Sep 17 00:00:00 2001 From: xlc <631948983#qq.com> Date: Thu, 7 Nov 2019 11:03:42 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=AC=AC=E4=B8=80?= =?UTF-8?q?=E7=AB=A0=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chapter1/1.2Spark单机版环境搭建.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/chapter1/1.2Spark单机版环境搭建.md b/chapter1/1.2Spark单机版环境搭建.md index c64405a..19754c6 100644 --- a/chapter1/1.2Spark单机版环境搭建.md +++ b/chapter1/1.2Spark单机版环境搭建.md @@ -22,7 +22,7 @@ 接下来解压,在平台已经将`spark`安装包下载到`/opt`目录下了,所以不需要再下载了。 ``` -tar -zxvf spark-2.2.2-bin-hadoop2.7/ -C /app +tar -zxvf spark-2.2.2-bin-hadoop2.7.tgz -C /app ``` 将压缩包解压到`/app`目录下。 @@ -64,13 +64,9 @@ export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_111 export SCALA_HOME=/app/scala-2.12.7 -export HADOOP_HOME=/usr/local/hadoop/ +export SPARK_MASTER_IP=machine_name # machine_name 根据自己的主机确定 -export HADOOP_CONF_DIR=/usr/local/hadoop/etc/hadoop - -export SPARK_MASTER_IP=machine_name // machine_name 根据自己的主机确定 - -export SPARK_LOCAL_IP=machine_name // machine_name 根据自己的主机确定 +export SPARK_LOCAL_IP=machine_name # machine_name 根据自己的主机确定 ``` @@ -80,8 +76,6 @@ export SPARK_LOCAL_IP=machine_name // machine_name 根据自己的主机确 | - | - | | JAVA_HOME | Java的安装路径 | |SCALA_HOME|Scala的安装路径| -| HADOOP_HOME| Hadoop的安装路径 | -| HADOOP_CONF_DIR| Hadoop配置文件的路径| | SPARK_MASTER_IP | Spark主节点的IP或机器名| | SPARK_LOCAL_IP | Spark本地的IP或主机名 | @@ -111,4 +105,4 @@ export SPARK_LOCAL_IP=machine_name // machine_name 根据自己的主机确

-好了,如果你能到这一步就已经完成了伪分布式`Spark`的安装啦。 \ No newline at end of file +好了,如果你能到这一步就已经完成了单机版`Spark`的安装啦。 \ No newline at end of file