1. 二元分类

预测网页是 暂时性的, 还是 长青的 (ephemeral,  evergreen)

》读取文件,创建DataFrame 格式数据

from pyspark.context import SparkContext 
from pyspark.sql.session import SparkSession
# sc = SparkContext("local")
# spark = SparkSession(sc)

# 读取文本文件, 创建为DataFrame 结构
row_df = spark.read.format("csv").option("header", "true").option("delimiter", "\t").load(r"D:\data\spark\train.tsv")
row_df.count()
# 7395
row_df.printSchema()
root
 |-- url: string (nullable = true)
 |-- urlid: string (nullable = true)
 |-- boilerplate: string (nullable = true)
 |-- alchemy_category: string (nullable = true)
 |-- alchemy_category_score: string (nullable = true)
 |-- avglinksize: string (nullable = true)
 |-- commonlinkratio_1: string (nullable = true)
 |-- commonlinkratio_2: string (nullable = true)
 |-- commonlinkratio_3: string (nullable = true)
..........
row_df.select('url', 'alchemy_category', 'alchemy_category_score', 'is_news', 'label').show(10)
+--------------------+------------------+----------------------+-------+-----+
|                 url|  alchemy_category|alchemy_category_score|is_news|label|
+--------------------+------------------+----------------------+-------+-----+
|http://www.bloomb...|          business|              0.789131|      1|    0|
|http://www.popsci...|        recreation|              0.574147|      1|    1|
|http://www.menshe...|            health|              0.996526|      1|    1|
|http://www.dumbli...|            health|              0.801248|      1|    1|
|http://bleacherre...|            sports|              0.719157|      1|    0|
|http://www.conven...|                 ?|                     ?|      ?|    0|
|http://gofashionl...|arts_entertainment|               0.22111|      1|    1|
|http://www.inside...|                 ?|                     ?|      ?|    0|
|http://www.valetm...|                 ?|                     ?|      1|    1|
|http://www.howswe...|                 ?|                     ?|      ?|    1|
+--------------------+------------------+----------------------+-------+-----+
only showing top 10 rows

》自定义函数 udf  将 ? 转换成 0

from pyspark.sql.functions import udf
def replace_question(x):
    return ("0" if x=="?" else x)
replace_question = udf(replace_question)


from pyspark.sql.functions import col
import pyspark.sql.types

# 将第 4个字段开始转换成 double类型
df = row_df.select(['url', 'alchemy_category'] + [replace_question(col(column)).cast("double").alias(column) for column in row_df.columns[4:]])

df.printSchema()
root
 |-- url: string (nullable = true)
 |-- alchemy_category: string (nullable = true)
 |-- alchemy_category_score: double (nullable = true)
 |-- avglinksize: double (nullable = true)
 |-- commonlinkratio_1: double (nullable = true)
 |-- commonlinkratio_2: double (nullable = true)............

 》划分 训练集和测试集, 并将其 暂存到内存中

#
train_df, test_df = df.randomSplit([0.7, 0.3])
train_df.cache()
test_df.cache()

》先将字符串形式转换成 数字形式

from pyspark.ml.feature import StringIndexer

categoryIndexer = StringIndexer(inputCol='alchemy_category', outputCol='alchemy_category_Index')
categoryTransfomer = categoryIndexer.fit(df)
category_train = categoryTransfomer.transform(train_df)
category_train.select("alchemy_category", "alchemy_category_Index").show(5)
+------------------+----------------------+
|  alchemy_category|alchemy_category_Index|
+------------------+----------------------+
|arts_entertainment|                   2.0|
|        recreation|                   1.0|
|                 ?|                   0.0|
|                 ?|                   0.0|
|          business|                   3.0|
+------------------+----------------------+
only showing top 5 rows

》进行独热编码

from pyspark.ml.feature import OneHotEncoder

onehot = OneHotEncoder(dropLast= False, inputCol="alchemy_category_Index", outputCol= "alchemy_category_vector")
df2 = onehot.transform(category_train)
df2.select("alchemy_category", "alchemy_category_Index", "alchemy_category_vector").show(5)
#输出以个 14 维 的矩阵形式
+------------------+----------------------+-----------------------+
|  alchemy_category|alchemy_category_Index|alchemy_category_vector|
+------------------+----------------------+-----------------------+
|arts_entertainment|                   2.0|         (14,[2],[1.0])|
|        recreation|                   1.0|         (14,[1],[1.0])|
|                 ?|                   0.0|         (14,[0],[1.0])|
|                 ?|                   0.0|         (14,[0],[1.0])|
|          business|                   3.0|         (14,[3],[1.0])|
+------------------+----------------------+-----------------------+
only showing top 5 rows

