5

私は、scikit-learn を使用して NLP を実行し始めています。私はすでに NLTK の分類子をいくつか使用していますが、今は scikit-learn に実装されている分類子を試してみたいと思っています。

私のデータは基本的に文であり、それらの文のいくつかの単語から特徴を抽出して、分類タスクを実行します。私の機能のほとんどは名目上のものです: 単語の品詞 (POS)、単語を左に、POS 単語を左に、単語を右に、POS 単語を右に-右、ある単語から別の単語への構文関係のパスなど

NLTK 分類子 (デシジョン ツリー、単純ベイズ) を使用していくつかの実験を行ったとき、機能セットは、機能に対応する値 (公称値) を含む単なる辞書でした。例: [ {"postag":"名詞", "wleft":"家", "パス":"VPNPNP",...},.... ]。これを分類子に渡すだけで、彼らは仕事をしてくれました。

これは使用されるコードの一部です:

def train_classifier(self):
        if self.reader == None:
            raise ValueError("No reader was provided for accessing training instances.")

        # Get the argument candidates
        argcands = self.get_argcands(self.reader)

        # Extract the necessary features from the argument candidates
        training_argcands = []
        for argcand in argcands:
            if argcand["info"]["label"] == "NULL":
                training_argcands.append( (self.extract_features(argcand), "NULL") )
            else:
                training_argcands.append( (self.extract_features(argcand), "ARG") )

        # Train the appropriate supervised model
        self.classifier = DecisionTreeClassifier.train(training_argcands)

        return

抽出された機能セットの 1 つの例を次に示します。

[({'phrase': u'np', 'punct_right': 'NULL', 'phrase_left-sibling': 'NULL', 'subcat': 'fcl=np np vp np pu', 'pred_lemma': u'revelar', 'phrase_right-sibling': u'np', 'partial_path': 'vp fcl', 'first_word-postag': 'Bras\xc3\xadlia PROP', 'last_word-postag': 'Bras\xc3\xadlia PROP', 'phrase_parent': u'fcl', 'pred_context_right': u'um', 'pred_form': u'revela', 'punct_left': 'NULL', 'path': 'vp\xc2\xa1fcl!np', 'position': 0, 'pred_context_left_postag': u'ADV', 'voice': 0, 'pred_context_right_postag': u'ART', 'pred_context_left': u'hoje'}, 'NULL')]

前に述べたように、ほとんどの機能は名目上のもの (文字列値) です。

さて、scikit-learn パッケージの分類子を試してみたいと思います。私が理解しているように、このタイプの機能セットは、sklearn に実装されているアルゴリズムには受け入れられません。すべての機能値は数値でなければならず、配列または行列でなければならないからです。したがって、DictVectorizer クラスを使用して「元の」機能セットを変換しました。ただし、この変換されたベクトルを渡すと、次のエラーが発生します。

# With DecisionTreeClass
Traceback (most recent call last): 
.....
self.classifier.fit(train_argcands_feats,new_train_argcands_target)
  File "/usr/local/lib/python2.7/dist-packages/sklearn/tree/tree.py", line 458, in fit
    X = np.asarray(X, dtype=DTYPE, order='F')
  File "/usr/local/lib/python2.7/dist-packages/numpy/core/numeric.py", line 235, in asarray
    return array(a, dtype, copy=False, order=order)
TypeError: float() argument must be a string or a number


# With GaussianNB

Traceback (most recent call last):
....
self.classifier.fit(train_argcands_feats,new_train_argcands_target)
  File "/usr/local/lib/python2.7/dist-packages/sklearn/naive_bayes.py", line 156, in fit
    n_samples, n_features = X.shape
ValueError: need more than 0 values to unpack

DictVectorizer() を使用すると、これらのエラーが発生します。ただし、DictVectorizer(sparse=False) を使用すると、コードがトレーニング部分に到達する前でもエラーが発生します。

Traceback (most recent call last):
train_argcands_feats = self.feat_vectorizer.fit_transform(train_argcands_feats)
  File "/usr/local/lib/python2.7/dist-packages/sklearn/feature_extraction/dict_vectorizer.py", line 123, in fit_transform
    return self.transform(X)
  File "/usr/local/lib/python2.7/dist-packages/sklearn/feature_extraction/dict_vectorizer.py", line 212, in transform
    Xa = np.zeros((len(X), len(vocab)), dtype=dtype)
