MLlib主要概念之ML Pipelines

ML Pipelines

前言:在这一节中,我们介绍一个叫做ML Pipelines管道的概念。ML Pipelines提供了一套建立在 DataFrames 之上的高级APIs来帮助用户创造和协调机器学习中实际实用的管道技术。
本文布局
这里写图片描述

Pipelines的主要概念

MLlib是标准化的机器学习算法APIs来让机器学习算法变得更简单融合复杂的算法在一个管道里,或者工作流。管道是一种灵感来自于 scikit-learn project,这节将会介绍它的Pipelines API。

DataFrame:这是ML API 使用来自于Spark SQL的DataFrame作为一个ML 自己的数据集。DataFrame是一种能够支持多种数据类型的数据集。比如DataFrame能够含有不同的列存储文本,向量,真实的标签,和预测标签。

Transformer:Transformer是一种能够将一个DataFrame转化另一个DataFrame的算法。比如ML 模型是一个Transformer ,这样的模型就能够将一个有特征的DataFrame转化为一个预测的DataFrame。

Estimator:Pipelines是一个能够采取合适的方法将DataFrame产出一个Transformer。

Pipeline:Pipeline是一种被多种Transformers 和Estimators共同描述的唯一的 ML workflow;

Parameter:所有的Transformers and Estimators都共用一个指定的参数API。

DataFrame

机器学习能够被应用到各种不同的数据类型,比如向量,文本,图片,和结构化数据。这个API为了支持多样数据类型采用来自Spark SQL的DataFrame。
DataFrame支持许多基础的和结构化的类型,并且能够被RDD明确和隐性的创造。这段代码事例,DataFrame的列被text, “features,” 和 “label”命名了

Pipeline的组成

Transformers
Transformers是一个包含了特征transformers和已经学习好的模型的抽象概念。从技术上来说transformers实现了transform()方法, transform()能够将 DataFrame转化成另一个 DataFrame。通常是通过增加一个或者更多的列来实现。

Estimators
Estimators是一个学习算法或者任何在数据上训练和普适算法的抽象概念。从技术上来说,Estimators实现了 fit()方法,fit()是一种接受 DataFrame并转化为模型的方法,是一个Transformer。举个例子,
一个学习算法比如逻辑回归算法就是一个Estimators,并使fit()方法训练出一个LogisticRegressionModel。

pipeline components的属性
Transformer.transform()s 和Estimator.fit()s都是无状态的 ,在未来,状态性的算法会由可选择的概念支持。
每一个 Transformer 和 Estimator运行实例都有一个不同的ID,这个ID用来区别参数。(下文讨论)

Pipeline
在机器学习中,运行一个序列化好的数据的算法是一件很常见的事情。比如一个简单的文本处理工作流可能包含下面几个步骤。
1.对每个文档进行分词。
2.将每个文档分词转化为数学特征向量。
3.利用特征向量和标签产生一个预测模型。
MLlib使用Pipeline代表这个工作流。Pipeline由序列化好的PipelineStages和运行特定的顺序。下节点我们使用这个简单的工作流来运行一个简单的例子。

他是如何工作的

一个 Pipeline已经被指定了运行步骤,每一个步骤不是 Transformer就是Estimator,这些步骤都是按顺序运行的。输入的DataFrame数据被转化,每当通过每一个步骤。在Transformer阶段,transform()返回DataFrame。在Estimator阶段,fit()返回一个Transformer(这是一个 PipelineModel的一部分,或者已经转化合适的Pipeline), Transformer的transform()方法返回一个DataFrame。
下面的图片是使用Pipeline的过程。
这里写图片描述

在上面的图片中,第一行代表了 Pipeline三个阶段。前面两个阶段(Tokenizer and HashingTF)是Transformers(蓝色),最后的第三阶段(LogisticRegression)是 Estimator(红色)。第二行代表了数据通过pipeline的转化,圆柱面代表了DataFrames。Pipeline.fit()载入一个原始的DataFrame,包含RAW 文本文档和标签。Tokenizer.transform()对raw 文本文档进行分词,并引用DataFrame的词加入新列,HashingTF.transform()将词列化为特征向量。使用生成的特征向量加入新的列。现在,LogisticRegression是一个Estimator, Pipeline 首先调用LogisticRegression.fit()方法产生一个 LogisticRegressionModel(逻辑回归模型)。Pipeline如果有更多的步骤,他就回调用 LogisticRegressionModel’s transform()方法,在DataFrame还未通过下一步骤时候。Pipelines and PipelineModels帮助我们确保训练数据和测试数据通过了相同特征处理步骤。

