sklearn scikit onevsrestclassifier multilabel learn example python classification scikit-learn

python - onevsrestclassifier - Use scikit-learn para clasificar en múltiples categorías



multilabel sklearn example (5)

Intento usar uno de los métodos de aprendizaje supervisado de scikit-learn para clasificar fragmentos de texto en una o más categorías. La función de predicción de todos los algoritmos que probé solo devuelve una coincidencia.

Por ejemplo, tengo una pieza de texto:

"Theaters in New York compared to those in London"

Y he entrenado el algoritmo para elegir un lugar para cada fragmento de texto que le doy.

En el ejemplo anterior, me gustaría que devuelva New York y London , pero solo devuelve New York .

¿Es posible usar scikit-learn para devolver resultados múltiples? ¿O incluso devolver la etiqueta con la siguiente probabilidad más alta?

Gracias por tu ayuda.

---Actualizar

Intenté usar OneVsRestClassifier pero aún así solo recibo una opción por cada fragmento de texto. Debajo está el código de muestra que estoy usando

y_train = (''New York'',''London'') train_set = ("new york nyc big apple", "london uk great britain") vocab = {''new york'' :0,''nyc'':1,''big apple'':2,''london'' : 3, ''uk'': 4, ''great britain'' : 5} count = CountVectorizer(analyzer=WordNGramAnalyzer(min_n=1, max_n=2),vocabulary=vocab) test_set = (''nice day in nyc'',''london town'',''hello welcome to the big apple. enjoy it here and london too'') X_vectorized = count.transform(train_set).todense() smatrix2 = count.transform(test_set).todense() base_clf = MultinomialNB(alpha=1) clf = OneVsRestClassifier(base_clf).fit(X_vectorized, y_train) Y_pred = clf.predict(smatrix2) print Y_pred

Resultado: [''Nueva York'' ''Londres'' ''Londres'']


Cambie esta línea para que funcione en las nuevas versiones de python

# lb = preprocessing.LabelBinarizer() lb = preprocessing.MultiLabelBinarizer()


EDITAR: Actualizado para Python 3, scikit-learn 0.18.1 usando MultiLabelBinarizer como se sugiere.

También he estado trabajando en esto y realicé una pequeña mejora en la excelente respuesta de mwv que puede ser útil. Toma etiquetas de texto como entrada en lugar de etiquetas binarias y las codifica utilizando MultiLabelBinarizer.

import numpy as np from sklearn.pipeline import Pipeline from sklearn.feature_extraction.text import CountVectorizer from sklearn.svm import LinearSVC from sklearn.feature_extraction.text import TfidfTransformer 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''] mlb = MultiLabelBinarizer() Y = mlb.fit_transform(y_train_text) classifier = Pipeline([ (''vectorizer'', CountVectorizer()), (''tfidf'', TfidfTransformer()), (''clf'', OneVsRestClassifier(LinearSVC()))]) classifier.fit(X_train, Y) predicted = classifier.predict(X_test) all_labels = mlb.inverse_transform(predicted) for item, labels in zip(X_test, all_labels): print(''{0} => {1}''.format(item, '', ''.join(labels)))

Esto me da el siguiente resultado:

nice day in nyc => new york welcome to london => london london is rainy => london it is raining in britian => london it is raining in britian and the big apple => new york it is raining in britian and nyc => london, new york hello welcome to new york. enjoy it here and london too => london, new york


Lo que quiere se llama clasificación multi-etiqueta. Scikits-learn puede hacer eso. Vea aquí: http://scikit-learn.org/dev/modules/multiclass.html .

No estoy seguro de lo que está pasando mal en su ejemplo, mi versión de sklearn aparentemente no tiene WordNGramAnalyzer. ¿Tal vez se trata de usar más ejemplos de entrenamiento o probar un clasificador diferente? Sin embargo, tenga en cuenta que el clasificador de etiquetas múltiples espera que el destino sea una lista de tuplas / listas de etiquetas.

Lo siguiente funciona para mí:

import numpy as np from sklearn.pipeline import Pipeline from sklearn.feature_extraction.text import CountVectorizer from sklearn.svm import LinearSVC from sklearn.feature_extraction.text import TfidfTransformer from sklearn.multiclass import OneVsRestClassifier 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 = [[0],[0],[0],[0],[0],[0],[1],[1],[1],[1],[1],[1],[0,1],[0,1]] X_test = np.array([''nice day in nyc'', ''welcome to london'', ''hello welcome to new york. enjoy it here and london too'']) target_names = [''New York'', ''London''] classifier = Pipeline([ (''vectorizer'', CountVectorizer(min_n=1,max_n=2)), (''tfidf'', TfidfTransformer()), (''clf'', OneVsRestClassifier(LinearSVC()))]) classifier.fit(X_train, y_train) predicted = classifier.predict(X_test) for item, labels in zip(X_test, predicted): print ''%s => %s'' % (item, '', ''.join(target_names[x] for x in labels))

Para mí, esto produce la salida:

nice day in nyc => New York welcome to london => London hello welcome to new york. enjoy it here and london too => New York, London

Espero que esto ayude.


Me topé con esto también, y el problema para mí fue que mi y_Train era una secuencia de cadenas, en lugar de una secuencia de secuencias de String. Aparentemente, OneVsRestClassifier decidirá basándose en el formato de la etiqueta de entrada, ya sea que use multi-clase o multi-etiqueta. Entonces cambia:

y_train = (''New York'',''London'')

a

y_train = ([''New York''],[''London''])

Al parecer, esto desaparecerá en el futuro, ya que se rompe de todas las etiquetas son las mismas: https://github.com/scikit-learn/scikit-learn/pull/1987


Pocos ejemplos de clasificación múltiple son los siguientes:

Ejemplo 1:-

import numpy as np from sklearn.preprocessing import LabelBinarizer encoder = LabelBinarizer() arr2d = np.array([1, 2, 3,4,5,6,7,8,9,10,11,12,13,14,1]) transfomed_label = encoder.fit_transform(arr2d) print(transfomed_label)

La salida es

[[1 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 1 0 0 0 0 0 0 0 0 0 0 0 0] [0 0 1 0 0 0 0 0 0 0 0 0 0 0] [0 0 0 1 0 0 0 0 0 0 0 0 0 0] [0 0 0 0 1 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 1 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 1 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 1 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 1 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 1 0 0 0 0] [0 0 0 0 0 0 0 0 0 0 1 0 0 0] [0 0 0 0 0 0 0 0 0 0 0 1 0 0] [0 0 0 0 0 0 0 0 0 0 0 0 1 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 1] [1 0 0 0 0 0 0 0 0 0 0 0 0 0]]

Ejemplo 2: -

import numpy as np from sklearn.preprocessing import LabelBinarizer encoder = LabelBinarizer() arr2d = np.array([''Leopard'',''Lion'',''Tiger'', ''Lion'']) transfomed_label = encoder.fit_transform(arr2d) print(transfomed_label)

La salida es

[[1 0 0] [0 1 0] [0 0 1] [0 1 0]]