Estoy tratando de 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 un fragmento de texto:
"Theaters in New York compared to those in London"
Y he entrenado el algoritmo para que elija un lugar para cada fragmento de texto que le proporcione.
En el ejemplo anterior, me gustaría que regresara New York
y London
, pero solo regresa New York
.
¿Es posible usar scikit-learn para devolver múltiples resultados? ¿O incluso devolver la etiqueta con la siguiente probabilidad más alta?
Gracias por tu ayuda.
---Actualizar
Intenté usarlo, OneVsRestClassifier
pero solo obtengo una opción por texto. A continuación se muestra 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']
fuente
min_n
ymax_n
. Necesito cambiarlos parangram_range=(1,2)
que funcionenEDITAR: actualizado para Python 3, scikit-learn 0.18.1 usando MultiLabelBinarizer como se sugiere.
También he estado trabajando en esto y realicé una ligera 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 usando 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
fuente
labelBinarizer
Esta anticuado. Úselo en sulb = preprocessing.MultiLabelBinarizer()
lugarNew York
yLondon
.classif = OneVsRestClassifier(SVC(kernel='linear'))
. Perplejo.También me encontré con esto, y el problema para mí fue que mi y_Train era una secuencia de cadenas, en lugar de una secuencia de secuencias de cadenas. Aparentemente, OneVsRestClassifier decidirá basándose en el formato de la etiqueta de entrada si usar múltiples clases o múltiples etiquetas. Así que cambia:
y_train = ('New York','London')
a
y_train = (['New York'],['London'])
Aparentemente 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
fuente
Cambie esta línea para que funcione en nuevas versiones de python
# lb = preprocessing.LabelBinarizer() lb = preprocessing.MultiLabelBinarizer()
fuente
Algunos 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]]
fuente