》将几个特征列转换成 1 列的行向量,并统一命名。在建模时,只需使用该集合特征就可以。

from pyspark.ml.feature import VectorAssembler

#选择要进行转换的多个特征
asseblerInputs = ["alchemy_category_vector"] + row_df.columns[4: -1]


assembler = VectorAssembler(inputCols=asseblerInputs, outputCol= "features")
df3 = assembler.transform(df2)
print(df3.columns)
['url', 'alchemy_category', 'alchemy_category_score', 'avglinksize', 'commonlinkratio_1', 'commonlinkratio_2', 'commonlinkratio_3', 'commonlinkratio_4', 'compression_ratio', 'embed_ratio', 'framebased', 'frameTagRatio', 'hasDomainLink', 'html_ratio', 'image_ratio', 'is_news', 'lengthyLinkDomain', 'linkwordscore', 'news_front_page', 'non_markup_alphanum_characters', 'numberOfLinks', 'numwords_in_url', 'parametrizedLinkRatio', 'spelling_errors_ratio', 'label', 'alchemy_category_Index', 'alchemy_category_vector', 'features']
df3.select("features").first() #抽取得到所需要建模的特征
Out[22]:
Row(features=SparseVector(36, {2: 1.0, 14: 0.5811, 15: 2.5268, 16: 0.6807, 17: 0.3277, 18: 0.2689, 19: 0.2605, 20: 0.471, 23: 0.0277, 25: 0.2184, 26: 0.1053, 27: 1.0, 28: 1.0, 29: 13.0, 31: 16382.0, 32: 238.0, 33: 8.0, 34: 0.3361, 35: 0.0943}))
In [23]:

df2.select("spelling_errors_ratio").first()
Out[23]:
Row(spelling_errors_ratio=0.094298246)

》使用决策树进行建模

#
from pyspark.ml.classification import DecisionTreeClassifier
dt = DecisionTreeClassifier(labelCol="label", featuresCol="features", impurity="gini", maxDepth=10, maxBins=14)
dt_model = dt.fit(df3)
print(dt_model)

》由于上述同样对测试集需要进行同样操作,所以使用较为麻烦,最好是使用pipeline

#1. 建立pipeline
from pyspark.ml import Pipeline
from pyspark.ml.feature import StringIndexer, OneHotEncoder, VectorAssembler
from pyspark.ml.classification import DecisionTreeClassifier

stringIndex = StringIndexer(inputCol="alchemy_category", outputCol="alchemy_category_index")
onehoter = OneHotEncoder(dropLast=False, inputCol="alchemy_category_index", outputCol="alchemy_category_vector")
assemleInputs = ["alchemy_category_vector"] + row_df.columns[4: -1]
assembler = VectorAssembler(inputCols=asseblerInputs, outputCol="features")
dt = DecisionTreeClassifier(labelCol="label", featuresCol="features", impurity="gini", maxDepth=10, maxBins=14)
pipeline = Pipeline(stages = [stringIndex, onehoter, assembler, dt])
pipeline.getStages() #查看pipeline 的阶段
[StringIndexer_6c703f5b0925,
 OneHotEncoder_d71a3c746298,
 VectorAssembler_72028ec11847,
 DecisionTreeClassifier_ecf3417a4a68]

》使用pipeline 进行数据处理和 模型训练

pipelineModel = pipeline.fit(train_df)
pipelineModel.stages[3]
# 进行预测
predicted = pipelineModel.transform(test_df)
predicted.columns
'spelling_errors_ratio',
 'label',
 'alchemy_category_index',
 'alchemy_category_vector',
 'features',
 'rawPrediction',
 'probability',
 'prediction']
