如何使用朴素贝叶斯和主成分分析(C#、Accord.NET)对文档进行分类

Posted

技术标签:

【中文标题】如何使用朴素贝叶斯和主成分分析(C#、Accord.NET)对文档进行分类【英文标题】:How to classify documents using Naive Bayes and Principal Component Analysis (C#, Accord.NET) 【发布时间】:2015-06-24 03:34:49 【问题描述】:

我正在开展一个电子邮件分类项目,该项目会将电子邮件分类到某个类别。到目前为止,我们将有趣的数据(例如:主题和正文)与其他信息一起保存到我们的数据库中。我们已成功地将术语频率 - 逆文档频率应用于项目,以检索在我们的电子邮件主题和正文中找到的所有术语/特征的矩阵。该矩阵的一个非常小的样本输出将是:

      dog    cat    fish
doc1  0,024  0,011  0,008
doc2  0,011  0,014  0,007
doc3  0,005  0,024  0,003
doc4  0,008  0,028  0,008
doc5  0,002  0,03   0,006

实际上,这个矩阵要大得多,因为我们有大约 23000 个术语,用于一组 165 封电子邮件。因为我们需要使用这个矩阵中的术语对电子邮件进行分类,所以 23000 个特征实在是太多了。这就是我们实施降维算法 (PCA) 的原因。这是通过使用此代码(Accord 框架)完成的:

// Creates the Principal Component Analysis of the given source
pca = new PrincipalComponentAnalysis(matrix, AnalysisMethod.Center);

// Compute the Principal Component Analysis
pca.Compute();         

// Creates a projection of the information
double[,] components = pca.Transform(matrix, 20);

// Creates form to show components
frmRPCA frmPCA = new frmRPCA(components);
frmPCA.ShowDialog();

现在我们已经硬编码了维度的数量,但这暂时不应该成为问题。

我一直在查看有关如何使用朴素贝叶斯进行分类的 Accord 框架示例,但我无法真正弄清楚如何将其付诸实践。主要是因为该示例在我们处理数字时使用了文本,而我不太了解分类的工作原理。 See the example on how to implement Naive Bayes.

基本上,我的原始矩阵包含我的特征及其 TF-IDF 值(参见上面的示例),我想使用包含我的 PCA 的矩阵(pca.Transform 方法的输出)对它们进行分类。目前,我只有 2 个类我想对我的电子邮件进行分类(注册和提交)。我将如何实现这一目标?另外,如果我以后想添加多个类,我将如何扩展它?

示例输出应该是这样的:

doc1 Registration
doc2 Registration
doc3 Registration
doc4 Submission
doc5 Submission

【问题讨论】:

因为你实际上有一个分类问题,我认为如果你使用 LDA(线性判别分析)来减少你的维度数量而不是 PCA 会更有用。事实是,PCA 以更好地解释方差的方式减少了维度,而 LDA 以更容易对实例进行分类的方式减少了维度。我会尽快将其扩展为实际答案! 感谢您的快速响应塞萨尔!我还没有研究 LDA,但我会马上做一些研究。 顺便说一句,对不起。我刚刚意识到我解释了 LDA,但我并没有真正回答你关于朴素贝叶斯的问题。我会尽快更新的 【参考方案1】:

如果您对分类感兴趣,那么 LDA(及其变体)可能更适合您的情况。事实上,PCA 试图通过仅查看您的数据来最小化方差。但是,如果您有关于数据的额外信息(例如类标签),则有更好的方法来满足您的需求。

如果您有类标签形式的额外信息(它是, 数据集中的每个样本都有一个关联的整数值,表示它属于哪个类),那么您可以使用 LDA(线性判别分析)来减少 对分类有用的维度。

如果您有 实际输出 形式的额外信息(即,每个 数据集中的样本实际上有一个与 它),那么你可以使用 PLS(偏最小二乘法)以一种有用的方式降低维度 回归。

假设您有分类问题,这里有一个关于如何使用 LDA 减少特征数据​​数量的示例:

// Create some sample input data instances. This is the same
// data used in the Gutierrez-Osuna's example available at:
// http://research.cs.tamu.edu/prism/lectures/pr/pr_l10.pdf

double[][] inputs = 

    // Class 0
    new double[]   4,  1 , 
    new double[]   2,  4 ,
    new double[]   2,  3 ,
    new double[]   3,  6 ,
    new double[]   4,  4 ,

    // Class 1
    new double[]   9, 10 ,
    new double[]   6,  8 ,
    new double[]   9,  5 ,
    new double[]   8,  7 ,
    new double[]  10,  8 
;

int[] output = 

    0, 0, 0, 0, 0, // The first five are from class 0
    1, 1, 1, 1, 1  // The last five are from class 1
;

// Then, we will create a LDA for the given instances.
var lda = new LinearDiscriminantAnalysis(inputs, output);

lda.Compute(); // Compute the analysis


// Now we can project the data into LDA space:
double[][] projection = lda.Transform(inputs);

如果您想将问题从二维减少到一维,您可以使用:

double[][] reduced_data = lda.Transform(inputs, 1);

结果将是一个 10x1 矩阵。它将包含对执行分类仍然有用的数据的低维表示。因此,您可以使用reduced_data 代替使用您的原始数据来学习分类器。

此外,LDA 对象带有一个简单的最小距离分类器,您可以使用它来对实例进行分类。例如,您可以使用

对数据集进行分类
int[] results = lda.Classify(inputs);

但是,没有什么可以阻止您使用您可能喜欢的任何其他分类器(例如朴素贝叶斯)。例如,为了使用朴素贝叶斯,您可以使用

// Create a new normal distribution Naive Bayes classifier for 
// a classification problem with 1 feature and the two classes
var nb = new NaiveBayes.Normal(classes: 2, inputs: 1);

// Compute the Naive Bayes model
nb.Estimate(reduced_data, output);

// Now, if we would like to classify the first instance 
// in our dataset, we would use
int result = nb.Compute(lda.Transform(input[0]));

还有应该demonstrate how LDA works和naive bayes works的框架附带的示例应用程序。

【讨论】:

感谢您的详细说明,Cesar。我和我的队友正在我们的计划中解决这个问题。 当您在输出数组中使用不同的数字时,分类是否可能不起作用?首先,我们对 0 和 1 进行硬编码,分类完成了它应该做的事情。后来,我们决定使用数据库中类别的 id 来创建数组。 2 个不同的 id 是 165 和 168。但是,现在所有内容都归为一类。 是的,算法期望类标签从 0 开始,并且符号之间没有间隙。如果您的数据库有字符串类标签,您可以尝试使用Codification class 将您的字符串标签转换为学习算法要求的顺序符号。 顺便说一下,如果你知道你需要的标签,你可以使用接受一个列名和一组可能的字符串值的构造函数来创建这个类的一个对象,然后使用它将您的标签转换为算法预期的顺序类标签。 我正在尝试一些非常相似的东西,但是lda.Compute() 给了我OutOfMemoryException,我有 118 个课程(这可能是问题所在)我的输入是 188 x 5690。关于如何处理的任何建议?

以上是关于如何使用朴素贝叶斯和主成分分析(C#、Accord.NET)对文档进行分类的主要内容,如果未能解决你的问题,请参考以下文章

python - 如何在使用朴素贝叶斯和python训练数据后进行预测?

朴素贝叶斯-商品评论情感分析

朴素贝叶斯和 SVM 分类 - 如何在 x y 轴上绘制精度?

朴素贝叶斯和条件概率计算

最近邻、朴素贝叶斯和决策树分类器解决给定分类问题的效果如何?

使用朴素贝叶斯情感分析实现 PoS