Примечание
Перейти в конец, чтобы скачать полный код примера или запустить этот пример в браузере с помощью 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 Newsgroups
Мы будем использовать набор данных 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,
)
Каждый признак содержит метаинформацию о публикации, например тему и текст сообщения.
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.917 секунды)
Связанные примеры
© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/compose/plot_column_transformer.html