在这里,我们将基于DataFrame使用MLlib包。 另外,根据Spark文档,现在主要的Spark机器学习API是spark.ml包中基于DataFrame的一套模型。
1 ML包的介绍
从顶层上看,ML包主要包含三大抽象类:转换器、预测器和工作流。
1.1 转换器(Transformer)
从Transformer抽象类派生出来的每一个新的Transformer都需要实现一个.transform(…) 方法,该方法可以将一个DataFrame转换成另一个DataFrame。
在spark.ml.feature中有许多Transformer:
String<->Index 相互转换:
1.2 预测器(Estimators)
预测器可以被认为是需要评估的统计模型,来进行预测或对观测结果进行分类。
如果派生自抽象的Estimator类,则新模型必须实现.fit(…)方法,该方法给DataFrame中的数据以及一些默认或用户指定的参数泛化模型。
一、分类
ML包提供了七种分类模型,这里介绍四种常用的模型。
二、回归
PySpark ML包中有七种模型可用于回归任务。这里只介绍两种模型,如后续需要用可查阅官方手册。
三、聚类
聚类是一种无监督的模型。PySpark ML包提供了四种模型。
1.3 管道/工作流(Pipeline)
一个管道串起多个转换器和预测器,明确一个机器学习工作流。
预测婴儿存活率。
import pyspark.sql.types as typ
labels = [
('INFANT_ALIVE_AT_REPORT', typ.IntegerType()),
('BIRTH_PLACE', typ.StringType()),
('MOTHER_AGE_YEARS', typ.IntegerType()),
('FATHER_COMBINED_AGE', typ.IntegerType()),
('CIG_BEFORE', typ.IntegerType()),
('CIG_1_TRI', typ.IntegerType()),
('CIG_2_TRI', typ.IntegerType()),
('CIG_3_TRI', typ.IntegerType()),
('MOTHER_HEIGHT_IN', typ.IntegerType()),
('MOTHER_PRE_WEIGHT', typ.IntegerType()),
('MOTHER_DELIVERY_WEIGHT', typ.IntegerType()),
('MOTHER_WEIGHT_GAIN', typ.IntegerType()),
('DIABETES_PRE', typ.IntegerType()),
('DIABETES_GEST', typ.IntegerType()),
('HYP_TENS_PRE', typ.IntegerType()),
('HYP_TENS_GEST', typ.IntegerType()),
('PREV_BIRTH_PRETERM', typ.IntegerType())
]
# Specifying the schema of the DataFrame
schema = typ.StructType([
typ.StructField(e[0], e[1], False) for e in labels
])
births = spark.read.csv('births_transformed.csv.gz',
header=True,
schema=schema)
因为统计模型只能对数值数据进行操作,我们必须对birth_place变量进行编码。
import pyspark.ml.feature as ft
# Casting the column to an IntegerType
births = births \
.withColumn('BIRTH_PLACE_INT', births['BIRTH_PLACE'] \
.cast(typ.IntegerType()))
# Using the OneHotEncoder to encode
encoder = ft.OneHotEncoder(
inputCol='BIRTH_PLACE_INT',
outputCol='BIRTH_PLACE_VEC')
# Using the VectorAssembler to create a single column with all the features collated together.
featuresCreator = ft.VectorAssembler(
inputCols=[col[0] for col in labels[2:]] + \
[encoder.getOutputCol()],
outputCol='features'
)
import pyspark.ml.classification as cl
logistic = cl.LogisticRegression(
maxIter=10,
regParam=0.01,
labelCol='INFANT_ALIVE_AT_REPORT')
from pyspark.ml import Pipeline
pipeline = Pipeline(stages=[
encoder,
featuresCreator,
logistic
])
births_train, births_test = births \
.randomSplit([0.7, 0.3], seed=666)
model = pipeline.fit(births_train)
test_model = model.transform(births_test)
import pyspark.ml.evaluation as ev
evaluator = ev.BinaryClassificationEvaluator(
rawPredictionCol='probability',
labelCol='INFANT_ALIVE_AT_REPORT')
print(evaluator.evaluate(test_model,
{evaluator.metricName: 'areaUnderROC'}))
print(evaluator.evaluate(test_model,
{evaluator.metricName: 'areaUnderPR'}))
pipelinePath = './infant_oneHotEncoder_Logistic_Pipeline'
pipeline.write().overwrite().save(pipelinePath)
# You can load it up later and use it straight away to .fit(...) and predict:
loadedPipeline = Pipeline.load(pipelinePath)
loadedPipeline \
.fit(births_train)\
.transform(births_test)