# 预测的类别,预测的概率
predicted.select("rawPrediction", "probability", "prediction", "label").take(5)
[Row(rawPrediction=DenseVector([56.0, 123.0]), probability=DenseVector([0.3128, 0.6872]), prediction=1.0, label=1.0),
 Row(rawPrediction=DenseVector([132.0, 32.0]), probability=DenseVector([0.8049, 0.1951]), prediction=0.0, label=0.0),
 Row(rawPrediction=DenseVector([132.0, 32.0]), probability=DenseVector([0.8049, 0.1951]), prediction=0.0, label=0.0),
 Row(rawPrediction=DenseVector([28.0, 221.0]), probability=DenseVector([0.1124, 0.8876]), prediction=1.0, label=1.0),
 Row(rawPrediction=DenseVector([120.0, 46.0]), probability=DenseVector([0.7229, 0.2771]), prediction=0.0, label=0.0)]

》使用auc 对模型进行评估

from pyspark.ml.evaluation import BinaryClassificationEvaluator
evaluator = BinaryClassificationEvaluator(rawPredictionCol="rawPrediction", labelCol="label", metricName="areaUnderROC")
auc = evaluator.evaluate(predicted)
auc    #0.62

》使用TrainValidationSplit找到最好参数

from pyspark.ml.tuning import ParamGridBuilder, TrainValidationSplit

paramGrid = ParamGridBuilder().addGrid(dt.impurity, ["gini", "entropy"]).addGrid(dt.maxDepth, [5, 10, 15]).addGrid(dt.maxBins, [10, 15, 20]).build()
# 在训练集找到最好的参数
tsv = TrainValidationSplit(estimator=dt, evaluator=evaluator, estimatorParamMaps=paramGrid, trainRatio=0.8)
tsv_pipeline = Pipeline(stages = [stringIndex, onehoter, assembler, tsv]) #将 dt 转换成 tsv 
tsv_pipelineModel = tsv_pipeline.fit(train_df)
bestModel = tsv_pipelineModel.stages[3].bestModel #找出最好的模型
bestModel
tsv_prediction = tsv_pipelineModel.transform(test_df)
tsv_auc = evaluator.evaluate(tsv_prediction)
tsv_auc    #0.65

》使用交叉验证方法

from pyspark.ml.tuning import CrossValidator

cv = CrossValidator(estimator=dt, evaluator= evaluator, estimatorParamMaps=paramGrid, numFolds=3)
cv_pipeline = Pipeline(stages = [stringIndex, onehoter, assembler, cv])
cv_pipelineModel = cv_pipeline.fit(train_df)
bestModel = cv_pipelineModel.stages[3].bestModel
bestModel
cv_prediction = cv_pipelineModel.transform(test_df)
cv_auc = evaluator.evaluate(cv_prediction)
cv_auc  # 0.67

》使用随机森林, 随机森林表现较好

from pyspark.ml.classification import RandomForestClassifier

rf = RandomForestClassifier(labelCol="label", featuresCol="features", numTrees=50)
rfpipeline = Pipeline(stages = [stringIndex, onehoter, assembler, rf])
rfpipelineModel = rfpipeline.fit(train_df)
rf_preddiction = rfpipelineModel.transform(test_df)
evaluator.evaluate(rf_preddiction) # 0.73

#使用交叉验证, 使用 3 折 交叉验证获取最好的参数
paramGrid = ParamGridBuilder().addGrid(rf.impurity, ["gini", "entropy"]).addGrid(rf.maxDepth, [5, 10, 15]).addGrid(rf.maxBins, [10, 15, 20]). \
addGrid(rf.numTrees, [10, 20, 60]).build()
cv_rf = CrossValidator(estimator=dt, estimatorParamMaps=paramGrid, evaluator=evaluator, numFolds=3)
rfcv_pipeline = Pipeline(stages = [stringIndex, onehoter, assembler, cv_rf])
rfcvModel = rfcv_pipeline.fit(train_df)
rfcv_prediction = rfcvModel.transform(test_df)
evaluator.evaluate(rfcv_prediction)    # 0.75

2.多元分类

预测森林的覆盖类别

》读取文件

file = r'D:\data\spark\covtype.data'
rawData = sc.textFile(file)
lines = rawData.map(lambda x: x.split(","))
lines.count() #581012

#查看字段数
fieldNum = len(lines.first())
fieldNum # 55

》创建列名和DataFrame

from pyspark.sql.types import StringType, StructField, StructType
fields = [StructField("f" + str(i), StringType(), True) for i in range(fieldNum)]
schema = StructType(fields)
covtype_df = spark.createDataFrame(lines, schema)
covtype_df.columns
covtype_df.printSchema()
root
 |-- f0: string (nullable = true)
 |-- f1: string (nullable = true)
 |-- f2: string (nullable = true)
 |-- f3: string (nullable = true)
 |-- f4: string (nullable = true)
 |-- f5: string (nullable = true)
 |-- f6: string (nullable = true)
 |-- f7: string (nullable = true)
 |-- f8: string (nullable = true)