Example: Estimator(估计量), Transformer, and Param

from pyspark.ml.linalg import Vectors
from pyspark.ml.classification import LogisticRegression

# Prepare training data from a list of (label, features) tuples.
training = spark.createDataFrame([
    (1.0, Vectors.dense([0.0, 1.1, 0.1])),
    (0.0, Vectors.dense([2.0, 1.0, -1.0])),
    (0.0, Vectors.dense([2.0, 1.3, 1.0])),
    (1.0, Vectors.dense([0.0, 1.2, -0.5]))], ["label", "features"])

# Create a LogisticRegression instance. This instance is an Estimator.
lr = LogisticRegression(maxIter=10, regParam=0.01)
# Print out the parameters, documentation, and any default values.
print "LogisticRegression parameters:\n" + lr.explainParams() + "\n"

# Learn a LogisticRegression model. This uses the parameters stored in lr.
model1 = lr.fit(training)

# Since model1 is a Model (i.e., a transformer produced by an Estimator),
# we can view the parameters it used during fit().
# This prints the parameter (name: value) pairs, where names are unique IDs for this
# LogisticRegression instance.
print "Model 1 was fit using parameters: "
print model1.extractParamMap()

# We may alternatively specify parameters using a Python dictionary as a paramMap
paramMap = {lr.maxIter: 20}
paramMap[lr.maxIter] = 30  # Specify 1 Param, overwriting the original maxIter.
paramMap.update({lr.regParam: 0.1, lr.threshold: 0.55})  # Specify multiple Params.

# You can combine paramMaps, which are python dictionaries.
paramMap2 = {lr.probabilityCol: "myProbability"}  # Change output column name
paramMapCombined = paramMap.copy()
paramMapCombined.update(paramMap2)

# Now learn a new model using the paramMapCombined parameters.
# paramMapCombined overrides all parameters set earlier via lr.set* methods.
model2 = lr.fit(training, paramMapCombined)
print "Model 2 was fit using parameters: "
print model2.extractParamMap()

# Prepare test data
test = spark.createDataFrame([
    (1.0, Vectors.dense([-1.0, 1.5, 1.3])),
    (0.0, Vectors.dense([3.0, 2.0, -0.1])),
    (1.0, Vectors.dense([0.0, 2.2, -1.5]))], ["label", "features"])

# Make predictions on test data using the Transformer.transform() method.
# LogisticRegression.transform will only use the 'features' column.
# Note that model2.transform() outputs a "myProbability" column instead of the usual
# 'probability' column since we renamed the lr.probabilityCol parameter previously.
prediction = model2.transform(test)
selected = prediction.select("features", "label", "myProbability", "prediction")
for row in selected.collect():
    print row

Example: Pipeline

from pyspark.ml import Pipeline
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.feature import HashingTF, Tokenizer

# Prepare training documents from a list of (id, text, label) tuples.
training = spark.createDataFrame([
    (0L, "a b c d e spark", 1.0),
    (1L, "b d", 0.0),
    (2L, "spark f g h", 1.0),
    (3L, "hadoop mapreduce", 0.0)], ["id", "text", "label"])

# Configure an ML pipeline, which consists of three stages: tokenizer, hashingTF, and lr.
tokenizer = Tokenizer(inputCol="text", outputCol="words")
hashingTF = HashingTF(inputCol=tokenizer.getOutputCol(), outputCol="features")
lr = LogisticRegression(maxIter=10, regParam=0.01)
pipeline = Pipeline(stages=[tokenizer, hashingTF, lr])

# Fit the pipeline to training documents.
model = pipeline.fit(training)

# Prepare test documents, which are unlabeled (id, text) tuples.
test = spark.createDataFrame([
    (4L, "spark i j k"),
    (5L, "l m n"),
    (6L, "mapreduce spark"),
    (7L, "apache hadoop")], ["id", "text"])

# Make predictions on test documents and print columns of interest.
prediction = model.transform(test)
selected = prediction.select("id", "text", "prediction")
for row in selected.collect():
    print(row)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章