Примечание
Перейти в конец чтобы скачать полный пример кода или запустить этот пример в браузере через JupyterLite или Binder.
Трансформер столбцов с разнородными источниками данных#
Наборы данных часто могут содержать компоненты, требующие разных конвейеров извлечения и обработки признаков. Этот сценарий может возникнуть, когда:
ваш набор данных состоит из разнородных типов данных (например, растровых изображений и текстовых подписей),
ваш набор данных хранится в
pandas.DataFrameи разные столбцы требуют разных конвейеров обработки.
Этот пример демонстрирует, как использовать
ColumnTransformer на наборе данных, содержащем различные типы признаков. Выбор признаков не особенно полезен, но служит для иллюстрации техники.
# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause
import numpy as np
from sklearn.compose import ColumnTransformer
from sklearn.datasets import fetch_20newsgroups
from sklearn.decomposition import PCA
from sklearn.feature_extraction import DictVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import classification_report
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import FunctionTransformer
from sklearn.svm import LinearSVC
набор данных 20 новостных групп#
Мы будем использовать набор данных 20 новостных групп, который включает сообщения из новостных групп по 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,
)
Каждый признак включает метаинформацию о посте, такую как тема и тело новостного поста.
print(X_train[0])
From: mccall@mksol.dseg.ti.com (fred j mccall 575-3539)
Subject: Re: Metric vs English
Article-I.D.: mksol.1993Apr6.131900.8407
Organization: Texas Instruments Inc
Lines: 31
American, perhaps, but nothing military about it. I learned (mostly)
slugs when we talked English units in high school physics and while
the teacher was an ex-Navy fighter jock the book certainly wasn't
produced by the military.
[Poundals were just too flinking small and made the math come out
funny; sort of the same reason proponents of SI give for using that.]
--
"Insisting on perfect safety is for people who don't have the balls to live
in the real world." -- Mary Shafer, NASA Ames Dryden
Создание преобразователей#
Сначала нам нужен преобразователь, который извлекает тему и тело каждого сообщения. Поскольку это статическое преобразование (не требует информации о состоянии из обучающих данных), мы можем определить функцию, выполняющую преобразование данных, а затем использовать
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)
Конвейер классификации#
Приведенный ниже конвейер извлекает тему и тело из каждого сообщения с помощью
SubjectBodyExtractor, создавая массив размерности (n_samples, 2). Этот массив затем используется для вычисления стандартных признаков мешка слов для темы и тела, а также длины текста и количества предложений в теле, используя
ColumnTransformerМы объединяем их с весами, затем обучаем классификатор на объединенном наборе признаков.
pipeline = Pipeline(
[
# Extract subject & body
("subjectbody", subject_body_transformer),
# Use ColumnTransformer to combine the subject and body features
(
"union",
ColumnTransformer(
[
# bag-of-words for subject (col 0)
("subject", TfidfVectorizer(min_df=50), 0),
# bag-of-words with decomposition for body (col 1)
(
"body_bow",
Pipeline(
[
("tfidf", TfidfVectorizer()),
("best", PCA(n_components=50, svd_solver="arpack")),
]
),
1,
),
# Pipeline for pulling text stats from post's body
(
"body_stats",
Pipeline(
[
(
"stats",
text_stats_transformer,
), # returns a list of dicts
(
"vect",
DictVectorizer(),
), # list of dicts -> feature matrix
]
),
1,
),
],
# weight above ColumnTransformer features
transformer_weights={
"subject": 0.8,
"body_bow": 0.5,
"body_stats": 1.0,
},
),
),
# Use an SVC classifier on the combined features
("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)))
[Pipeline] ....... (step 1 of 3) Processing subjectbody, total= 0.0s
[Pipeline] ............. (step 2 of 3) Processing union, total= 0.4s
[Pipeline] ............... (step 3 of 3) Processing svc, total= 0.0s
Classification report:
precision recall f1-score support
0 0.84 0.87 0.86 396
1 0.87 0.84 0.85 394
accuracy 0.86 790
macro avg 0.86 0.86 0.86 790
weighted avg 0.86 0.86 0.86 790
Общее время выполнения скрипта: (0 минут 2.460 секунд)
Связанные примеры
Классификация текстовых документов с использованием разреженных признаков
Бикластеризация документов с помощью алгоритма спектральной совместной кластеризации