》将字符串类型转换成double 类型

#转换成double 类型, col用于读取字段的数据
from pyspark.sql.functions import col
covtype_df = covtype_df.select([col(column).cast("double").alias(column) for column in covtype_df.columns])
covtype_df.show(2)

# 设置label ,withColumn, 最后一行设置为类别,从0开始
covtype_df = covtype_df.withColumn("label", covtype_df["f54"]-1).drop("f54")
covtype_df.show(1)
+------+----+---+-----+---+-----+-----+-----+-----+------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+-----+
|    f0|  f1| f2|   f3| f4|   f5|   f6|   f7|   f8|    f9|f10|f11|f12|f13|f14|f15|f16|f17|f18|f19|f20|f21|f22|f23|f24|f25|f26|f27|f28|f29|f30|f31|f32|f33|f34|f35|f36|f37|f38|f39|f40|f41|f42|f43|f44|f45|f46|f47|f48|f49|f50|f51|f52|f53|label|
+------+----+---+-----+---+-----+-----+-----+-----+------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+-----+
|2596.0|51.0|3.0|258.0|0.0|510.0|221.0|232.0|148.0|6279.0|1.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|1.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|0.0|  4.0|
+------+----+---+-----+---+-----+-----+-----+-----+------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+-----+
only showing top 1 row

》将数据分为训练集和测试集

#将数据随机分为训练集和测试集, 并将它们存与内存中,加快后序运行速度 cache()
train_df, test_df = covtype_df.randomSplit(weights=[0.7, 0.3], seed=666)#设立随机种子
train_df.cache()
test_df.cache()

》使用pipeline

#进行训练
from pyspark.ml import Pipeline
from pyspark.ml.feature import VectorAssembler
from pyspark.ml.classification import DecisionTreeClassifier
from pyspark.ml import evaluation
featuresCols = covtype_df.columns[:54]
# featuresCols
vec = VectorAssembler(inputCols=featuresCols, outputCol="features")
dt = DecisionTreeClassifier(labelCol="label", featuresCol="features", impurity="gini", seed=666, maxBins=20, maxDepth=5)
dt_pipeline = Pipeline(stages = [vec, dt])
dtModel = dt_pipeline.fit(train_df)
dt_prediction = dtModel.transform(test_df)
dt_prediction.columns

