web-dev-qa-db-ja.com

scikit-learnを使用して複数のカテゴリに分類する

私はscikit-learnの教師付き学習方法の1つを使用して、テキストを1つ以上のカテゴリに分類しようとしています。私が試したすべてのアルゴリズムの予測関数は、1つの一致を返すだけです。

たとえば、私はテキストを持っています:

"Theaters in New York compared to those in London"

そして、私はそれをフィードするすべてのテキストスニペットの場所を選択するアルゴリズムを訓練しました。

上記の例では、New YorkLondonを返しますが、New Yorkのみを返します。

Scikit-learnを使用して複数の結果を返すことは可能ですか?または、次に高い確率でラベルを返しますか?

ご協力いただきありがとうございます。

- -更新

OneVsRestClassifierを使用してみましたが、テキストごとに1つのオプションしか返されません。以下は私が使用しているサンプルコードです

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

76
CodeMonkeyB

必要なものはマルチラベル分類と呼ばれます。 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

お役に立てれば。

108
mwv

編集:Python 3、提案されたMultiLabelBinarizerを使用して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
58
J Maurer

この行を変更して、Pythonの新しいバージョンで動作するようにします

# lb = preprocessing.LabelBinarizer()
lb = preprocessing.MultiLabelBinarizer()
7
Srini Sydney

私もこれに遭遇しましたが、問題は、y_Trainが文字列のシーケンスではなく、文字列のシーケンスであったことです。どうやら、OneVsRestClassifierは、入力ラベル形式に基づいて、マルチクラスとマルチラベルのどちらを使用するかを決定します。だから変更:

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

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

どうやら、これはすべてのラベルの破損が同じであるため、将来消えます。 https://github.com/scikit-learn/scikit-learn/pull/1987

7
user2824135

複数の分類の例は次のとおりです。

例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]]
2
Goyal Vicky