文章目录
一、PySpark机器学习模块
pyspark.ml为机器学习模块,提供了分类,回归,聚类,推荐等算法模型。如下表所示。
类别 | 模型 | 功能 |
分类模型 | LogisticRegression | 逻辑回归模型,分类的基准模型 |
DecisionTreeClassifier | 决策树模型 | |
GBTClassifier | 梯度提升决策树模型 | |
RandomForestRegressor | 随机森林模型 | |
NaiveBayes | 贝叶斯模型 | |
回归模型 | DecisionTreeRegressor | 决策树回归模型 |
RandomForestRegressor | 随机森林回归模型 | |
GBTRegressor | 梯度提升回归树模型 | |
LinearRegression | 线性回归模型 | |
GeneralizedLinearRegression | 广义线性回归模型 | |
聚类模型 | LDA | 主题生成模型,用于获取文本文档的主题 |
KMeans | K均值聚类模型 | |
BisectingKMeans | 结合K均值算法和层次聚类算法,将数据迭代分解为K类 | |
推荐模型 | ALS | 协同过滤算法(基于交替最小二乘法) |
类别 | 评估方法 | 功能 |
分类模型 | BinaryClassificationEvaluator | 评估二分类模型的方法 |
MulticlassClassificationEvaluator | 评估多分类模型的方法 | |
MultilabelClassificationEvaluator | 评估多标签分类模型的方法 | |
回归模型 | RegressionEvaluator | 评估回归模型的方法 |
聚类模型 | ClusteringEvaluator | 评估聚类模型的方法 |
推荐模型 | RankingEvaluator | 评估排名模型的方法 |
pyspark.ml.tuning模块提供了模型优化方法,通过对模型的参数进行 调整,可以获得较好的预测 结果。先设定参数的可选范围,然后遍历参数,从中选择最优的参数组合。模型优化方法如下:
优化方法 | 功能 |
---|---|
ParamGridBuilder | 参数网格,设置参数值的范围,遍历搜索网格 |
CrossValidator | K折交叉验证,将数据集分成K份,选择其中1份作为测试数据集,剩下的K-1份数据分别作用来训练模型,总共进行K次训练,取K次估计值的平均值。 |
TrainValidationSplit | 根据参数划分训练数据集和测试数据集,模型只训练一次。 |
二、回归模型应用案例1:广告投入后,销售额预测
回归算法是一类用于预测数值型数据的算法。回归算法的目标是找到一个函数,该函数能够将输入变量(特征)映射到输出变量(目标),以便预测新的、未见过的数据的目标值。
本案例根据商品的广告投入,预测商品销售额,数据集为advertising.csv,“微信”、“微博”、“其他”三个字段为特征,表示在微信、微博和其他平台的广告投入,“销售额”为目标值,表示投入广告后,商品的销售额。部分数据如下图所示。
待预测数据集为:advertising_pred.csv,没有目标值,使用训练好的回归模型,预测目标值(销售额)。该数据集的数据如下所示。
数据集advertising.csv和advertising_pred.csv已上传至HDFS系统的/data目录下。
1.数据读取
PySpark从HDFS的目录/data/下,读取数据集advertising.csv。
from pyspark import SparkConf
from pyspark.ml.feature import StringIndexer, VectorAssembler, OneHotEncoder, MinMaxScaler
from pyspark.sql import SparkSession, Row
from pyspark.sql.functions import *
from pyspark.ml.classification import *
from pyspark.ml.evaluation import *
from pyspark.ml import Pipeline, tuning
from pyspark.ml.linalg import Vectors
from pyspark.ml.regression import *
conf = SparkConf().setAppName("回归模型3").setMaster('spark://192.168.126.10:7077')
sc = SparkContext.getOrCreate(conf)
spark = SparkSession(sc)
# -----------------1.数据获取-------------------
filename = "advertising.csv"
advertising = spark.read.csv('hdfs://192.168.126.10:9000/data/' + filename, header=True,
inferSchema=True) # 训练集包含标题行,inferSchema=True自动推断数据类型
advertising.describe().show() # 查看数据集的基本数据信息
advertising.printSchema() # 输出数据集的结构
advertising.show(5)
print(f"训练数据集总的记录数:{advertising.count()}, 总列数:{len(advertising.columns)}")
程序运行结果如下所示。
2. 特征工程
特征工程(Feature Engineering)是指在机器学习中,通过对原始数据进行选择、提取、变换等操作,生成更能够表达数据本质特征的特征集合。特征工程主要包括以下几个方面:
(1)数据预处理:指在特征工程中对原始数据进行清洗、标准化、归一化等操作,以便更好地被算法使用。数据预处理的目的是消除数据的噪声和异常值,提高数据的质量和可用性。
(2)特征选择:指从原始数据中选择一部分最具有代表性的特征,以减少特征的维度和冗余性,提高模型的泛化能力和效率。
(3)特征提取:指从原始数据中提取一些可以代表数据特征的新特征,以帮助机器学习算法更好地发现数据之间的关系。特征提取的方法包括主成分分析(PCA)、独立成分分析(ICA)、局部线性嵌入(LLE)等。
(4)特征变换:指对原始数据进行变换,以产生新的特征,以便更好地被算法使用。常见的特征变换包括多项式变换、对数变换、指数变换等。
特征工程不一定要做完上面所提的全部内容,需要根据具体问题的特点和数据的属性进行合理的选择和调整。
本案例比较简单,字段很少,并且全部为数值型数据,因此不需要做太复杂的特征工程。
本案例选择所有的特征字段,然后将选择的字段转换为一个向量,最后将数据集划分为训练集和测试集。代码如下:
# ----------------------2. 特征工程---------------------
# 特征选择:选择数值型的字段,用于后期的目标值预测
features = ['微信', '微博', '其他']
# 将选择的特征列转换为一个向量
data_assembler = VectorAssembler(inputCols=features,
outputCol='向量化后特征') # 构建特征向量转换器。将给定的特征列,转换为一个向量列,列名自定义为向量化后特征
advertising_assembler = data_assembler.transform(advertising) # 使用特征向量转换器,向量化数据集的特征。
advertising_assembler.show(5)
advertising_train, advertising_test = advertising_assembler.randomSplit([0.7, 0.3], seed=3) # 划分训练集和测试集,种子为3(用于重现实验结果)
向量化后的特征如下图所示。
3.构建模型:线性回归模型
待预测目标值为销售额,是一个连续值,因此选择回归模型。
# -------------3.模型构建:线性回归模型----------------
lr = LinearRegression(labelCol='销售额', featuresCol='向量化后特征', regParam=0.1) # 构建线性回归模型。模型的构建需要两列数据:标签列和特征列
lrModel = lr.fit(advertising_train) # 模型训练:拟合训练数据,得到 线性回归模型
# 模型评估,方法一:训练模型后的基本摘要summary
trainingSummary = lrModel.summary # 内部评估,使用训练数据评估模型基本性能
print("均方误差,接近0模型性能最优:", trainingSummary.meanSquaredError)
print("判定系数R^2,接近1模型性能最优:", trainingSummary.r2)
# 模型评估,方法二:用外部测试集评估模型,模型评估方法RegressionEvaluator
lr_predictions = lrModel.transform(advertising_test) # 用训练好的模型,预测测试集数据
lr_predictions.show() # 查看预测结果,发现有预测结果,列名为prediction
re_evaluator = RegressionEvaluator(labelCol='销售额',
predictionCol='prediction',
metricName='rmse') # 构建评估器,真实值(标签)为y列,预测值为prediction,评价指标为均方误差rmse
print("均方误差,接近0模型性能最优:", re_evaluator.evaluate(lr_predictions))
re_evaluator = RegressionEvaluator(labelCol='销售额',
predictionCol='prediction',
metricName='r2')
print("判定系数R^2,接近1模型性能最优:", re_evaluator.evaluate(lr_predictions))
上面的代码中,
(1)构建模型:首先构建线性回归模型 lr = LinearRegression(labelCol=‘销售额’, featuresCol=‘向量化后特征’, regParam=0.1)。模型的构建需要两列数据:标签列和特征列。标签列(目标列)为“销售额”,特征列为已经向量化的特征列:“向量化后特征”。设置正则化参数regParam为0.1
(2)训练模型:# 模型训练:使用训练数据集advertising_train拟合线性回归模型 。lrModel = lr.fit(advertising_train)
(3)模型评估:
方法一: 获取模型的摘要信息,用于内部评估 ,trainingSummary = lrModel.summary。可以打印均方误差,该值越接近0表示模型性能越好。或打印判定系数R^2,该值越接近1表示模型性能越好 。
方法二:使用外部测试集评估模型性能。
-
先使用训练好的模型对测试集advertising_test进行预测,得到预测结果。
-
构建评估器,用于计算均方误差(RMSE)。re_evaluator = RegressionEvaluator(labelCol=‘销售额’, predictionCol=‘prediction’, metricName=‘rmse’) 。评估指标有:
评估指标 | 指标具体名字 | 含义 |
---|---|---|
rmse | Root Mean Square Error,均方根误差 | 表示预测值与真实值之间的平均偏差大小。RMSE越小,表示模型的预测精度越高。 |
mse | Mean Square Error,均方误差 | 与RMSE类似,但MSE是平方差的平均值,不取平方根。MSE越小,同样表示模型的预测精度越高。 |
r2 | R-squared,判定系数 | 表示模型对数据的拟合程度。R²的值越接近1,表示模型的拟合效果越好,预测能力越强。 |
mae | Mean Absolute Error,平均绝对误差 | 表示预测值与真实值之间的平均绝对偏差。MAE越小,表示模型的预测精度越高。 |
var | Variance,方差 | 表示数据的离散程度。在模型评估中,方差通常用于衡量模型的稳定性或泛化能力。方差越小,表示模型对数据的拟合越稳定,泛化能力可能越强(但也要注意避免过拟合)。 |
由参数metricName决定评估指标。
- 由评估器对测试集的预测结果进行评估:re_evaluator.evaluate(lr_predictions),得到评估结果。
4.模型应用:使用训练好的模型预测数据
模型使用步骤:
(1)导入待预测数据。
(2)使用前面构建的特征向量转换器,将待预测 数据的多个特征列转换为向量。
(3)使用前面训练好的线性回归模型,预测数据(销售量)。
代码如下:
# ----------4.模型应用:使用训练好的模型预测数据--------------
filename = "advertising_pred.csv"
newData = spark.read.csv('hdfs://192.168.126.10:9000/data/' + filename, header=True,
inferSchema=True) # 训练集包含标题行,inferSchema=True自动推断数据类型
newData2 = data_assembler.transform(newData) # 利用前面构建的特征向量转换器,将多个特征列转换为向量
newDataPred = lrModel.transform(newData2) # 使用训练好的线性回归模型,预测数据。
newDataPred.show() # 可以看到待预测数据集多了一列预测数据prediction,
预测的销售额(prediction)为10.12,结果如下:
三、其他回归模型的构建与应用:决策树回归模型(DecisionTreeRegressor)
1. 构建决策树回归模型
构建决策树回归模型,指定标签列(销售额)和特征列(向量化后特征)
dtr = DecisionTreeRegressor(labelCol=‘销售额’, featuresCol=‘向量化后特征’)
2. 训练模型
使用训练数据集advertising_train训练决策树回归模型,dtrModel = dtr.fit(advertising_train)。
3. 预测
使用训练好的决策树回归模型对测试集advertising_test进行预测,得到预测结果
4.构建评估器
(1)构建评估器,指定标签列(销售额)、预测列(prediction)和评价指标为均方根误差(rmse)。均方根误差越接近0,模型性能越好。
(2) 再次构建评估器,但这次使用判定系数R^2作为评价指标, 判定系数越接近1,模型性能越好 。
5. 模型应用
使用训练好的决策树回归模型对新的数据集newData2进行预测,得到预测结果 。需要注意的是,newData2数据在上一节已经做了向量化处理。
# ---------决策树回归模型DecisionTreeRegressor----------------
print("\n\n---------------决策树模型------------------\n")
dtr = DecisionTreeRegressor(labelCol='销售额',
featuresCol='向量化后特征') # 1.构建决策树回归模型
dtrModel = dtr.fit(advertising_train) # 2.训练模型,得到决策树回归模型
dtr_predictions = dtrModel.transform(advertising_test) # 3.预测 测试集的销售额,用于评估模型
dtr_evaluator = RegressionEvaluator(labelCol='销售额',
predictionCol='prediction',
metricName='rmse') # 4.构建评估器,确定评价指标:均方误差rmse
print("决策树模型均方误差,接近0模型性能最优:", dtr_evaluator.evaluate(dtr_predictions))
dtr_evaluator = RegressionEvaluator(labelCol='销售额',
predictionCol='prediction',
metricName='r2') # 4.构建评估器,确定评价指标:均方误差rmse
print("决策树模型判定系数R^2,接近1模型性能最优:", dtr_evaluator.evaluate(dtr_predictions))
# 决策树模型应用
newDataPred = dtrModel.transform(newData2) # 5.使用决策树回归模型 预测销售额
newDataPred.show()
程序运行结果如下:
四、回归模型应用案例2:小费预测
1.数据集介绍
使用线性回归模型LinearRegression类预测小费。数据集tips共有244个样本,各字段的含义如下:
total_bill:顾客的总账单金额(美元)。这个字段表示顾客在餐厅消费的总金额,是小费金额计算的一个重要参考。
sex:顾客的性别。通常表示为“Male”(男性)或“Female”(女性)。这个字段用于分析性别是否对小费金额有影响。
smoker:顾客是否吸烟。通常表示为“Yes”(是)或“No”(否)。这个字段用于分析吸烟习惯是否与小费金额有关。
day:用餐的星期几。这个字段可能包含“Thur”(周四)、“Fri”(周五)、“Sat”(周六)、“Sun”(周日)等,用于分析星期几是否会影响小费金额。
time:用餐的时间。通常表示为“Lunch”(午餐)或“Dinner”(晚餐)。这个字段用于分析用餐时间是否会影响小费金额。
size:用餐的顾客人数。这个字段表示一桌顾客的数量,用于分析顾客人数是否与小费金额有关。
tip:顾客给出的小费金额(美元)。这是数据集预测的主要目标,即根据其他字段的信息来预测顾客可能会给出的小费金额。
其中,sex,smoker,day,time字段的值为字符型数据,需要转换为数值型数据,即:数值化。tips数据集的部分数据如下图所示:
2. 读取数据
from pyspark import SparkConf
from pyspark.ml.feature import StringIndexer, VectorAssembler, OneHotEncoder, MinMaxScaler
from pyspark.sql import SparkSession, Row
from pyspark.sql.functions import *
from pyspark.ml.classification import *
from pyspark.ml.evaluation import *
from pyspark.ml import Pipeline, tuning
from pyspark.ml.linalg import Vectors
from pyspark.ml.regression import *
conf = SparkConf().setAppName("预测小费").setMaster('spark://192.168.126.10:7077')
sc = SparkContext.getOrCreate(conf)
spark = SparkSession(sc)
# -----------------1.数据获取-------------------
filename = "tips.csv"
tips = spark.read.csv('hdfs://192.168.126.10:9000/data/' + filename, header=True,
inferSchema=True) # 训练集包含标题行,inferSchema=True自动推断数据类型
tips.show(5)
tips.describe().show() # 查看数据集的基本数据信息
tips.printSchema() # 输出数据集的结构
print(f"训练数据集总的记录数:{tips.count()}, 总列数:{len(tips.columns)}")
3.特征工程
3.1 数值化字符串型数据
- 创建标签索引转换器StringIndexer,用于将字符串类型的列转换为索引值。
- 然后用数据集tips 拟合数据,得到数值化转换模型model ;
- 最后使用转换模型model ,将数据集tips中的字符串类型列(sex,smoker,day,time)转为数值型数据,并添加到原数据集tips中。
# 将字符型数据列 数值化
labelIndex = StringIndexer(inputCols=['sex', 'smoker', 'day', 'time'],
outputCols=['indexed_sex', 'indexed_smoker', 'indexed_day', 'indexed_time']) # 构建标签索引转换器
model = labelIndex.fit(tips) # 拟合数据,得到 数值化转换模型
tips = model.transform(tips) # 将tips中的字符型数据数值化,并把转化后的列添加到原数据集tips
print("字符型列的数据数值化后的数据集data:")
tips.show(5)
程序运行结果 如下:
3.2 选择、向量化特征
- 选择数值型特征(total_bill,size)和已数值化的特征(indexed_sex,indexed_smoker,indexed_day,indexed_time)。
- 创建向量转换器data_assembler ,用于将多个特征列合并成一个向量列。
- 使用向量转换器data_assembler,将选定的特征列合并成向量,并添加到数据集中,形成新的一列:raw_features。
- 最后将数据集划分为训练集tips_train和测试集tips_test 。
# 选择特征:选择数值型特征和已数值化的特征
features = ['total_bill', 'size', 'indexed_sex', 'indexed_smoker', 'indexed_day', 'indexed_time']
# 将选择的特征向量化为一列
data_assembler = VectorAssembler(inputCols=features, outputCol='raw_features') # 实例化 向量转换器,用于将多个特征列合并成一个向量列
tips = data_assembler.transform(tips) # 将选定的特征列合并成向量,并添加到数据集中,形成新的一列:raw_features
tips.show(5)
tips_train, tips_test = tips.randomSplit([0.7, 0.3], seed=3)
程序运行结果如下:
4.创建模型:线性回归模型LinearRegression
4.1 创建模型
- 创建线性回归模型,指定目标列、特征列和正则化参数。
- 使用 训练数据集 训练模型,得到训练好的模型lrModel 。
- 使用训练好的模型lrModel 对测试集tips_test进行预测,结果自动生成预测值列’prediction’。
# ---------------5.构建模型:线性回归模型LinearRegression-----------------------
lr = LinearRegression(labelCol='tip', featuresCol='raw_features', regParam=0.1) # 创建线性回归模型,指定目标列、特征列和正则化参数
lrModel = lr.fit(tips_train) # 使用 训练数据集 训练模型
lr_pred = lrModel.transform(tips_test) # 使用训练好的模型对测试集进行预测,结果将包含预测值列'prediction'
lr_pred.show(5)
4.2 模型评估
- 创建模型评估器,指定真实标签列名为’tip’,预测结果列名为’prediction’,使用RMSE作为评估指标。
- 输出模型的RMSE值,值越小表示模型性能越好。
- 再次创建评估器,确定评估指标为r^2。
# 模型评估
lr_evaluator = RegressionEvaluator(labelCol='tip', # 指定真实标签列名为'tip'
predictionCol='prediction', # 指定预测结果列名为'prediction'
metricName='rmse') # 使用RMSE作为评估指标
print("线性回归模型的均方误差,接近0模型性能最优:", lr_evaluator.evaluate(lr_pred)) # 输出模型的RMSE值,值越小表示模型性能越好
lr_evaluator = RegressionEvaluator(labelCol='tip', # 构建评估器,确定评估指标r^2
predictionCol='prediction',
metricName='r2')
print("线性回归模型的判定系数R^2,接近1模型性能最优:", lr_evaluator.evaluate(lr_pred))
4.3 模型应用
-
获取待预测数据集tips_pred,重新命名为newData。数据集tips_pred没有目标列,如下图所示。
-
使用前面的数值化转换模型model,将newData中的字符型数据数值化。
-
使用前面创建的向量转换器data_assembler,将特征转换为一列向量。
-
使用训练好的 线性回归模型 lrModel,预测新数据集newData的小费。
# ---------模型应用----------
filename = "tips_pred.csv"
newData = spark.read.csv('hdfs://192.168.126.10:9000/data/' + filename, header=True,
inferSchema=True) # 获取待预测数据
newData = model.transform(newData) # 使用前面的数值化转换模型model,将newData中的字符型数据数值化
newData = data_assembler.transform(newData) # 向量转换器data_assembler,将特征转换为一列向量
newData_pred = lrModel.transform(newData) # 使用训练好的 线性回归模型 lrModel,预测新数据集newData的小费
newData_pred.show()
预测结果(小费)如下:
5.其他回归模型的应用(随机森林树回归模型:RandomForestRegressor)
使用前面导入并且已经处理好的待预测数据newData,编程步骤如下:
- 创建随机森林回归模型实例。
- 训练随机森林回归模型。
- 使用训练好的模型进行预测 测试集,用于模型评估。
- 构建评估器,确定评估指标,评估模型。
- 使用训练好的 随机森林树回归模型 rfrModel,预测新数据集newData的小费
# -----------------随机森林树回归模型:RandomForestRegressor--------------
rfr = RandomForestRegressor(labelCol='tip', featuresCol='raw_features') # 创建随机森林回归模型实例
rfrModel = rfr.fit(tips_train) # 训练随机森林回归模型
rfr_pred = rfrModel.transform(tips_test) # 使用训练好的模型进行预测 测试集,用于模型评估
# 模型评估
rfr_evaluator = RegressionEvaluator(labelCol='tip', # 构建评估器,确定评估指标rmse
predictionCol='prediction',
metricName='rmse')
print("随机森林树回归模型的均方误差,接近0模型性能最优:", rfr_evaluator.evaluate(rfr_pred))
rfr_evaluator = RegressionEvaluator(labelCol='tip', # 构建评估器,确定评估指标r^2
predictionCol='prediction',
metricName='r2')
print("随机森林树回归模型的判定系数R^2,接近1模型性能最优:", rfr_evaluator.evaluate(rfr_pred))
# -----模型应用-----
newData_pred = rfrModel.transform(newData) # 使用训练好的 随机森林树回归模型 rfrModel,预测新数据集newData的小费
newData_pred.show()
运行结果如下:
参考资料:
1.pyspark学生成绩分析与预测(上):https://blog.csdn.net/weixin_52563520/article/details/137675514
2.https://blog.csdn.net/weixin_52563520/article/details/139126270?spm=1001.2014.3001.5502
3.https://blog.csdn.net/weixin_52563520/article/details/135358767?spm=1001.2014.3001.5502
4.spark学习回归理论和实战房价预测:https://blog.csdn.net/qq_35394891/article/details/83184779
5.基于pyspark的波士顿房价预测案例:https://blog.csdn.net/weixin_46474921/article/details/121780705
6.戴刚,张良均. PySpark大数据分析与应用. 人民邮电出版社,2024.
7.汪明. PySpark实战. 清华大学出版社,2022