在pySpark ML中将列名称与模型参数相关

Jef*_*eff 6 python pyspark apache-spark-ml

我正在对具有一个分类自变量的数据使用GLM(在Spark 2.0中使用ML)运行模型。我使用StringIndexer和将该列转换为伪变量OneHotEncoder,然后使用VectorAssembler将其与连续的独立变量组合成稀疏向量的列。

如果我的列名continuous以及categorical其中,所述第一浮体是一列,第二个是表示字符串的列(在这种情况下,8)不同的类别:

string_indexer = StringIndexer(inputCol='categorical', 
                               outputCol='categorical_index')

encoder = OneHotEncoder(inputCol ='categorical_index',
                        outputCol='categorical_vector')

assembler = VectorAssembler(inputCols=['continuous', 'categorical_vector'],
                            outputCol='indep_vars')

pipeline  = Pipeline(stages=string_indexer+encoder+assembler)
model = pipeline.fit(df)
df = model.transform(df)
Run Code Online (Sandbox Code Playgroud)

至此一切正常,我运行模型:

glm = GeneralizedLinearRegression(family='gaussian', 
                                  link='identity',
                                  labelCol='dep_var',
                                  featuresCol='indep_vars')
model = glm.fit(df)
model.params
Run Code Online (Sandbox Code Playgroud)

哪个输出:

DenseVector([8440.0573,3729.449,4388.9042,2879.1802,4613.7646,5163.3233,5186.6189,5513.1392])

很好,因为我可以验证这些系数(通过其他来源)本质上是正确的。但是,我还没有找到一种将这些系数链接到原始列名的好方法,这是我需要做的(我为SO简化了此模型;涉及更多)。

列名称和系数之间的关系被StringIndexer和打破OneHotEncoder。我发现了一种相当慢的方法:

df[['categorical', 'categorical_index']].distinct()
Run Code Online (Sandbox Code Playgroud)

这给了我一个较小的数据框,将字符串名称与数字名称相关联,我认为我可以将其与稀疏向量中的键相关联?但是,当您考虑数据规模时,这非常笨拙且缓慢。

有一个更好的方法吗?

pie*_*ada 5

对于 PySpark,这里是将特征索引映射到特征名称的解决方案:

首先,训练你的模型:

pipeline = Pipeline().setStages([label_stringIdx,assembler,classifier])
model = pipeline.fit(x)
Run Code Online (Sandbox Code Playgroud)

转换您的数据:

df_output = model.transform(x)
Run Code Online (Sandbox Code Playgroud)

提取特征索引和特征名称之间的映射。将数字属性和二进制属性合并到一个列表中。

numeric_metadata = df_output.select("features").schema[0].metadata.get('ml_attr').get('attrs').get('numeric')
binary_metadata = df_output.select("features").schema[0].metadata.get('ml_attr').get('attrs').get('binary')

merge_list = numeric_metadata + binary_metadata 
Run Code Online (Sandbox Code Playgroud)

输出:

[{'name': 'variable_abc', 'idx': 0},
{'name': 'variable_azz', 'idx': 1},
{'name': 'variable_azze', 'idx': 2},
{'name': 'variable_azqs', 'idx': 3},
  ....
Run Code Online (Sandbox Code Playgroud)


Ter*_*ura 0

抱歉,这似乎是一个很晚的答案,也许您可​​能已经弄清楚了,但无论如何。我最近对 ​​String Indexer、OneHotEncoder 和 VectorAssembler 进行了相同的实现,据我所知,以下代码将呈现您正在寻找的内容。

from pyspark.ml import Pipeline
from pyspark.ml.feature import OneHotEncoder, StringIndexer, VectorAssembler

categoricalColumns = ["one_categorical_variable"]
stages = [] # stages in the pipeline


for categoricalCol in categoricalColumns:

# Category Indexing with StringIndexer
stringIndexer = StringIndexer(inputCol=categoricalCol, 
    outputCol=categoricalCol+"Index")

# Using OneHotEncoder to convert categorical variables into binary 
    SparseVectors

encoder = OneHotEncoder(inputCol=stringIndexer.getOutputCol(), 
    outputCol=categoricalCol+"classVec")

# Adding the stages so that they will be run all at once later

stages += [stringIndexer, encoder]

# convert label into label indices using the StringIndexer

label_stringIdx = StringIndexer(inputCol = "Service_Level", outputCol = 
    "label")
stages += [label_stringIdx]

# Transform all features into a vector using VectorAssembler

numericCols = ["continuous_variable"]
assemblerInputs = map(lambda c: c + "classVec", categoricalColumns) + 
    numericCols
assembler = VectorAssembler(inputCols=assemblerInputs, outputCol="features")
stages += [assembler]

# Creating a Pipeline for Training

pipeline = Pipeline(stages=stages)

# Running the feature transformations.
pipelineModel = pipeline.fit(df)
df = pipelineModel.transform(df)
Run Code Online (Sandbox Code Playgroud)