python - scikit-learn 中分类算法的文本特征输入格式

标签 python scikit-learn classification text-processing feature-engineering

我开始使用 scikit-learn 来做一些 NLP。我已经使用了 NLTK 中的一些分类器,现在我想尝试在 scikit-learn 中实现的分类器。

我的数据基本上是句子,我从这些句子的一些词中提取特征来做一些分类任务。我的大部分特征都是名义上的:单词的词性 (POS)、单词到左边、POS 单词到左边、单词到右边、POS 单词到最后-对,从一个词到另一个词的句法关系路径等。

当我使用 NLTK 分类器(决策树、朴素贝叶斯)进行一些实验时,特征集只是一个字典,其中包含特征的相应值:标称值。如:[ {"postag":"noun", "wleft":"house", "path":"VPNNPN",...},.... ]。我只需要将它传递给分类器,它们就完成了它们的工作。

这是使用的部分代码:

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

这是提取的其中一个特征集的示例:

[({'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 中实现的算法是 Not Acceptable ,因为所有特征值都必须是数字,并且它们必须在数组或矩阵中。因此,我使用 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 提供的分类算法?

在此先感谢您能给我的所有帮助。

更新

正如下面的答案所建议的,我尝试将 NLTK 包装器用于 scikit-learn。我刚刚更改了创建分类器的代码行:

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

因此,显然,包装器无法创建稀疏矩阵,因为特征是名义上的。然后,我回到原来的问题。

最佳答案

ValueError: array is too big. 非常明确:您不能在内存中分配 (n_samples, n_features) 的密集数组数据结构。将那么多的零存储在连续的内存块中是没有用的(在您的情况下是不可能的)。使用 DictVectorizer documentation 中的稀疏数据结构相反。

此外,如果您更喜欢 NLTK API,您可以使用它的 scikit-learn 集成而不是使用 scikit-learn DictVectorizer:

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

查看文件末尾。

关于python - scikit-learn 中分类算法的文本特征输入格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12102320/

相关文章:

python - 如何在tensorflow中加载本地镜像?

python - 使用 gridsearchcv 进行逻辑回归的特征重要性

python - 值错误 : Dataset with data_id 554 not found

node.js - 在 Node.js 上训练分类器(自然 - NLP)以查找意外句子

python - (Python) socket.gaierror : [Errno 11001] getaddrinfo failed

python - 在共享服务器 : No module named MySQLdb? 上安装 Django

python - PyQt4 : How many lines are visible in QTextEdit at once without scrolling?

machine-learning - 在 Scikit-Learn 中使用近似最近邻进行分类

r - 电子邮件垃圾邮件分类从标题中提取特征

python - sklearn : Plot confusion matrix combined across training+test sets