可以在任何文本分类上应用PCA吗?

时间:2016-01-11 15:52:49

标签: python scikit-learn pca naivebayes

我正在尝试使用python进行分类。我在网页上使用Naive Bayes MultinomialNB分类器(从网络文本中检索数据表格,稍后我将此文本分类为:网络分类)。

现在,我试图在这些数据上应用PCA,但是python会出现一些错误。

我的朴素贝叶斯分类代码:

from sklearn import PCA
from sklearn import RandomizedPCA
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
vectorizer = CountVectorizer()
classifer = MultinomialNB(alpha=.01)

x_train = vectorizer.fit_transform(temizdata)
classifer.fit(x_train, y_train)

这种天真的贝叶斯分类给出了输出:

>>> x_train
<43x4429 sparse matrix of type '<class 'numpy.int64'>'
    with 6302 stored elements in Compressed Sparse Row format>

>>> print(x_train)
(0, 2966)   1
(0, 1974)   1
(0, 3296)   1
..
..
(42, 1629)  1
(42, 2833)  1
(42, 876)   1

我尝试在我的数据(temizdata)上应用PCA:

>>> v_temizdata = vectorizer.fit_transform(temizdata)
>>> pca_t = PCA.fit_transform(v_temizdata)
>>> pca_t = PCA().fit_transform(v_temizdata)

但这引起了错误:

  

引发TypeError(&#39;传递了一个稀疏矩阵,但密集的&#39; TypeError:A   传递稀疏矩阵,但需要密集数据。使用X.toarray()   转换为密集的numpy数组。

我将矩阵转换为densematrix或numpy数组。然后我尝试了新的密集矩阵,但我有错误。

我的主要目标是测试PCA对文本分类的影响。

转换为密集阵列:

v_temizdatatodense = v_temizdata.todense()
pca_t = PCA().fit_transform(v_temizdatatodense)

最后尝试classfy:

classifer.fit(pca_t,y_train)
最终classfy的错误

  

引发ValueError(&#34;输入X必须为非负&#34;)ValueError:输入X.   必须是非负面的

一方面,我的数据(temizdata)仅被置于Naive Bayes中,另一侧temizdata首先放入PCA(用于减少输入)而不是分类。 __

3 个答案:

答案 0 :(得分:14)

我不会将sparse矩阵转换为dense(不鼓励),而是使用scikits-learn's TruncatedSVD,这是一种类似PCA的dimmensionality reduction算法(默认情况下使用)随机SVD(适用于稀疏数据):

svd = TruncatedSVD(n_components=5, random_state=42)
data = svd.fit_transform(data) 

并引用TruncatedSVD文档:

  

特别是,截断的SVD适用于sklearn.feature_extraction.text中的矢量化器返回的术语计数/ tf-idf矩阵。在这种情况下,它被称为潜在语义分析(LSA)。

这正是你的用例。

答案 1 :(得分:4)

NaiveBayes分类器需要离散值功能,但PCA会破坏这些功能的属性。如果要使用PCA,则必须使用其他分类器。

可能有其他降维方法适用于NB,但我不知道那些。也许简单的feature selection可以起作用。

旁注:您可以尝试在应用PCA后对功能进行离散化处理,但我认为这不是一个好主意。

答案 2 :(得分:0)

问题在于,通过应用降维,您将生成负面特征。但是,多项式NB不具有负面特征。请参阅this个问题。

尝试使用另一个分类器(例如RandomForest)或尝试使用sklearn.preprocessing.MinMaxScaler()将训练功能扩展到[0,1]