相关概念

  • 机器学习(Machine Learning,简写为ML)机器学习是研究如何使计算机能够模拟或实现人类的学习功能,从大量的数据中发现规律,提取知识,并在实践中不断地完善和增强自我。机器学习是机器获取知识的根本途径,只有让计算机系统具有类似人的学习能力,才可能实现人工智能的终极目标
  • 深度学习(DL,Deep Learning)是机器学习领域中的一个研究方向,它被引入机器学习使其更接近于最初的目标——人工智能(AI,Artificial Intelligence)。
  • 人工神经网络(Artificial Neural Networks,简写为ANNs)也简称为神经网络(NNs)或称作连接模型(Connection Model),它是一种模仿动物神经网络行为特征,进行分布式并行信息处理的算法数学模型。

应用场景

  • 数据挖掘:从数据中提取信息和价值
  • NLP 自然语言处理 naturel language processing
  • CV computer vision 计算机视觉 人脸识别/自动驾驶

机器学习模型 = 数据 + 机器学习算法

机器学习的分类

img

监督学习

监督学习指的是人们给机器标记好的数据,有特征值和目标值比如:

  1. 一大堆照片,标记出哪些是猫的照片,哪些是狗的照片
  2. 让机器自己学习归纳出算法或模型
  3. 使用该算法或模型判断出其他没有标记的照片是否是猫或狗

监督学习典型模型:Linear regression、Logistic regression、SVM、Neural Network等

分类问题

分类是监督学习的一个核心问题

在监督学习中:

  • 当输出变量Y取有限个离散值时,预测问题便成了分类问题
  • 监督学习从数据中学习一个分类模型或分类决策函数,称为分类器(classifer)
  • 分类器对新的输入进行输出的预测(prediction),称为分类(classification)

分类问题包括学习和分类的两个过程:

  • 在学习过程中,根据已知的训练数据集利用有效的学习方法学习一个分类器
  • 在分类的过程中,利用学习的分类器对新的输入实例进行分类。

分类问题的典型应用场景如垃圾邮件识别就是一个2分类问题,使用相应的机器学习算法判定邮件属于垃圾邮件还是非垃圾邮件。如下图所示:

  • 给出了30个训练样本集实例:15个样本为负类别(negative class,圆圈表示),15个样本为正类别(positive class,加号表示)a5x5 = a1x1 + a2x2 + a3x3 + a4x4 + b
  • 数据集是二维的,这意味着每个样本都有两个与其相关的值
  • 通过监督学习算法获得一条规则,并将其表示为图中的一条黑色的虚线将两类样本分开,并且可以根据 值将新样本划分到某个类别中(看位于直线的那一侧)。

img

回归问题

另一类监督学习方法针对连续型输出变量进行预测,也就是所谓的回归分析(regression analysis)。回归分析中,数据中会给出大量的自变量和相应的连续因变量(对应输出结果),通过尝试寻找自变量和因变量的关系,就能够预测输出变量。

比如生活中常见的房价问题:

  • 横轴代表房屋面积,纵轴代表房屋的售价
  • 我们可以画出图示中的数据点,再根据使得各点到直线的距离的平均平方距离的最小,从而绘制出下图的拟合直线
  • 根据生活常识随着房屋面积的增加,房价也会增长

img

回归问题的分类有:

  • 根据输入变量的个数分为一元回归和多元回归
  • 按照输入变量和输出变量之间的关系分为线性回归和非线性回归

无监督学习

通俗地讲:非监督学习(unsupervised learning)指的是人们给机器一大堆没有分类标记的数据,让机器可以对数据分类、检测异常等。

聚类问题

聚类是一种探索性数据分析技术,在没有任何相关先验信息的情况下(相当于不清楚数据的信息),它可以帮助我们将数据划分为有意义的小的组别(也叫簇cluster)。其中每个簇内部成员之间有一定的相似度,簇之间有较大的不同。这也正是聚类作为无监督学习的原因。

聚类和分类的区别

  • 分类:监督学习的算法,分类问题在模型训练之前, 能分成几类已经确定了, 答案就在目标值中
  • 聚类 :无监督学习的算法 ,聚类之前,数据划分成几个类别比较合适, 如何进行类别划分都是未知的

聚类的应用场景

  • 在对业务不是很属性的情况下, 使用聚类可以帮助打开思路
  • 使用聚类算法做聚类分析 是分析过程的开头, 得到聚类结果之后, 再详细的分析每个类别各自的特点

机器学习步骤

  • 加载数据
    • 数据ETL
    • 确定特征列-DataFrame中的列
    • 特征值-列值
    • 目标列-预测值
  • 特征工程
    • 特征筛选-筛选哪些列作为特殊列参与模型训练
    • 特征转换-特征列值必须转化数值
    • 特征缩放-统一数值的量纲
  • 模型训练
    • 聚类-KMeans
    • 分类-决策树
  • 模型评估
    • 无监督学习-聚类算法
    • 有监督学习:训练集和测试集(8:2,7:3)
      • 分类:用测试集的预测结果/测试集已知的目标值=准确度
      • 回归:求测试集预测结果与目标值标准差:方差开根号
  • 模型上线
    • 保存模型=算法+数据
    • 一般保存在HDFS

加载数据 -> 特征工程(特征选择、特征转换、特征缩放)->模型训练(根据选择的机器学习算法训练模型model)->模型评估->模型上线

Spark MLlib

MLlib | Apache Spark

spark mllib spark2.0之前维护的,其中有rdd和df的API

spark ml spark2.0之后维护,官网建议使用其中只能df的API

MLLIB是Spark的机器学习库。提供了利用Spark构建大规模和易用性的机器学习平台,组件:

