Включение классификации по нескольким меткам с помощью 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].
Надеюсь, ответ вам ясен.