PySpark ML特征变换,调用拟合/变换方法两次或覆盖它?

时间:2017-06-05 18:16:54

标签: pyspark apache-spark-mllib apache-spark-ml

我们可以使用Spark-ML库中提供的各种预处理类。

from pyspark.ml.feature import StringIndexer, VectorIndexer,VectorAssembler

labelIndexer = StringIndexer(inputCol = label_name, outputCol="indexedLabel")
string_feature_indexers = [
   StringIndexer(inputCol=x, outputCol="int_{0}".format(x))
   for x in char_col_toUse_names
]
assembler = VectorAssembler(inputCols=[col for col in all_columns], outputCol="features")    
featureIndexer = VectorIndexer(inputCol="features", outputCol="indexedFeatures", maxCategories=100)
rf = RandomForestClassifier(labelCol="indexedLabel", featuresCol="indexedFeatures", numTrees=1)
pipeline = Pipeline(stages=[labelIndexer] + string_feature_indexers + [assembler, featureIndexer, rf])

model = pipeline.fit(trainingData)
predictions = model.transform(testData)

现在,当我们在管道上调用fit时,上面使用的所有变换的拟合也被调用,并且类似于变换。我是否正确地假设这个?

但是对于所有这些变换,我们还可以在将fit/ transform函数添加到管道之前调用它们as give here

上面代码的内容类似,如下所示,

labelIndexer = StringIndexer(inputCol = label_name, outputCol="indexedLabel").fit(data)
string_feature_indexers = [
   StringIndexer(inputCol=x, outputCol="int_{0}".format(x)).fit(data)
   for x in char_col_toUse_names
]
assembler = VectorAssembler(inputCols=[col for col in all_columns], outputCol="features")
assembler.transform(data)    
featureIndexer = VectorIndexer(inputCol="features", outputCol="indexedFeatures", maxCategories=100).fit(data)
rf = RandomForestClassifier(labelCol="indexedLabel", featuresCol="indexedFeatures", numTrees=1)
pipeline = Pipeline(stages=[labelIndexer] + string_feature_indexers + [assembler, featureIndexer, rf])

model = pipeline.fit(trainingData)
predictions = model.transform(testData)

现在我怀疑,pipeline.fit无论如何会调用所有这些变换的拟合方法,那么我们需要在手前调用它? 如果在两个地方调用拟合,哪个获得偏好?

注意:上面的代码只是为讨论/怀疑创建的,并不代表正确的执行代码。

1 个答案:

答案 0 :(得分:2)

您正在混淆变形金刚与估算器,这是两个可能的管道阶段。

Transformer没有fit方法,只有transform方法。同样,估算工具没有transform方法,而是使用fit方法生成变换器。

在管道定义中,您可以将变形金刚和估算器作为阶段。当您调用管道fit方法时,它仅在Estimators上调用fit方法来生成变换器,输出是PipelineModel,它只是变形金刚的集合。

例如,如果您的管道具有以下阶段:[transformerA, estimatorB, transformerC],则管道fit(dataset)调用将执行以下操作:

  1. dataset = transformerA.transform(dataset) //懒人电话
  2. transformerB = estimatorB.fit(dataset) //它将执行先前的延迟调用
  3. dataset = transformerB.transform(dataset) //懒惰的电话,从未执行
  4. dataset = transformerC.transform(dataset) //懒惰的电话,从未执行
  5. 未返回已转换的dataset,因为它仅用于从估算器生成变换器。然后,此调用将生成具有以下变换器的PipelineModel:[transformerA, transformerB, transformerC]。您可以将整个PipelineModel视为单个Transformer。

    如果您的Pipeline仅包含Transformers,则管道fit调用将仅检查架构一致性,因为这些转换是惰性求值的。 例如,如果你有这样的东西:

    model = EstimatorA.fit(dataset)
    pipeline = Pipeline(stages=[model])
    pipelineModel = pipeline.fit(dataset)
    

    model是一个变形金刚,所以当你pipeline.fit(dataset)执行pipelineModel时,你不会再进行另一次拟合,事实上dataset的创建应该非常快,因为你不会执行对fit的任何计算(估算器中只有tv4可以触发执行)。

    我希望这会有所帮助。

相关问题