可视化K意味着聚类

时间:2013-06-29 17:36:36

标签: java k-means

我正在12维矩阵上进行KMean聚类。我设法在K集群中得到结果。我想通过将其绘制成2D图来显示结果,但我无法弄清楚如何将12维数据转换为2维。

有关如何进行转换或任何可视化结果的替代方法的建议?我试过了Multidimensional Scaling for Java (MDSJ),但它没有用。

我使用的KMean算法来自Java Machine Learning Library: Clustering basics

3 个答案:

答案 0 :(得分:1)

我会做Principal Component Analysis(可能是Multidimensional scaling算法中最简单的算法)。 (BTW PCA与KMeans无关,它是降维的一般方法)

  1. 我假设变量在列中,观察在行中。

  2. 标准化数据 - 将变量转换为z分数。这意味着:从每个单元格中减去列的平均值,并将结果除以std。列的偏差。这样你就可以获得零均值和单位方差。前者是强制性的,后者,我会说,很好。如果方差为零,则从协方差矩阵计算特征向量,否则必须使用哪种自动标准化数据的相关矩阵。见this for explanation)。

  3. 计算协方差矩阵的特征向量和特征值。通过特征值对特征向量进行排序。 (许多图书馆已经为你提供了那种方式排序的特征向量)。

  4. 使用特征向量矩阵的前两列并乘以原始矩阵(转换为z分数),可视化此数据。

  5. 使用colt库,您可以执行以下操作。它与其他矩阵库类似:

        import cern.colt.matrix.DoubleMatrix1D;
        import cern.colt.matrix.DoubleMatrix2D;
        import cern.colt.matrix.doublealgo.Statistic;
        import cern.colt.matrix.impl.SparseDoubleMatrix2D;
        import cern.colt.matrix.linalg.Algebra;
        import cern.colt.matrix.linalg.EigenvalueDecomposition;
        import hep.aida.bin.DynamicBin1D;
    
        public class Pca {
            // to show matrix creation, it does not make much sense to calculate PCA on random data
            public static void main(String[] x) {
                double[][] data = {
                    {2.0,4.0,1.0,4.0,4.0,1.0,5.0,5.0,5.0,2.0,1.0,4.0}, 
                    {2.0,6.0,3.0,1.0,1.0,2.0,6.0,4.0,4.0,4.0,1.0,5.0},
                    {3.0,4.0,4.0,4.0,2.0,3.0,5.0,6.0,3.0,1.0,1.0,1.0},
                    {3.0,6.0,3.0,3.0,1.0,2.0,4.0,6.0,1.0,2.0,4.0,4.0}, 
                    {1.0,6.0,4.0,2.0,2.0,2.0,3.0,4.0,6.0,3.0,4.0,1.0}, 
                    {2.0,5.0,5.0,3.0,1.0,1.0,6.0,6.0,3.0,2.0,6.0,1.0}
                };
    
                DoubleMatrix2D matrix = new DenseDoubleMatrix2D(data);
    
                DoubleMatrix2D pm = pcaTransform(matrix);
    
                // print the first two dimensions of the transformed matrix - they capture most of the variance of the original data
                System.out.println(pm.viewPart(0, 0, pm.rows(), 2).toString());
            }
    
            /** Returns a matrix in the space of principal components, take the first n columns  */
            public static DoubleMatrix2D pcaTransform(DoubleMatrix2D matrix) {
                DoubleMatrix2D zScoresMatrix = toZScores(matrix);
                final DoubleMatrix2D covarianceMatrix = Statistic.covariance(zScoresMatrix);
    
                // compute eigenvalues and eigenvectors of the covariance matrix (flip needed since it is sorted by ascending).
                final EigenvalueDecomposition decomp = new EigenvalueDecomposition(covarianceMatrix);
    
                // Columns of Vs are eigenvectors = principal components = base of the new space; ordered by decreasing variance
                final DoubleMatrix2D Vs = decomp.getV().viewColumnFlip(); 
    
                // eigenvalues: ev(i) / sum(ev) is the percentage of variance captured by i-th column of Vs
                // final DoubleMatrix1D ev = decomp.getRealEigenvalues().viewFlip();
    
                // project the original matrix to the pca space
                return Algebra.DEFAULT.mult(zScoresMatrix, Vs);
            }
    
    
            /**
             * Converts matrix to a matrix of z-scores (by columns)
             */
            public static DoubleMatrix2D toZScores(final DoubleMatrix2D matrix) {
                final DoubleMatrix2D zMatrix = new SparseDoubleMatrix2D(matrix.rows(), matrix.columns());
                for (int c = 0; c < matrix.columns(); c++) {
                    final DoubleMatrix1D column = matrix.viewColumn(c);
                    final DynamicBin1D bin = Statistic.bin(column);
    
                    if (bin.standardDeviation() == 0) {   // use epsilon
                        for (int r = 0; r < matrix.rows(); r++) {
                            zMatrix.set(r, c, 0.0);
                        }
                    } else {
                        for (int r = 0; r < matrix.rows(); r++) {
                            double zScore = (column.get(r) - bin.mean()) / bin.standardDeviation();
                            zMatrix.set(r, c, zScore);
                        }
                    }
                }
    
                return zMatrix;
            }
        }
    

    您也可以使用weka。我首先将数据加载到weka中,然后使用GUI运行PCA(在属性选择下)。您将看到使用什么参数调用哪些类,然后从代码中执行相同的操作。问题是你需要将矩阵转换/包装成weka使用的数据格式。

答案 1 :(得分:0)

CrossValidated 2讨论了一个类似的问题。基本思想是找到一个适当的投影来分隔这些聚类(例如,discproj中的R),然后绘制新空间上聚类的投影。

答案 2 :(得分:0)

除了其他答案所暗示的,你也应该看一下multidimensional scaling