Введение
В этом практическом занятии мы научимся использовать 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 позволил нам обрабатывать разные типы признаков в одной линейке.