scikit-learn을 사용하여 여러 범주로 분류


80

scikit-learn의지도 학습 방법 중 하나를 사용하여 텍스트를 하나 이상의 범주로 분류하려고합니다. 내가 시도한 모든 알고리즘의 예측 기능은 하나의 일치를 반환합니다.

예를 들어 텍스트가 있습니다.

"Theaters in New York compared to those in London"

그리고 내가 피드하는 모든 텍스트 스 니펫의 위치를 ​​선택하도록 알고리즘을 훈련 시켰습니다.

위의 예에서는 New Yorkand 를 반환하기를 원 London하지만 New York.

scikit-learn을 사용하여 여러 결과를 반환 할 수 있습니까? 아니면 다음으로 높은 확률로 라벨을 반환할까요?

당신의 도움을 주셔서 감사합니다.

---최신 정보

나는 사용해 OneVsRestClassifier보았지만 여전히 텍스트 조각 당 하나의 옵션 만 반환됩니다. 아래는 내가 사용하는 샘플 코드입니다.

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

결과 : [ 'New York' 'London' 'London']

답변:


111

원하는 것은 다중 레이블 분류입니다. Scikits-learn은 그렇게 할 수 있습니다. 여기를 참조하십시오 : http://scikit-learn.org/dev/modules/multiclass.html .

귀하의 예에서 무엇이 잘못되었는지 잘 모르겠습니다. 제 sklearn 버전에는 WordNGramAnalyzer가없는 것 같습니다. 아마도 더 많은 훈련 예제를 사용하거나 다른 분류기를 시도하는 질문일까요? 다중 레이블 분류자는 대상이 튜플 목록 / 레이블 목록 일 것으로 예상합니다.

다음은 나를 위해 작동합니다.

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))

나를 위해 이것은 출력을 생성합니다.

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

도움이 되었기를 바랍니다.


1
나는 도시 이름을 결합한 마지막 두 가지 훈련 예제를 제거하려고 시도했고 나는 얻는다 : hello welcome to new york. 여기와 런던도 즐기십시오 => 뉴욕 더 이상 두 개의 레이블을 반환하지 않습니다. 나에게 두 도시의 조합을 훈련하면 두 개의 레이블이 반환됩니다. 내가 뭔가를 놓치고 있습니까? 도와 주셔서 다시 한 번 감사드립니다
CodeMonkeyB

1
이것은 단지 장난감 데이터 세트 일 뿐이며 그로부터 너무 많은 결론을 내리지는 않을 것입니다. 실제 데이터에 대해이 절차를 시도 했습니까?
mwv

3
@CodeMonkeyB :이 대답을 정말로 받아 들여야합니다. 프로그래밍 관점에서 보면 맞습니다. 실제로 작동하는지 여부는 코드가 아니라 데이터에 따라 다릅니다.
Fred Foo

2
다른 사람이 min_nmax_n. ngram_range=(1,2)작업 하도록 변경해야합니다
emmagras 2015-06-12

1
다음 오류가 발생합니다. ValueError : 레거시 다중 레이블 데이터 표현을 사용하는 것 같습니다. 시퀀스 시퀀스는 더 이상 지원되지 않습니다. 대신 이진 배열 또는 희소 행렬을 사용하십시오.
MANU

61

편집 : 제안 된대로 MultiLabelBinarizer를 사용하여 Python 3, scikit-learn 0.18.1 용으로 업데이트되었습니다.

나는 이것에 대해서도 작업하고 있으며 유용 할 수있는 mwv의 훌륭한 답변을 약간 개선했습니다. 이진 레이블이 아닌 텍스트 레이블을 입력으로 사용하고 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)))

이것은 다음과 같은 출력을 제공합니다.

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

13
labelBinarizer구식입니다. 사용 lb = preprocessing.MultiLabelBinarizer()대신에
로마

1
유일한 출력 레이블이 New York및 이기 때문에 영국을 제공하지 않습니다 London.
umop aplsdn

2
scikit-learn 에 따르면 One-Vs-All은 sklearn.svm.SVC를 제외한 모든 선형 모델에서 지원되며 다중 레이블은 의사 결정 트리, 임의 포리스트, 가장 가까운 이웃에 의해 지원되므로이 유형에는 LinearSVC ()를 사용하지 않습니다. 의 작업 (일명 다중 레이블 분류)
PeterB

2
@mindstorm이 언급하는 One-Vs-All은 scikit-learn 클래스 "OneVsRestClassifier"에 해당합니다 ( "all"이 아닌 "Rest"에주의). 이 scikit-learn 도움말 페이지에서 설명합니다.
lucid_dreamer

1
@mindstorm이 언급했듯이이 페이지 에서 문서에 "One-Vs-All : sklearn.svm.SVC를 제외한 모든 선형 모델"이 언급 되어있는 것은 사실입니다 . 그러나 scikit-learn 문서의 다른 다중 레이블 예제는이 줄이있는 다중 레이블 예제를 보여줍니다 classif = OneVsRestClassifier(SVC(kernel='linear')). 어찌할 바를 모르는.
lucid_dreamer

8

나는 이것도 만났고, 나에게 문제는 내 y_Train이 String의 시퀀스가 ​​아니라 String의 시퀀스라는 것입니다. 분명히 OneVsRestClassifier는 입력 레이블 형식에 따라 다중 클래스와 다중 레이블을 사용할지 여부를 결정합니다. 따라서 변경 :

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

...에

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

분명히 이것은 모든 레이블의 중단이 동일하기 때문에 미래에 사라질 것입니다 : https://github.com/scikit-learn/scikit-learn/pull/1987


8

새 버전의 파이썬에서 작동하도록이 줄을 변경하십시오.

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

2

몇 가지 다중 분류 예는 다음과 같습니다.

예 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)

출력은

[[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]]

예 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)

출력은

[[1 0 0]
 [0 1 0]
 [0 0 1]
 [0 1 0]]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.