Введение
В этом практическом занятии (лабораторной работе) вы научитесь выполнять полусupervised классификацию текстового набора данных с использованием библиотеки scikit-learn. Полусupervised обучение - это тип машинного обучения, при котором модель обучается на как помеченных, так и непомеченных данных. В этом практическом занятии будет показано, как использовать алгоритмы Self-Training и LabelSpreading для полусupervised классификации текстов. Мы будем использовать набор данных 20 newsgroups для обучения и тестирования наших моделей.
Советы по виртуальной машине (VM)
После запуска виртуальной машины нажмите в левом верхнем углу, чтобы переключиться на вкладку Notebook и получить доступ к Jupyter Notebook для практики.
Иногда вам может потребоваться подождать несколько секунд, пока Jupyter Notebook загрузится. Валидация операций не может быть автоматизирована из-за ограничений Jupyter Notebook.
Если у вас возникнут проблемы во время обучения, не стесняйтесь обращаться к Labby. Оставьте отзыв после занятия, и мы оперативно решим проблему для вас.
Загрузка набора данных
Мы будем использовать набор данных 20 newsgroups, который содержит около 18 000 постов из новостных групп по 20 темам. На этом шаге мы загрузим набор данных и выведем основную информацию о нем.
import numpy as np
from sklearn.datasets import fetch_20newsgroups
## Загрузка набора данных с первыми пятью категориями
data = fetch_20newsgroups(
subset="train",
categories=[
"alt.atheism",
"comp.graphics",
"comp.os.ms-windows.misc",
"comp.sys.ibm.pc.hardware",
"comp.sys.mac.hardware",
],
)
## Вывод информации о наборе данных
print("%d documents" % len(data.filenames))
print("%d categories" % len(data.target_names))
Создание конвейера (pipeline) для supervised обучения
На этом шаге мы создадим конвейер (pipeline) для supervised обучения. Конвейер будет состоять из CountVectorizer, который преобразует текстовые данные в матрицу подсчета токенов, TfidfTransformer, который применяет нормализацию частоты термина - обратной частоты документа (term frequency - inverse document frequency) к матрице подсчета, и SGDClassifier, который обучает модель.
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.linear_model import SGDClassifier
from sklearn.pipeline import Pipeline
## Параметры для SGDClassifier
sdg_params = dict(alpha=1e-5, penalty="l2", loss="log_loss")
## Параметры для CountVectorizer
vectorizer_params = dict(ngram_range=(1, 2), min_df=5, max_df=0.8)
## Создание конвейера (pipeline)
pipeline = Pipeline(
[
("vect", CountVectorizer(**vectorizer_params)),
("tfidf", TfidfTransformer()),
("clf", SGDClassifier(**sdg_params)),
]
)
Обучение и оценка supervised модели
На этом шаге мы разделим набор данных на обучающую и тестовую выборки, а затем обучим и оценим supervised модель, созданную на шаге 2.
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score
## Разделение набора данных на обучающую и тестовую выборки
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y)
## Обучение и оценка supervised модели
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
print(
"Micro-averaged F1 score on test set: %0.3f"
% f1_score(y_test, y_pred, average="micro")
)
Создание конвейера (pipeline) для Self-Training
На этом шаге мы создадим конвейер (pipeline) для полусupervised обучения с использованием метода Self-Training. Конвейер будет аналогичен конвейеру для supervised обучения, но вместо SGDClassifier мы будем использовать SelfTrainingClassifier.
from sklearn.semi_supervised import SelfTrainingClassifier
## Создание конвейера (pipeline) для Self-Training
st_pipeline = Pipeline(
[
("vect", CountVectorizer(**vectorizer_params)),
("tfidf", TfidfTransformer()),
("clf", SelfTrainingClassifier(SGDClassifier(**sdg_params), verbose=True)),
]
)
Обучение и оценка модели Self-Training
На этом шаге мы применим метод Self-Training к 20% размеченных данных. Мы случайным образом выберем 20% размеченных данных, обучим модель на этих данных, а затем используем модель для предсказания меток для оставшихся неразмеченных данных.
import numpy as np
## Выбор 20% обучающих данных
y_mask = np.random.rand(len(y_train)) < 0.2
X_20, y_20 = map(
list, zip(*((x, y) for x, y, m in zip(X_train, y_train, y_mask) if m))
)
## Установка невыбранной части данных как неразмеченных
y_train[~y_mask] = -1
## Обучение и оценка конвейера (pipeline) Self-Training
st_pipeline.fit(X_train, y_train)
y_pred = st_pipeline.predict(X_test)
print(
"Micro-averaged F1 score on test set: %0.3f"
% f1_score(y_test, y_pred, average="micro")
)
Создание конвейера (pipeline) для LabelSpreading
На этом шаге мы создадим конвейер (pipeline) для полусupervised обучения с использованием алгоритма LabelSpreading. Конвейер будет аналогичен конвейеру для supervised обучения, но вместо SGDClassifier мы будем использовать алгоритм LabelSpreading.
from sklearn.semi_supervised import LabelSpreading
from sklearn.preprocessing import FunctionTransformer
## Создание конвейера (pipeline) LabelSpreading
ls_pipeline = Pipeline(
[
("vect", CountVectorizer(**vectorizer_params)),
("tfidf", TfidfTransformer()),
("toarray", FunctionTransformer(lambda x: x.toarray())),
("clf", LabelSpreading()),
]
)
Обучение и оценка модели LabelSpreading
На этом шаге мы применим алгоритм LabelSpreading к 20% размеченных данных. Мы случайным образом выберем 20% размеченных данных, обучим модель на этих данных, а затем используем модель для предсказания меток для оставшихся неразмеченных данных.
## Обучение и оценка конвейера (pipeline) LabelSpreading
ls_pipeline.fit(X_train, y_train)
y_pred = ls_pipeline.predict(X_test)
print(
"Micro-averaged F1 score on test set: %0.3f"
% f1_score(y_test, y_pred, average="micro")
)
Резюме
В этом практическом занятии (lab) мы научились выполнять полусupervised классификацию текстового датасета с использованием библиотеки scikit-learn. Мы применили алгоритмы Self-Training и LabelSpreading для обучения и тестирования наших моделей. Полусupervised обучение может быть полезно, когда доступно ограниченное количество размеченных данных, и оно может помочь улучшить производительность модели за счет использования неразмеченных данных.