Включение классификации по нескольким меткам с помощью NLTK, scikit-learn и OneVsRestClassifier

Отказ от ответственности: я довольно плохо знаком с AI, Python, NLTK и scikit-learn.

Я пытаюсь обучить классификатор, чтобы классифицировать набор документов на набор меток.

Я использую оболочку NLTK, чтобы поговорить с OneVsRestClassifier от scikit-learn.

training_set = [
    [{"car": True, ...}, "Label 1"],
    [{"car": False, ...}, "Label 2"],
    ...
    [{"car": False, ...}, "Label 1"],
]

ovr = SklearnClassifier(OneVsRestClassifier(MultinomialNB()))
ovr.train(training_set)

Это прекрасно работает с мультиклассовой классификацией, где классификатор пытается классифицировать документы только по меткам. Точность хорошая, но я хочу, чтобы классификатор присвоил документам 0, 1 или более меток. Как я могу это сделать?

К сожалению, я не могу просто инициализировать классификатор, говоря, что он является классификатором с несколькими метками, документация гласит:

Эту стратегию также можно использовать для многоуровневого обучения, где классификатор используется для прогнозирования нескольких меток, например, путем подгонки к двумерной матрице, в которой ячейка [i, j] равна 1, если в выборке i метка j и 0 в противном случае.

Это не совсем понятно для меня, так как я не знаком с этим языком. У меня такое ощущение, что я должен сформировать свой тренировочный набор таким образом, чтобы классификатор понял, что я хочу, чтобы он классифицировал мои данные по нескольким меткам? Если да, то как?

Я попытался предоставить метки в массиве, например так:

training_set = [
    [{"car": True, ...}, ["Label 1"]],
    [{"car": False, ...}, ["Label 2"]],
    ...
    [{"car": False, ...}, ["Label 1"]],
]

Это не сработало, как ожидалось, и подняло:

DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().
  y = column_or_1d(y, warn=True)
One-vs-rest accuracy percent: 0.0

2 ответа

Решение

Я решил эту проблему, избавившись от адаптера NLTK для scikit-learn и импортировав модуль NLTK, чтобы помочь мне преобразовать мою структуру данных в нечто, поддающееся обработке в scikit-learn OneVsRestClassifier.

from nltk import compat
from sklearn.feature_extraction import DictVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.multiclass import OneVsRestClassifier

_vectorizer = DictVectorizer(dtype=float, sparse=True)

def prepare_scikit_x_and_y(labeled_featuresets):
    X, y = list(compat.izip(*labeled_featuresets))
    X = _vectorizer.fit_transform(X)

    set_of_labels = []
    for label in y:
        set_of_labels.append(set(label))

    y = self.mlb.fit_transform(set_of_labels)

    return X, y

def train_classifier(labeled_featuresets):
    X, y = prepare_scikit_x_and_y(labeled_featuresets)
    classifier.fit(X, y)

training_set = [
    [{"car": True, ...}, ["Label 1"]],
    [{"car": False, ...}, ["Label 2"]],
    ...
    [{"car": False, ...}, ["Label 1"]],
]


ovr = OneVsRestClassifier(MultinomialNB())
ovr.train(training_set)

Счастливая фасоль

То, что пытается сказать документация, используйте 2-D матрицу для цели. Таким образом, в основном, ваш тренировочный набор может быть,

training_set = [
    [{"car": True, ...}, [is_label_1, is_label_2, is_label_3]],
    [{"car": False, ...}, [is_label_1, is_label_2, is_label_3]],
    ...
    [{"car": False, ...}, [is_label_1, is_label_2, is_label_3]],
]

Для конкретного образца обучите его нескольким меткам, например, для 1-го образца, если присутствуют метка 1 и метка 3, передайте его как [1, 0, 1].

Надеюсь, ответ вам ясен.

Другие вопросы по тегам