Scikit-Learn Column Transformer

Beginner

This tutorial is from open-source community. Access the source code

Введение

В этом практическом занятии мы научимся использовать ColumnTransformer из Scikit-Learn на наборе данных, содержащем разные типы признаков. Эта техника полезна, когда набор данных содержит компоненты, требующие различных конвейеров извлечения и обработки признаков.

Советы по использованию ВМ

После запуска виртуальной машины кликните в левом верхнем углу, чтобы переключиться на вкладку Ноутбук и получить доступ к Jupyter Notebook для практики.

Иногда вам может потребоваться подождать несколько секунд, пока Jupyter Notebook не загрузится полностью. Валидация операций не может быть автоматизирована из-за ограничений Jupyter Notebook.

Если вы сталкиваетесь с проблемами во время обучения, не стесняйтесь обращаться к Labby. Оставьте отзыв после занятия, и мы оперативно решим проблему для вас.

Набор данных

Мы будем использовать набор данных 20 newsgroups, который состоит из сообщений из новостных групп по 20 темам. Набор данных разделен на обучающую и тестовую подмножества в зависимости от сообщений, опубликованных до и после определенной даты. Мы будем использовать только сообщения из 2 категорий, чтобы ускорить время выполнения.

categories = ["sci.med", "sci.space"]
X_train, y_train = fetch_20newsgroups(
    random_state=1,
    subset="train",
    categories=categories,
    remove=("footers", "quotes"),
    return_X_y=True,
)
X_test, y_test = fetch_20newsgroups(
    random_state=1,
    subset="test",
    categories=categories,
    remove=("footers", "quotes"),
    return_X_y=True,
)

Создание трансформеров

Мы создадим трансформеры, которые извлекают признаки из набора данных. Мы определим две функции, которые выполняют преобразование данных, а затем используем FunctionTransformer из Scikit-Learn для создания трансформеров.

def subject_body_extractor(posts):
    ## construct object dtype array with two columns
    ## first column = 'subject' and second column = 'body'
    features = np.empty(shape=(len(posts), 2), dtype=object)
    for i, text in enumerate(posts):
        ## temporary variable `_` stores '\n\n'
        headers, _, body = text.partition("\n\n")
        ## store body text in second column
        features[i, 1] = body

        prefix = "Subject:"
        sub = ""
        ## save text after 'Subject:' in first column
        for line in headers.split("\n"):
            if line.startswith(prefix):
                sub = line[len(prefix) :]
                break
        features[i, 0] = sub

    return features

subject_body_transformer = FunctionTransformer(subject_body_extractor)

def text_stats(posts):
    return [{"length": len(text), "num_sentences": text.count(".")} for text in posts]

text_stats_transformer = FunctionTransformer(text_stats)

Линейка классификации

Мы создадим линейку, которая извлекает признаки из набора данных, объединяет их и обучает классификатор на объединенном наборе признаков. Для этого мы используем Pipeline и ColumnTransformer из Scikit-Learn.

pipeline = Pipeline(
    [
        ## Извлечение темы и тела
        ("subjectbody", subject_body_transformer),
        ## Использование ColumnTransformer для объединения признаков темы и тела
        (
            "union",
            ColumnTransformer(
                [
                    ## мешок слов для темы (колонка 0)
                    ("subject", TfidfVectorizer(min_df=50), 0),
                    ## мешок слов с декомпозицией для тела (колонка 1)
                    (
                        "body_bow",
                        Pipeline(
                            [
                                ("tfidf", TfidfVectorizer()),
                                ("best", TruncatedSVD(n_components=50)),
                            ]
                        ),
                        1,
                    ),
                    ## Линейка для извлечения статистик текста из тела поста
                    (
                        "body_stats",
                        Pipeline(
                            [
                                (
                                    "stats",
                                    text_stats_transformer,
                                ),  ## возвращает список словарей
                                (
                                    "vect",
                                    DictVectorizer(),
                                ),  ## список словарей -> матрица признаков
                            ]
                        ),
                        1,
                    ),
                ],
                ## веса для признаков выше ColumnTransformer
                transformer_weights={
                    "subject": 0.8,
                    "body_bow": 0.5,
                    "body_stats": 1.0,
                },
            ),
        ),
        ## Использование классификатора SVC на объединенных признаках
        ("svc", LinearSVC(dual=False)),
    ],
    verbose=True,
)

Обучение и тестирование

Мы обучим нашу линейку на тренировочных данных и используем ее для предсказания тем для X_test. Затем выводятся метрики качества нашей линейки.

pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
print("Classification report:\n\n{}".format(classification_report(y_test, y_pred)))

Резюме

В этом практическом занятии мы узнали, как использовать ColumnTransformer из Scikit-Learn на наборе данных, содержащем разные типы признаков. Мы создали трансформеры, которые извлекали признаки из набора данных, и использовали их для обучения классификатора на объединенном наборе признаков. ColumnTransformer позволил нам обрабатывать разные типы признаков в одной линейке.