Próbuję użyć jednej z metod nadzorowanego uczenia scikit-learn, aby sklasyfikować fragmenty tekstu w jedną lub więcej kategorii. Funkcja przewidywania wszystkich algorytmów, które wypróbowałem, zwraca tylko jedno dopasowanie.
Na przykład mam fragment tekstu:
"Theaters in New York compared to those in London"
Wyszkoliłem algorytm, aby wybierał miejsce dla każdego fragmentu tekstu, który go karmię.
W powyższym przykładzie chciałbym, aby powrócił New York
i London
, ale tylko zwraca New York
.
Czy można użyć scikit-learn do zwrócenia wielu wyników? A może nawet zwrócić etykietę z kolejnym największym prawdopodobieństwem?
Dzięki za pomoc.
---Aktualizacja
Próbowałem użyć, OneVsRestClassifier
ale nadal otrzymuję tylko jedną opcję z powrotem na fragment tekstu. Poniżej znajduje się przykładowy kod, którego używam
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
Wynik: [„Nowy Jork” „Londyn” „Londyn”]
źródło
min_n
imax_n
. Muszę je zmienićngram_range=(1,2)
na działanieEDYCJA: Zaktualizowano dla Pythona 3, scikit-learn 0.18.1 przy użyciu MultiLabelBinarizer zgodnie z sugestią.
Pracowałem nad tym również i nieznacznie ulepszyłem doskonałą odpowiedź mwv, która może być przydatna. Pobiera etykiety tekstowe jako dane wejściowe, a nie etykiety binarne i koduje je za pomocą 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)))
To daje mi następujący wynik:
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
źródło
labelBinarizer
jest nieaktualny. Użyjlb = preprocessing.MultiLabelBinarizer()
zamiast tegoNew York
iLondon
.classif = OneVsRestClassifier(SVC(kernel='linear'))
. Zdziwiony.Właśnie w to też wpadłem i problem polegał na tym, że mój y_Train był sekwencją ciągów znaków, a nie sekwencją ciągów ciągów. Najwyraźniej OneVsRestClassifier zdecyduje na podstawie formatu etykiety wejściowej, czy użyć wieloklasowego czy wieloznakowego. Więc zmień:
y_train = ('New York','London')
do
y_train = (['New York'],['London'])
Najwyraźniej zniknie to w przyszłości, ponieważ zerwania wszystkich etykiet są takie same: https://github.com/scikit-learn/scikit-learn/pull/1987
źródło
Zmień tę linię, aby działała w nowych wersjach Pythona
# lb = preprocessing.LabelBinarizer() lb = preprocessing.MultiLabelBinarizer()
źródło
Kilka przykładów klasyfikacji wielokrotnych jest takich jak: -
Przykład 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)
Wyjście jest
[[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]]
Przykład 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)
Wyjście jest
[[1 0 0] [0 1 0] [0 0 1] [0 1 0]]
źródło