dt_prediction.select(["features", "probability", "rawPrediction", "prediction", "label"]).show(2)
+--------------------+--------------------+--------------------+----------+-----+
|            features|         probability|       rawPrediction|prediction|label|
+--------------------+--------------------+--------------------+----------+-----+
|(54,[0,1,2,3,4,5,...|[0.0,0.0244421380...|[0.0,471.0,12438....|       2.0|  2.0|
|(54,[0,1,2,3,4,5,...|[0.0,0.0244421380...|[0.0,471.0,12438....|       2.0|  2.0|
+--------------------+--------------------+--------------------+----------+-----+
only showing top 2 rows

》对模型进行评估

#对模型准确率进行评估
from pyspark.ml.evaluation import MulticlassClassificationEvaluator
evaluator = MulticlassClassificationEvaluator(labelCol="label", predictionCol="prediction", metricName= "accuracy") #使用准确率进行评估
acc = evaluator.evaluate(dt_prediction)
acc # 0.70

# 找出最佳模型, TrainValidationSplit需要传入分类器,参数,评估器
from pyspark.ml.tuning import ParamGridBuilder, TrainValidationSplit

paramGrid = ParamGridBuilder().addGrid(dt.impurity, ["gini", "entropy"]).addGrid(dt.maxDepth, [10, 15, 25]).addGrid(dt.maxBins, [30, 40, 50]).build()
tvs = TrainValidationSplit(estimator=dt, evaluator=evaluator, estimatorParamMaps=paramGrid, trainRatio=0.8, seed=666)
tsv_pipeline = Pipeline(stages=[vec, tvs])
tsvMoodel = tsv_pipeline.fit(train_df)

bestModel = tsvMoodel.stages[1].bestModel
bestModel.toDebugString[:500] #对建树过程进行查看

# 使用 withColumnRenamed 对列名进行重新命名
predictions = tsvMoodel.transform(test_df)
result = predictions.withColumnRenamed("f0", "海拔").withColumnRenamed("f1", "方位") \
.withColumnRenamed("f2", "斜率").withColumnRenamed("f3", "垂直距离") \
.withColumnRenamed("f4", "水平距离").withColumnRenamed("f5", "阴影")
result.select("海拔", "方位", "斜率", "垂直距离", "水平距离",  "阴影", "label", "prediction").show(5)
+------+----+----+--------+--------+-----+-----+----------+
|  海拔|方位|斜率|垂直距离|水平距离| 阴影|label|prediction|
+------+----+----+--------+--------+-----+-----+----------+
|1867.0|20.0|15.0|   108.0|    19.0|120.0|  2.0|       2.0|
|1876.0|25.0|17.0|   124.0|    26.0|150.0|  2.0|       2.0|
|1876.0|29.0|19.0|   124.0|    34.0| 90.0|  5.0|       5.0|
|1877.0|27.0|24.0|    90.0|    18.0| 95.0|  5.0|       5.0|
|1883.0|29.0|24.0|    60.0|    24.0|108.0|  5.0|       5.0|
+------+----+----+--------+--------+-----+-----+----------+
only showing top 5 rows

》计算准确率

#计算准确率
acc = evaluator.evaluate(predictions)
acc
#计算准确率
acc = evaluator.evaluate(predictions)
acc
Out[86]:
0.9292631820660754

3. 回归

“bike sharing” 数据集用于预测在不同情况下的单车的每一小时的租用的数量

》创建DataFrame

from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("Python Spark Regression").config("spark.some.config.option", "some-value").getOrCreate()
# 创建 DataFrame
file = r'D:\data\spark\hour.csv'
hour_df = spark.read.format('csv').option("header", "true").load(file)
hour_df.count()    # 17379
hour_df.printSchema()
root
 |-- instant: string (nullable = true)
 |-- dteday: string (nullable = true)
 |-- season: string (nullable = true)
 |-- yr: string (nullable = true)
 |-- mnth: string (nullable = true)
 |-- hr: string (nullable = true)
 |-- holiday: string (nullable = true)
 |-- weekday: string (nullable = true)
 |-- workingday: string (nullable = true)
 |-- weathersit: string (nullable = true)
 |-- temp: string (nullable = true)
 |-- atemp: string (nullable = true)
 |-- hum: string (nullable = true)
 |-- windspeed: string (nullable = true)
 |-- casual: string (nullable = true)
 |-- registered: string (nullable = true)
 |-- cnt: string (nullable = true)
# 删除不需要的字段
hour_df = hour_df.drop("instant").drop("yr").drop("dteday").drop("casual").drop("registered")

#将字符串类型转换成 double 类型, col 读取字段数据, cast("double") 转换成double
from pyspark.sql.functions import col
hour_df = hour_df.select([col(column).cast("double").alias(column) for column in hour_df.columns])
hour_df.printSchema()
root
 |-- season: double (nullable = true)
 |-- mnth: double (nullable = true)
 |-- hr: double (nullable = true)
 |-- holiday: double (nullable = true)
 |-- weekday: double (nullable = true)
 |-- workingday: double (nullable = true)
 |-- weathersit: double (nullable = true)
 |-- temp: double (nullable = true)
 |-- atemp: double (nullable = true)
 |-- hum: double (nullable = true)
 |-- windspeed: double (nullable = true)
 |-- cnt: double (nullable = true)
hour_df.show(5)
+------+----+---+-------+-------+----------+----------+----+------+----+---------+----+
|season|mnth| hr|holiday|weekday|workingday|weathersit|temp| atemp| hum|windspeed| cnt|
+------+----+---+-------+-------+----------+----------+----+------+----+---------+----+
|   1.0| 1.0|0.0|    0.0|    6.0|       0.0|       1.0|0.24|0.2879|0.81|      0.0|16.0|
|   1.0| 1.0|1.0|    0.0|    6.0|       0.0|       1.0|0.22|0.2727| 0.8|      0.0|40.0|
|   1.0| 1.0|2.0|    0.0|    6.0|       0.0|       1.0|0.22|0.2727| 0.8|      0.0|32.0|
|   1.0| 1.0|3.0|    0.0|    6.0|       0.0|       1.0|0.24|0.2879|0.75|      0.0|13.0|
|   1.0| 1.0|4.0|    0.0|    6.0|       0.0|       1.0|0.24|0.2879|0.75|      0.0| 1.0|
+------+----+---+-------+-------+----------+----------+----+------+----+---------+----+
only showing top 5 rows

》划分训练集和测试集

train_df, test_df = hour_df.randomSplit(weights=[0.7, 0.3], seed=666)
train_df.cache()
test_df.cache()

》建立的pipeline

#使用VectorIndexer 使月份,星期, 小时转换成类别
from pyspark.ml import Pipeline
from pyspark.ml.feature import VectorIndexer, VectorAssembler, StringIndexer
from pyspark.ml.regression import DecisionTreeRegressor
featuresCols = hour_df.columns[:-1]
featuresCols

vector = VectorAssembler(inputCols=featuresCols, outputCol="va_features")
vIndexer = VectorIndexer(inputCol="va_features", outputCol="features", maxCategories=24)
dt = DecisionTreeRegressor(featuresCol="features", labelCol="cnt", seed=1024)
dt_pipeline = Pipeline(stages=[vector, vIndexer, dt])
dt_pipeline.getStages()

dtModel = dt_pipeline.fit(train_df)
prediction = dtModel.transform(test_df)
prediction.columns

prediction.select("cnt", "prediction").show(5)
+----+-----------------+
| cnt|       prediction|
+----+-----------------+
|39.0|           59.575|
|10.0|38.08888888888889|
|12.0|38.08888888888889|
|13.0|38.08888888888889|
|16.0|38.08888888888889|
+----+-----------------+
only showing top 5 rows

#预测的很差

》对模型进行评估

from pyspark.ml.evaluation import RegressionEvaluator
evaluator = RegressionEvaluator(labelCol="cnt", predictionCol="prediction", metricName="rmse")
rmse = evaluator.evaluate(prediction)
rmse # 93.2708

#找出最佳模型参数
from pyspark.ml.tuning import ParamGridBuilder, TrainValidationSplit

paramGrid = ParamGridBuilder().addGrid(dt.maxDepth, [5, 10, 15, 25]).addGrid(dt.maxBins, [25, 35, 45, 50]).build() # bins 必须要大于 24
tvs = TrainValidationSplit(estimator=dt, evaluator=evaluator, estimatorParamMaps=paramGrid, trainRatio=0.8)
tvs_pipeline = Pipeline(stages=[vector, vIndexer, tvs])
tvs_model = tvs_pipeline.fit(train_df)
tvs_prediction = tvs_model.transform(test_df)
tsv_rmse = evaluator.evaluate(tvs_prediction)
tsv_rmse # 82.3553

#使用交叉验证
from pyspark.ml.tuning import CrossValidator
cv = CrossValidator(estimator=dt, evaluator=evaluator, estimatorParamMaps=paramGrid, numFolds=3)
cv_pipeline = Pipeline(stages = [vector, vIndexer, cv])
cv_model = cv_pipeline.fit(train_df)
cv_prediction = cv_model.transform(test_df)
cv_rmse = evaluator.evaluate(cv_prediction)
cv_rmse    #82.483

》使用梯度提升树(GBDT)进行训练

from pyspark.ml.regression import GBTRegressor
gbdt = GBTRegressor(labelCol="cnt", featuresCol="features")
gbdt_pipeline = Pipeline(stages=[vector, vIndexer, gbdt])
gbdt_model = gbdt_pipeline.fit(train_df)
gbdt_prediction = gbdt_model.transform(test_df)
gbdt_rmse = evaluator.evaluate(gbdt_prediction)
gbdt_rmse    # 75.863

#使用交叉验证找出最佳的参数
paramGrid = ParamGridBuilder().addGrid(gbdt.maxDepth, [5, 10]).addGrid(gbdt.maxBins, [25, 40]).addGrid(gbdt.maxIter, [10, 50]).build()
cross = CrossValidator(estimator=gbdt, evaluator=evaluator, numFolds=3, estimatorParamMaps=paramGrid, seed=1024)
gbdt_cross = Pipeline(stages=[vector, vIndexer, cross])

gbdt_model = gbdt_cross.fit(train_df)
pred = gbdt_model.transform(test_df)
rmse = evaluator.evaluate(pred)
rmse #  70