0

マルチラベル分類の問題を解決しようとしています

        from sklearn.preprocessing import MultiLabelBinarizer 

        traindf = pickle.load("traindata.pkl","rb"))
        X = traindf['Col1']
        X=MultiLabelBinarizer().fit_transform(X)

        y = traindf['Col2']
        y= MultiLabelBinarizer().fit_transform(y)

        Xtrain, Xvalidate, ytrain, yvalidate = train_test_split(X, y, test_size=.5)
        from sklearn.linear_model import LogisticRegression

        clf = OneVsRestClassifier(LogisticRegression(penalty='l2', C=0.01)).fit(Xtrain,ytrain)

        print "One vs rest accuracy: %.3f"  % clf.score(Xvalidate,yvalidate)

このようにして、私は常に0の精度を得ます。私が何か間違ったことをしている場合は指摘してください。マルチラベル分類は初めてです。ここに私のデータがどのように見えるかがあります

Col1                  Col2
asd dfgfg             [1,2,3]
poioi oiopiop         [4]

編集

@lejlot をご利用いただきありがとうございます。私はそれのコツをつかんでいると思います。これが私が試したものです

import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import SGDClassifier 
from sklearn.multiclass import OneVsRestClassifier
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression

tdf = pd.read_csv("mul.csv", index_col="DocID",error_bad_lines=False)

print tdf

私の入力データは次のようになります

DocID   Content           Tags    
1       abc abc abc       [1]
2       asd asd asd       [2]
3       abc abc asd     [1,2]
4       asd asd abc     [1,2]
5       asd abc qwe   [1,2,3]
6       qwe qwe qwe       [3]
7       qwe qwe abc     [1,3]
8       qwe qwe asd     [2,3]

これは私が作成したテストデータです。それから私はします

text_clf = Pipeline([
                     ('vect', TfidfVectorizer()),
                     ('clf', SGDClassifier(loss='hinge', penalty='l2',
                                            alpha=1e-3, n_iter=5, random_state=42)),
 ])

t=TfidfVectorizer()
X=t.fit_transform(tdf["Content"]).toarray()
print X

これは私に与える

[[ 1.          0.          0.        ]
 [ 0.          1.          0.        ]
 [ 0.89442719  0.4472136   0.        ]
 [ 0.4472136   0.89442719  0.        ]
 [ 0.55247146  0.55247146  0.62413987]
 [ 0.          0.          1.        ]
 [ 0.40471905  0.          0.91444108]
 [ 0.          0.40471905  0.91444108]]

それから

y=tdf['Tags']
y=MultiLabelBinarizer().fit_transform(y)

print y

私にくれます

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

ここで、なぜ6列があるのか​​ 疑問に思っていますか? 3つだけでいいんじゃない? とにかく、テストデータファイルも作成しました

sdf=pd.read_csv("multest.csv", index_col="DocID",error_bad_lines=False)
print sdf

これは次のように見えます

DocID  Content        PredTags             
34     abc abc qwe    [1,3]
35     asd abc asd    [1,2]
36     abc abc abc      [1]

PredTags精度をチェックする列があります。最後に、私は次のように適合して予測します

clf = OneVsRestClassifier(LogisticRegression(penalty='l2', C=0.01)).fit(X,y)
predicted = clf.predict(t.fit_transform(sdf["Content"]).toarray())
print predicted

それは私に与えます

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

では、どのタグが予測されているかを知るにはどうすればよいでしょうか? PredTagsカラムに対する精度を確認するにはどうすればよいですか?

アップデート

@lejlotに感謝します:)次のように精度を取得することもできました

sdf=pd.read_csv("multest.csv", index_col="DocID",error_bad_lines=False)
print sdf

predicted = clf.predict(t.fit_transform(sdf["Content"]).toarray())
print predicted


ty=sdf["PredTags"]
ty = [map(int, list(_y.replace(',','').replace('[','').replace(']',''))) for _y in ty]

yt=MultiLabelBinarizer().fit_transform(ty)
Xt=t.fit_transform(sdf["Content"]).toarray()

print Xt
print yt
print "One vs rest accuracy: %.3f"  % clf.score(Xt,yt)

テストセットの予測列も2値化する必要がありました:)

4

1 に答える 1

1

実際の問題は、テキストの扱い方にあります。何らかの特徴を抽出して、それをテキスト表現として使用する必要があります。たとえば、bag of words表現、tfidf、またはより複雑なアプローチを使用できます。

では、今何が起こっているのでしょうか?したがって、文字列のリストでmultilabelbinarizer を呼び出すと、scikit-learn はリスト内のすべてのイテラブルのセットを作成します...文字表現のセットにつながります。たとえば

from sklearn.preprocessing import MultiLabelBinarizer 
X = ['abc cde', 'cde', 'fff']
print MultiLabelBinarizer().fit_transform(X)

あなたにあげる

array([[1, 1, 1, 1, 1, 1, 0],
       [0, 0, 0, 1, 1, 1, 0],
       [0, 0, 0, 0, 0, 0, 1]])

        |  |  |  |  |  |  |
        v  v  v  v  v  v  v

        a  b  _  c  d  e  f

したがって、テキストの意味を捉えることができないため、分類はほとんど不可能です。

たとえば、Count Vectorization (bag of words) を実行できます。

from sklearn.feature_extraction.text import CountVectorizer
print CountVectorizer().fit_transform(X).toarray()

あなたにあげる

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

        |  |  |
        v  |  v
       abc | fff
           v
          cde

アップデート

最後に、二値化ではなくラベルを使用して予測を行うには、二値化器を次のように保存する必要があります

labels = MultiLabelBinarizer()
y = labels.fit_transform(y)

そして後で

clf = OneVsRestClassifier(LogisticRegression(penalty='l2', C=0.01)).fit(X,y)
predicted = clf.predict(t.fit_transform(sdf["Content"]).toarray())
print labels.inverse_transform(predicted)

更新 2

クラスが3つしかない場合、ベクトルには3つの要素が必要です.6つの要素があるため、「y」として渡すものを確認してください。データに間違いがある可能性があります

from sklearn.preprocessing import MultiLabelBinarizer
MultiLabelBinarizer().fit_transform([[1,2], [1], [3], [2]])

与える

array([[1, 1, 0],
       [1, 0, 0],
       [0, 0, 1],
       [0, 1, 0]])

予想通り。

私の最善の推測は、あなたの「タグ」も文字列であるため、実際に呼び出すことです

MultiLabelBinarizer().fit_transform(["[1,2]", "[1]", "[3]", "[2]"])

につながる

array([[1, 1, 1, 0, 1, 1],
       [0, 1, 0, 0, 1, 1],
       [0, 0, 0, 1, 1, 1],
       [0, 0, 1, 0, 1, 1]])

        |  |  |  |  |  | 
        v  v  v  v  v  v  

        ,  1  2  3  [  ] 

そして、これらはあなたの6つのクラスです。常に存在する 2 つの "自明な" クラス "[" と "]" と、複数のクラスに属するすべてのオブジェクトに現れるほぼ自明なクラス "," の 3 つの真のもの。

最初にタグを実際のリストに変換する必要があります。

y = [map(int, list(_y.replace(',','').replace('[','').replace(']',''))) for _y in y]
于 2015-12-15T15:17:34.040 に答える