ValueError: array is too big.

このエラーのため、スパース表現を使用する必要があることは明らかです。

問題は、scikit-learn が提供する分類アルゴリズムを使用するために、名目上の特徴をどのように変換すればよいかということです。

あなたが私に与えることができるすべての助けを前もってありがとう.

アップデート

以下の回答で示唆されているように、scikit-learn に NLTK ラッパーを使用しようとしました。分類子を作成するコード行を変更しました。

self.classifier = SklearnClassifier(DecisionTreeClassifier())

次に、「train」メソッドを呼び出すと、次のようになります。

File "/usr/local/lib/python2.7/dist-packages/nltk/classify/scikitlearn.py", line 100, in train
    X = self._convert(featuresets)
  File "/usr/local/lib/python2.7/dist-packages/nltk/classify/scikitlearn.py", line 109, in _convert
    return self._featuresets_to_coo(featuresets)
  File "/usr/local/lib/python2.7/dist-packages/nltk/classify/scikitlearn.py", line 126, in _featuresets_to_coo
    values.append(self._dtype(v))
ValueError: could not convert string to float: np

したがって、機能が名目上のものであるため、ラッパーは疎行列を作成できないようです。それでは、元の問題に戻ります。

4

2 に答える 2

4

ValueError: array is too big.は非常に明示的です。(n_samples、n_features) の密な配列データ構造をメモリに割り当てることはできません。メモリの連続したチャンクに多くのゼロを格納するのは無意味です (そしてあなたの場合は不可能です)。代わりに、 DictVectorizer のドキュメントのようにスパース データ構造を使用してください。

また、NLTK API を使用する場合は、 scikit-learn を使用する代わりに、その scikit-learn 統合を使用できますDictVectorizer

http://nltk.org/_modules/nltk/classify/scikitlearn.html

ファイルの最後を見てください。

于 2012-08-24T08:38:08.833 に答える
4

scikit-learn の NLTK ラッパーの問題は、機能名を数値にマッピングする辞書が実際に必要であるため、この場合は問題を解決できないことです。is scikit-learn は、DictVectorizer文字列の特徴値に遭遇したときに「one-of-K」コーディングを行うという点で、より洗練されています。使用方法は次のとおりです。

>>> data = [({'first_word-postag': 'Bras\xc3\xadlia PROP',
   'last_word-postag': 'Bras\xc3\xadlia PROP',
   'partial_path': 'vp fcl',
   'path': 'vp\xc2\xa1fcl!np',
   'phrase': u'np',
   'phrase_left-sibling': 'NULL',
   'phrase_parent': u'fcl',
   'phrase_right-sibling': u'np',
   'position': 0,
   'pred_context_left': u'hoje',
   'pred_context_left_postag': u'ADV',
   'pred_context_right': u'um',
   'pred_context_right_postag': u'ART',
   'pred_form': u'revela',
   'pred_lemma': u'revelar',
   'punct_left': 'NULL',
   'punct_right': 'NULL',
   'subcat': 'fcl=np np vp np pu',
   'voice': 0},
  'NULL')]

このリストを 2 つのリストに分割します。1 つはサンプルを含み、もう 1 つは対応するラベルです。

>>> samples, labels = zip(*data)

サンプルを次の場所にDictVectorizer.fit渡します (必要に応じて別の引数でラベルを渡すこともできますが、それらは無視されます):

>>> v = DictVectorizer()
>>> X = v.fit_transform(samples)
>>> X
<1x19 sparse matrix of type '<type 'numpy.float64'>'
    with 19 stored elements in COOrdinate format>

Xその後、スパース入力を受け入れる scikit-learn 分類器に渡すことができるはずです。@ogriselがすでに指摘しているように、それはGaussianNBしません。NLP タスクの場合、これらは離散データ用に特別に設計されているため、MultinomialNBorを使用する必要があります。BernoulliNB

于 2012-08-26T12:07:09.937 に答える