(1) ML 算法:包括了分类、回归、聚类、降维、协同过滤

(2) Featurization特征化:特征抽取、特征转换、特征降维、特征选择

(3) Pipelines管道:tools for constructing, evaluating, and tuning ML Pipelines

(4) Persistence持久化:模型的保存、读取、管道操作

(5) Utilities:提供了线性代数、统计学以及数据处理工具

注意:需要先安装numpy模块

1
2
3
4
5
# 先切换到你使用虚拟环境
conda env list
conda activate pyspark_env
# 下载numpy插件, 选择清华源
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple

StringIndexer/IndexerToString

StringIndexer将标签的字符串列编码为标签索引列。索引[0, numLabels]按标签频率排序,因此最常用的标签获得索引0。如果输入列是数字,我们将其转换为字符串并索引字符串值。

  • 作用: 字符串类型的列转换成数值类型
  • 场景: 模型训练的时候, 特征值和目标值都要是数值类型的, 我们可以使用StringIndex来把字符串类型的列转换数值类型
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
from pyspark.ml.feature import StringIndexer, IndexToString
from pyspark.sql import SparkSession

if __name__ == '__main__':
# 创建Spark运行环境
spark = SparkSession\
.builder\
.appName('stringIndexer.test')\
.master('local[*]')\
.getOrCreate()
# 创建测试数据
df = spark.createDataFrame([(0, "a"), (1, "b"), (2, "c"), (3, "a"), (4, "a"), (5, "c")], ["id", "category"])

# 将df中的字符串列转换为数值列
# 作用: 字符串类型的列转换成数值类型
# 场景: 模型训练的时候, 特征值和目标值都要是数值类型的, 我们可以使用StringIndex来把字符串类型的列转换数值类型
stringIndexer = StringIndexer(inputCol='category', outputCol='categoryIndex')

# 先调用fit方法创建模型
model = stringIndexer.fit(df)

# 再调用Transform方法进行模型计算并返回结果
result_df = model.transform(df)

result_df.show()
# +---+--------+-------------+
# | id|category|categoryIndex|
# +---+--------+-------------+
# | 0| a| 0.0|
# | 1| b| 2.0|
# | 2| c| 1.0|

# 将df中的字符串列转换为数值列 (没有多少应用场景)
indexString = IndexToString(inputCol='categoryIndex', outputCol='categoryString')

# 直接调用Transform计算结果
string_result_df = indexString.transform(result_df)
string_result_df.show()

MinmaxScaler

特征缩放(归一化处理):(特征值- 当前特征最小值)/ (当前特征最大值- 当前特征最小值)

  • 作用:把所有的特征缩放到0~1之间,都处于相同的量纲大小范围内
  • 场景:当特征之间量纲(取值大小)差距比较大的时候,需要先做特征缩放(归一化)
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
from pyspark.ml.feature import StringIndexer, MinMaxScaler
from pyspark.ml.linalg import Vectors
from pyspark.sql import SparkSession

if __name__ == '__main__':
# 创建Spark运行环境
spark = SparkSession\
.builder\
.appName('stringIndexer.test')\
.master('local[*]')\
.getOrCreate()
# 创建测试数据
dataFrame = spark.createDataFrame([
(0, Vectors.dense([1.0, 0.1, -1.0]),),
(1, Vectors.dense([2.0, 1.1, 1.0]),),
(2, Vectors.dense([3.0, 10.1, 3.0]),)], ["id", "features"])
dataFrame.show()
# 对特征列进行特征缩放
# 作用:把所有的特征缩放到0~1之间,都处于相同的量纲大小范围内
# 场景:当特征之间量纲(取值大小)差距比较大的时候,需要先做特征缩放(归一化)
minMaxScaler = MinMaxScaler(inputCol='features', outputCol='scaledFeatures')

# 调用fit方法创建模型
model = minMaxScaler.fit(dataFrame)

# 使用Transform方法进行计算
result_df = model.transform(dataFrame)

# 前面两步可以写成 result_df = minMaxScaler.fit(dataFrame).transform(dataFrame)
result_df.show()

VectorAssembler

  • 作用:VectorAssembler是一个变换器,它将给定的列表组合到一个向量列中。
  • 场景:在模型训练前, 我们要把模型训练用到的所有特征, 都放到一列中, 并且需要是向量的形式,,这个是Spark MLlib的硬性要求(模型训练传数据的时候, 只接收一列数据),只要涉及模型训练就会使用到VectorAssember。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from pyspark.ml.feature import StringIndexer, MinMaxScaler, VectorAssembler
from pyspark.ml.linalg import Vectors
from pyspark.sql import SparkSession

if __name__ == '__main__':
# 创建Spark运行环境
spark = SparkSession\
.builder\
.appName('stringIndexer.test')\
.master('local[*]')\
.getOrCreate()
# 创建测试数据
df = spark.createDataFrame(
[(0, 18, 1.0, Vectors.dense([0.0, 10.0, 0.5]), 1.0)],
["id", "hour", "mobile", "userFeatures", "clicked"])
# 作用:VectorAssembler是一个变换器,它将给定的列表组合到一个向量列中。
# 场景:在模型训练前, 我们要把模型训练用到的所有特征, 都放到一列中, 并且需要是向量的形式,,这个是Spark MLlib的硬性要求(模型训练传数据的时候, 只接收一列数据),只要涉及模型训练就会使用到VectorAssember。

# 把模型计算需要的特征列都封装到一个向量列中
vectorAssembler = VectorAssembler(inputCols=['hour','mobile','userFeatures','clicked',], outputCol='features')
result_df = vectorAssembler.transform(df)
result_df.show(truncate=False)