#python #machine-learning #scikit-learn #multilabel-classification #scikit-multilearn
#python #машинное обучение #scikit-учиться #мультиметка-классификация #scikit-мультиобучение
Вопрос:
Я пытаюсь классифицировать текст по нескольким меткам, и это работает хорошо, но поскольку я хочу рассмотреть прогнозируемые метки ниже порога .5, он изменился predict()
на predict_proba()
, чтобы получить все вероятности меток и выбрать значения, основанные на разных пороговых значениях, но я не могу преобразовать значение двоичных вероятностей каждой метки в фактическая текстовая метка. Вот воспроизводимый код:
import numpy as np
from sklearn.pipeline import Pipeline
from sklearn.svm import LinearSVC
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.multiclass import OneVsRestClassifier
from sklearn.preprocessing import MultiLabelBinarizer
X_train = np.array(["new york is a hell of a town",
"new york was originally dutch",
"the big apple is great",
"new york is also called the big apple",
"nyc is nice",
"people abbreviate new york city as nyc",
"the capital of great britain is london",
"london is in the uk",
"london is in england",
"london is in great britain",
"it rains a lot in london",
"london hosts the british museum",
"new york is great and so is london",
"i like london better than new york"])
y_train_text = [["new york"],["new york"],["new york"],["new york"],["new york"],
["new york"],["london"],["london"],["london"],["london"],
["london"],["london"],["new york","london"],["new york","london"]]
X_test = np.array(['nice day in nyc',
'welcome to london',
'london is rainy',
'it is raining in britian',
'it is raining in britian and the big apple',
'it is raining in britian and nyc',
'hello welcome to new york. enjoy it here and london too'])
target_names = ['New York', 'London']
lb = MultiLabelBinarizer()
Y = lb.fit_transform(y_train_text)
classifier = Pipeline([
('tfidf', TfidfVectorizer()),
('clf', OneVsRestClassifier(LinearSVC()))])
classifier.fit(X_train, Y)
predicted = classifier.predict_proba(X_test)
Это дает мне значения вероятности меток для каждого значения X_test
Теперь, когда я попытался lb.inverse_transform(predicted[0])
получить фактические метки first X_test, это не сработало.
Любая помощь, ребята, что я делаю неправильно и как получить желаемые результаты.
Примечание: Приведенное выше — фиктивные данные, но у меня есть 500 labels
данные, которые могут быть у каждого конкретного текста not more than 5 labels
.
Ответ №1:
Я попытался получить это, получив index
из multilabel classes
и predicted probalities
и сопоставив их, чтобы получить фактические метки, поскольку в sklearn не было прямого метода.
Вот как я это сделал.
multilabel = MultiLabelBinarizer()
y = multilabel.fit_transform('target_labels')
predicted_list = classifier.predict_proba(X_test)
def get_labels(predicted_list):
mlb =[(i1,c1)for i1, c1 in enumerate(multilabel.classes_)]
temp_list = sorted([(i,c) for i,c in enumerate(list(predicted_list))],key = lambda x: x[1], reverse=True)
tag_list = [item1 for item1 in temp_list if item1[1]>=0.35] # here 0.35 is the threshold i choose
tags = [item[1] for item2 in tag_list[:5] for item in mlb if item2[0] == item[0] ] # here I choose to get top 5 labels only if there are more than that
return tags
get_labels(predicted_list[0])
>> ['New York']