Monday, May 2, 2022

How to Get Feature names from Any Sklearn Pipeline

 Мы собираемся рассматривать Pipeline как дерево. Каждый слой может иметь произвольное количество FeatureUnion, но в конце концов все они будут складываться в один вектор признаков. Есть примерно три случая, которые следует учитывать при обходе. Первый — это базовый случай, когда мы находимся в реальном преобразователе или классификаторе, который будет генерировать наши функции. Во-вторых, если мы находимся в Pipeline. Третий и последний случай — это когда мы находимся внутри FeatureUnion. Давайте поговорим об этом немного подробнее.

============================

Case 1: Featurization Step

===========================

Здесь мы хотим написать функцию, которая с учетом какого-либо функционализатора будет возвращать имена функций. Это базовый случай в нашей DFS. В Sklearn есть несколько разных вещей, которые можно использовать для создания функций. Некоторыми примерами являются методы кластеризации, методы уменьшения размерности, традиционные классификаторы и препроцессоры, и это лишь некоторые из них. Каждый из них позволяет вам получить доступ к именам функций по-разному. Например, препроцессор текста TfidfVectorizer реализует метод get_feature_names, которыый приведен ниже. Однако , большинство методов кластеризации не имеют именованных функций, они представляют собой произвольные кластеры, но имеют фиксированное количество кластеров. Напишем вспомогательную функцию, которая с учетом метода характеристики Sklearn будет возвращать список функций.

=============================

def extract_feature_names(model, name) -> list[str]

=============================

Здесь мы попытаемся перечислить ряд потенциальных случаев, которые могут произойти внутри Sklearn. Мы используем hasattr, чтобы проверить, имеет ли предоставленная модель заданный атрибут, и если да, то мы вызываем его, чтобы получить имена функций. Если метод чем-то похож на кластеризацию и не включает фактические именованные функции, мы создаем наши собственные имена функций, используя предоставленное имя. Например, предположим, что мы применяем этот метод к PCA с двумя компонентами, и мы назвали шаг pca, тогда возвращаемые имена функций будут [pca_0, pca_1].

Давайте пройдем через это вместе. Эта функция займет три вещи. Первая — это модель, которую мы хотим проанализировать. Эта модель должна быть Pipeline. Второй — это список всех именованных шагов характеристики, которые мы хотим извлечь. В нашем последнем примере это были биграммы и отобранные вручную. Это названия отдельных шагов, которые мы использовали в нашей модели. Последний параметр — это текущее имя, на которое мы смотрим. Это необходимо для рекурсии и не имеет значения при первом проходе.

В этом примере мы создаем три написанных от руки средства описания правил, а также подконвейер, который выполняет несколько шагов и приводит к уменьшению размерности функций. Мы можем получить все имена функций из этого конвейера, используя одну строку!


(.env) [boris@fedora35server PIPELINE]$ cat GetFeatureNames.py

from sklearn.pipeline import FeatureUnion, Pipeline

import warnings

warnings.simplefilter(action='ignore', category=FutureWarning)

# Featurization Step

def extract_feature_names(model, name) -> list[str]:

    if hasattr(model, "get_feature_names"):

        return model.get_feature_names()

    elif hasattr(model, "n_clusters"):

        return [f"{name}_{x}" for x in range(model.n_clusters)]

    elif hasattr(model, "n_components"):

        return [f"{name}_{x}" for x in range(model.n_components)]

    elif hasattr(model, "components_"):

        n_components = model.components_.shape[0]

        return [f"{name}_{x}" for x in range(n_components)]

    elif hasattr(model, "classes_"):

        return classes_

    else:

        return [name]


# Implement the DFS.


def get_feature_names(model, names: list[str], name: str) -> list[str]:

    """Thie method extracts the feature names in order from a Sklearn Pipeline

    

    This method only works with composed Pipelines and FeatureUnions.  It will

    pull out all names using DFS from a model.

    

    Args:

        model: The model we are interested in

        names: The list of names of final featurizaiton steps

        name: The current name of the step we want to evaluate.

    Returns:

        feature_names: The list of feature names extracted from the pipeline.

    """

    # Check if the name is one of our feature steps.  This is the base case.

    if name in names:

        # If it has the named_steps atribute it's a pipeline and we need to access the features

        if hasattr(model, "named_steps"):

            return extract_feature_names(model.named_steps[name], name)

        # Otherwise get the feature directly

        else:

            return extract_feature_names(model, name)

    elif type(model) is Pipeline:

        feature_names = []

        for name in model.named_steps.keys():

            feature_names += get_feature_names(model.named_steps[name], names, name)

        return feature_names

    elif type(model) is FeatureUnion:

        feature_names= []

        for name, new_model in model.transformer_list:

            feature_names += get_feature_names(new_model, names, name)

        return feature_names

    # If it is none of the above do not add it.

    else:

        return []

# get the feature names in the correct order

from sklearn.decomposition import TruncatedSVD

from sklearn import svm

from sklearn.feature_extraction.text import CountVectorizer

from sklearn.feature_extraction.text import TfidfTransformer

from sklearn.feature_extraction.text import TfidfVectorizer

from sklearn import metrics


classifier = svm.LinearSVC(C=1.0, class_weight="balanced")

vocab = {"worst": 0, "awful": 1, "waste": 2,

         "boring": 3, "excellent": 4}

model = Pipeline([

    ("union", FeatureUnion(transformer_list=[

        ("h1", TfidfVectorizer(vocabulary={"worst": 0})),

        ("h2", TfidfVectorizer(vocabulary={"best": 0})),

        ("h3", TfidfVectorizer(vocabulary={"awful": 0})),

        ("tfidf_cls", Pipeline([

            ("vectorizer", CountVectorizer()),

            ("transformer", TfidfTransformer()),

            ("tsvd", TruncatedSVD(n_components=2))

        ]

        ))

    ])

     ),

    ("classifier", classifier),

])

print(get_feature_names(model, ["h1", "h2", "h3", "tsvd"], None))




















































REFERENCES




No comments:

Post a Comment