随机森林回归树官方例子小结

这个例子只是对官方的决策树的几个例子进行解释,重点在于理解特征处理前的fit操作

from pyspark import SparkConf
from pyspark.ml.feature import VectorIndexer
from pyspark.sql import SparkSession
import traceback
from pyspark.sql.types import *
from pyspark.sql.functions import *
from pyspark.ml.regression import IsotonicRegression
from pyspark.ml import Pipeline
from pyspark.ml.regression import GBTRegressor
from pyspark.ml.feature import VectorIndexer
from pyspark.ml.evaluation import RegressionEvaluator

appname = "test"  # 任务名称
master = "local"  # 单机模式设置
'''
local: 所有计算都运行在一个线程当中,没有任何并行计算,通常我们在本机执行一些测试代码,或者练手,就用这种模式。
local[K]: 指定使用几个线程来运行计算,比如local[4]就是运行4个worker线程。通常我们的cpu有几个core,就指定几个线程,最大化利用cpu的计算能力
local[*]: 这种模式直接帮你按照cpu最多cores来设置线程数了。
'''
# spark_driver_host = "10.0.0.248"

try:
    # conf = SparkConf().setAppName(appname).setMaster(master).set("spark.driver.host", spark_driver_host) # 集群

    from pyspark.sql import SparkSession
    from pyspark.sql import functions as F
    from pyspark.sql.functions import udf
    from pyspark.sql.types import *

    spark = SparkSession.builder.appName('gbt').master('local').getOrCreate()

    # 读取数据
    datapath = '''D://spark/spark/spark-2.3.0-bin-hadoop2.7/''';
    data = spark.read.format("libsvm")\
        .load(datapath + "data/mllib/sample_libsvm_data.txt")

    # 把特征中的离散值数量大于4的认为是连续特征,小于4的认为是离散特征,这里最大的疑惑是为何提前进行fit操作,而不是等到pineline的时候在进行?后面解释
    featureIndexer =\
        VectorIndexer(inputCol="features", outputCol="indexedFeatures", maxCategories=4).fit(data)

    # 这里只是看一下具体的数据
    featureData = featureIndexer.transform(data)
    featureData.select('*').show(5, False)

    # 拆分训练和测试数据
    (trainingData, testData) = data.randomSplit([0.7, 0.3])

    # 训练一颗gbt回归树,回归树的数量是10颗
    gbt = GBTRegressor(featuresCol="indexedFeatures", maxIter=10)

    # 把特征处理和回归树组成一个pineline
    pipeline = Pipeline(stages=[featureIndexer, gbt])

    # 使用pineline训练一个模型
    model = pipeline.fit(trainingData)

    # 使用模型对训练数据进行预测
    trainPredictions = model.transform(trainingData)
    # 使用模型对测试数据进行预测
    testPredictions = model.transform(testData)
    # 查看一下预测的结果
    trainPredictions.select("prediction", "label", "features").show(5, False)

    #使用回归评估模型评估预测的结果
    evaluator = RegressionEvaluator(
        labelCol="label", predictionCol="prediction", metricName="rmse")
    #训练误差
    trainrmse = evaluator.evaluate(trainPredictions)
    print("Root Mean Squared Error (RMSE) on trainPredictions data = %g" % trainrmse)
    #测试误差
    testrmse = evaluator.evaluate(testPredictions)
    print("Root Mean Squared Error (RMSE) on trainPredictions data = %g" % testrmse)

    #此处可以对比训练误差和测试误差,如果两者相差很大,那么表明发生了过拟合现象,需要减少树的颗树或者减少每颗树的高度


    #输出训练过程中使用的回归树的具体参数
    gbtModel = model.stages[1]
    print(gbtModel)

    spark.stop()
    print('计算成功!')
except:
    traceback.print_exc()  # 返回出错信息
    print('连接出错!')

代码里面有了一些详细的注释,值得注意的是梯度提升树每次训练出来的模型不一定都是一样的,也就是每次训练的结果有差异,这里其实最想解释的是indexfeature的提前fit操作的作用是什么,其实按照我们正常的理解,特征的各种归一化等的前置出来只需要一个evaculator评估器就可以了。不需要调用fit操作变成转换器transformer,因为pineline是可以处理评估器和转换器的,那么为什么这里需要提前调用fit操作转成transformer再放到pineline中呢,根本原因是VectorIndexer需要提前知道到底某一列都要哪些特征值,如果不这样做的话,后面训练的时候他遇到了没见过的特征值,比如对某个特征来说本来他fit的时候只遇到了3个离散特征值,所以他认为这是一个离散的特征,但是实际上等他时间训练数据的时候,训练数据中出现了超过4个的离散特征值,这时候就有问题了。因为这个特征其实属于连续特征,而不是一开始这个特征处理器以为的离散特征,所以就会报错,所以这里提前fit的目的是为了给特征处理器VectorIndexer提前认识所有的特征值,防止后面训练数据或者实际用来预测数据的时候遇到他没有见过的特征,这样就会导致程序出错.

参考文献:
https://blog.csdn.net/w28971023/article/details/8240756
https://blog.csdn.net/qq_34531825/article/details/52366265?spm=1001.2101.3001.6650.7&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-7.pc_relevant_antiscanv2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-7.pc_relevant_antiscanv2&utm_relevant_index=11
https://blog.csdn.net/woniu201411/article/details/83114226

你可能感兴趣的:(python机器学习,回归,随机森林,spark)