복붙노트

[PYTHON] VectorAssembler의 출력에서 ​​Spark ML의 열 이름으로 다시 기능을 매핑하는 방법은 무엇입니까?

PYTHON

VectorAssembler의 출력에서 ​​Spark ML의 열 이름으로 다시 기능을 매핑하는 방법은 무엇입니까?

저는 PySpark에서 선형 회귀 분석을 시도하고 있습니다. 저는 데이터 세트의 각 열에 대해 계수, P- 값 및 t- 값과 같은 요약 통계를 포함하는 테이블을 만들고 싶습니다. 그러나 선형 회귀 모델을 학습하기 위해 Spark의 VectorAssembler를 사용하여 피쳐 벡터를 만들어야했습니다. 이제 각 행에 대해 단일 피쳐 벡터와 대상 열이 있습니다. Spark의 내장 회귀 요약 통계에 액세스하려고 할 때 각 통계에 대한 숫자의 원시 목록을 제공하고 어떤 속성이 어떤 값에 해당 하는지를 알 수있는 방법이 없습니다. 수동으로 알아 내기가 실제로 어렵습니다 많은 수의 열. 어떻게 이러한 값을 다시 열 이름에 매핑합니까?

예를 들어, 현재 출력은 다음과 같습니다.

이 숫자는 내가 어떤 속성에 해당하는지 알지 못하면 아무런 의미가 없습니다. 그러나 DataFrame에는 "feature"라는 열만 있습니다.이 열은 희소 한 벡터 행을 포함합니다.

이것은 하나의 핫 엔코딩 된 피쳐가있을 때 더 큰 문제입니다. 하나의 변수에 길이 n의 인코딩이 있으면 n 개의 해당 계수 / p- 값 / t- 값 등을 얻을 것이기 때문입니다.

해결법

  1. ==============================

    1.현재 Spark는 귀하를 위해 그것을 할 수있는 어떤 방법도 제공하지 않으므로 귀하가 직접 만들면됩니다. 데이터가 다음과 같다고 가정 해 보겠습니다.

    현재 Spark는 귀하를 위해 그것을 할 수있는 어떤 방법도 제공하지 않으므로 귀하가 직접 만들면됩니다. 데이터가 다음과 같다고 가정 해 보겠습니다.

    import random
    random.seed(1)
    
    df = sc.parallelize([(
        random.choice([0.0, 1.0]), 
        random.choice(["a", "b", "c"]),
        random.choice(["foo", "bar"]),
        random.randint(0, 100),
        random.random(),
    ) for _ in range(100)]).toDF(["label", "x1", "x2", "x3", "x4"])
    

    다음 파이프 라인을 사용하여 처리됩니다.

    from pyspark.ml.feature import StringIndexer, OneHotEncoder, VectorAssembler
    from pyspark.ml import Pipeline
    from pyspark.ml.regression import LinearRegression
    
    indexers = [
      StringIndexer(inputCol=c, outputCol="{}_idx".format(c)) for c in ["x1", "x2"]]
    encoders = [
        OneHotEncoder(
            inputCol=idx.getOutputCol(),
            outputCol="{0}_enc".format(idx.getOutputCol())) for idx in indexers]
    assembler = VectorAssembler(
        inputCols=[enc.getOutputCol() for enc in encoders] + ["x3", "x4"],
        outputCol="features")
    
    pipeline = Pipeline(
        stages=indexers + encoders + [assembler, LinearRegression()])
    model = pipeline.fit(df)
    

    LinearRegressionModel를 취득합니다.

    lrm = model.stages[-1]
    

    데이터 변환 :

    transformed =  model.transform(df)
    

    ML 속성 추출 및 병합 :

    from itertools import chain
    
    attrs = sorted(
        (attr["idx"], attr["name"]) for attr in (chain(*transformed
            .schema[lrm.summary.featuresCol]
            .metadata["ml_attr"]["attrs"].values())))
    

    출력에 매핑합니다.

    [(name, lrm.summary.pValues[idx]) for idx, name in attrs]
    
    [('x1_idx_enc_a', 0.26400012641279824),
     ('x1_idx_enc_c', 0.06320192217171572),
     ('x2_idx_enc_foo', 0.40447778902400433),
     ('x3', 0.1081883594783335),
     ('x4', 0.4545851609776568)]
    
    [(name, lrm.coefficients[idx]) for idx, name in attrs]
    
    [('x1_idx_enc_a', 0.13874401585637453),
     ('x1_idx_enc_c', 0.23498565469334595),
     ('x2_idx_enc_foo', -0.083558932128022873),
     ('x3', 0.0030186112903237442),
     ('x4', -0.12951394186593695)]
    
  2. ==============================

    2.여기에서 열의 실제 순서를 볼 수 있습니다.

    여기에서 열의 실제 순서를 볼 수 있습니다.

    df.schema["features"].metadata["ml_attr"]["attrs"]
    

    일반적으로 [ "binary"와 [ "numeric"] 두 개의 클래스가있을 것입니다.

    pd.DataFrame(df.schema["features"].metadata["ml_attr"]["attrs"]["binary"]+df.schema["features"].metadata["ml_attr"]["attrs"]["numeric"]).sort_values("idx")
    

    모든 열의 정확한 순서를 제공해야합니다.

  3. ==============================

    3.한 줄 대답은 다음과 같습니다.

    한 줄 대답은 다음과 같습니다.

    [x["name"] for x in sorted(train_downsampled.schema["all_features"].metadata["ml_attr"]["attrs"]["binary"]+
       train_downsampled.schema["all_features"].metadata["ml_attr"]["attrs"]["numeric"], 
       key=lambda x: x["idx"])]
    

    이것의 핵심은 @pratiklodha에 감사드립니다.

  4. from https://stackoverflow.com/questions/42935914/how-to-map-features-from-the-output-of-a-vectorassembler-back-to-the-column-name by cc-by-sa and MIT license