如何使用主成分分析应用特征减少? (C#,Accord)

时间:2015-04-15 11:54:25

标签: c# matrix pca accord.net

我正在尝试通过Accord框架实现PCA,以实现降低功能,即降低功能。基本上,我有一个包含超过23000个特征的大矩阵。这些是从一组文档中提取的所有功能。这个矩阵的一个非常简单的概述如下所示:

      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个可能的功能(并且#将来只会增加),我们需要减少这个,假设有+ - 20个功能(稍后需要进行分类)。为了让我们意识到这一点,我们需要使用能够减少特征/尺寸数量的东西。所以我们做了一些搜索并遇到了协议框架,内核PCA,ALGLIB等。由于我们没有任何PCA背景而且我们与数学家相差甚远,所以我们都非常模糊。

所以我们选择使用Accord框架,因为它看起来很简单,通过使用以下代码进行测试:

double[,] sourceMatrix = 
        {
            { 2.5,  2.4 },
            { 0.5,  0.7 },
            { 2.2,  2.9 },
            { 1.9,  2.2 },
            { 3.1,  3.0 },
            { 2.3,  2.7 },
            { 2.0,  1.6 },
            { 1.0,  1.1 },
            { 1.5,  1.6 },
            { 1.1,  0.9 }
        };

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

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

        // Creates a projection
        double[,] components = pca.Transform(sourceMatrix);

        for (int i = 0; i < components.GetLength(0); i++)
        {
            for (int j = 0; j < components.GetLength(1); j++)
            {
                Console.WriteLine(components[i, j]);
            }
        }

        Console.ReadLine();

此代码将打印控制台中Transform方法产生的矩阵。由于我们并不真正理解所有数字的含义以及它们如何帮助减少这些特征,因此我们决定在datagridview中查看Components矩阵,方法是使用与前一代码示例完全相同的矩阵。 :

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

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

    // Display
    dgvPCA.DataSource = pca.Components;
    dgvPCA.Columns["Analysis"].Visible = false;

返回比例,累积比例,奇异值和特征值。再一次,没有任何线索。

那么我们如何应用这个原则来将+ - 23000项的矩阵减少到+ - 20?

2 个答案:

答案 0 :(得分:3)

免责声明:我将冒昧地回答您的问题中无法解决的所有问题。 TL; DR:建议在底部

主成分(PC)只是许多要素的投影(线性组合),其中要素是沿某个维度的值向量(通常是观察或测量)。

对于您的问题,这些功能似乎是术语的“术语频率 - 反向文档频率”,每个文档都有一个“度量”。所有文档的所有功能都构成一个矩阵。

主成分分析(PCA)的作用是通过查找这些主成分(您可以将其视为抽象要素,它们有时也称为“它们”来转换(或拉开)此矩阵。隐藏的功能“)。如上所述,它们只是原始术语向量的线性组合,如:

PC1 = 0.1 * Cat + 0.001 * Dog - 0.8 * Fish ... `
PC2 = 0.0001 * Cat - 0.102 * Dog + 0.1 * Fish ...` 
...
PCN = 0.00000001 * Cat - 0.0000000001 * Dog + 0.00000000000001 * Fish ....

其中 N 与原始要素数相同,这些值(0.1,0.001,-0.8,...)表示每个要素的加载在给定的PC上,表达原始术语如何与PC相关联。高正值或负值表示该术语与PC的高正相关或负相关。

找到的主成分的一个重要特性是orthogonal,即不相关,这在视觉上很清晰here

您可能会尝试通过想象您正在查看2D xy散点图(x和y是两个要素)以及数据点云(x和y的单独观察)并尝试旋转来自己对此进行可视化并转换轴,同时数据点保持静止。

x-y plot

首先,您尝试旋转x轴以使其与点云的中心相交,如线性回归线所示。接下来,您将Y轴移动(平移)到点云的中心。 X轴和Y轴的旋转和平移位置是您的主要组成部分。

rotated axes

您可能已经注意到,主成分按其等级进行编号。排名最低的组件解释原始数据集中方差的最大量。对于上面的示例图像,您可以清楚地看到“PCA Axis 1”比“PCA Axis 2”更多地解释了方差

通常,一起解释数据集中所有方​​差的大部分的PC数量将远小于 N 输入要素。通过选择解释足够差异的第一台X PC,可以减少要素维度的数量。

您可以做的另一件事是在PC上查看所谓的得分。这将查看每个文档在PC上的分数,即它对给定PC的贡献程度。

可以找到更详尽的介绍性文字here以及其中一些概念的示例herehere

回到你的问题,我给你的建议:

将主成分分析应用于复杂问题(例如从一组简化的术语中对文档进行分类)远非微不足道,需要彻底了解PCA和您要解决的分类问题。

我建议您尝试寻找/聘请这个领域的专家,他可以向您提供指导,并通过询问您重要的问题帮助您走上正确的道路。

进行更多研究以更好地了解正在其他地方使用的功能减少和分类方法以解决与您正在解决的问题相似的问题也是明智之举。

此外,建议使用专门针对此类数据分析(例如SAS,Matlab,R,...)的工具来开发和验证您的特征选择和分类方法。一旦验证了方法,如果您需要在一个c#软件中实现它们,请寻找最适合的工具(可能是Accord)。

答案 1 :(得分:1)

我之前遇到过一个非常类似的问题,这就是我发现的问题。 使用PCA(基于协议实现)的问题是获得原始数据中最重要的功能。 PCA结果是新组件,它基于旧组件的总和乘以其解释的权重。

这里的问题是获得权重可能有点棘手,因此您可能会发现使用 svm 来解决问题更简单,更有效。

协议还提供了一个非常有用的实现,这是一个示例代码:

double[][] inputs = new double[DataFiles.Count][];
int[] outputs = new int[DataFiles.Count];
//fill the inputs and outputs with your data
double c = SequentialMinimalOptimization.EstimateComplexity(inputs);


// Creates the SVM for input variables
SupportVectorMachine svm = new SupportVectorMachine(inputs:Count);

// Creates a new instance of the sparse logistic learning algorithm
var smo = new ProbabilisticDualCoordinateDescent(svm, inputs, outputs)
{
// Set learning parameters
Complexity = c,
Tolerance = 1e-5,
};
try
{
double error = smo.Run();
}
catch (ConvergenceException)
{
}
// Show feature weight importance
double[] weights = svm.Weights;

请在下面找到进一步的解释 https://github.com/accord-net/framework/wiki/Linear-Support-Vector-Machines