• 从WekaWiki上的一个文本聚类的示例开始(3)


    在完成了预处理和特征提取后,下一步就是用 聚类算法 进行文本聚类。在聚类算法中 距离函数的选择很重要,文本挖掘中最好的距离函数就是 余弦距离,但是Weka 3.6.10中 尚不支持 余弦距离,需要自己实现。

    我们可以在 Eclipse 中创建一个文本挖掘的项目,引入 weka.jar,然后然后实现一个计算余弦距离的类,让这个类继承自weka中用于计算欧氏距离的类,代码如下:

    package cn.csdn.test;
    
    import java.util.Enumeration;
    
    import weka.core.Attribute;
    import weka.core.EuclideanDistance;
    import weka.core.Instance;
    import weka.core.Instances;
    import weka.core.converters.ConverterUtils.DataSource;
    import weka.core.neighboursearch.PerformanceStats;
    
    //public class CosineDistance implements DistanceFunction, OptionHandler, Serializable, RevisionHandler{
    public class CosineDistance extends EuclideanDistance{
    
    public Instances m_Data = null;
     public String version ="1.0";
     
     @Override
     public double distance(Instance arg0, Instance arg1) {
      // TODO Auto-generated method stub
      return distance(arg0, arg1, Double.POSITIVE_INFINITY, null);
     }
    
     @Override
     public double distance(Instance arg0, Instance arg1, PerformanceStats arg2) {
      // TODO Auto-generated method stub
      return distance(arg0, arg1, Double.POSITIVE_INFINITY, arg2);
     }
    
     @Override
     public double distance(Instance arg0, Instance arg1, double arg2) {
      // TODO Auto-generated method stub
      return distance(arg0, arg1, arg2, null);
     }
    
     @Override
     public double distance(Instance first, Instance second, double cutOffValue,
       PerformanceStats arg3) {
      double distance = 0;
      int firstI, secondI;
      int firstNumValues = first.numValues();
      int secondNumValues = second.numValues();
      int numAttributes = m_Data.numAttributes();
      int classIndex = m_Data.classIndex();
      double normA, normB;
      normA = 0;
      normB = 0;
    
      for (int p1 = 0, p2 = 0; p1 < firstNumValues || p2 < secondNumValues;) {
       if (p1 >= firstNumValues)
        firstI = numAttributes;
       else
        firstI = first.index(p1);
    
       if (p2 >= secondNumValues)
        secondI = numAttributes;
       else
        secondI = second.index(p2);
    
       if (firstI == classIndex) {
        p1++;
        continue;
       }
    //   if ((firstI < numAttributes)) {
    //    p1++;
    //    continue;
    //   }
    
       if (secondI == classIndex) {
        p2++;
        continue;
       }
    //   if ((secondI < numAttributes)) {
    //    p2++;
    //    continue;
    //   }
    
       double diff;
    
       if (firstI == secondI) {
        diff = difference(firstI, first.valueSparse(p1), second
          .valueSparse(p2));
        
        normA += Math.pow(first.valueSparse(p1), 2);
        normB += Math.pow(second.valueSparse(p2), 2);
        p1++;
        p2++;
       } else if (firstI > secondI) {
        diff = difference(secondI, 0, second.valueSparse(p2));
        normB += Math.pow(second.valueSparse(p2), 2);
        p2++;
       } else {
        diff = difference(firstI, first.valueSparse(p1), 0);
        normA += Math.pow(first.valueSparse(p1), 2);
        p1++;
       }
       if (arg3 != null)
        arg3.incrCoordCount();
    
       distance = updateDistance(distance, diff);
       if (distance > cutOffValue)
        return Double.POSITIVE_INFINITY;
      }
      
      //do the post here, don't depends on other functions
      //System.out.println(distance + " " + normA + " "+ normB);
      distance = distance/Math.sqrt(normA)/Math.sqrt(normB);
      distance = 1-distance;
      if(distance < 0 || distance > 1)
       System.err.println("unknown: " + distance);
      return distance;
     }
     
     public double updateDistance(double currDist, double diff){
      double result;
      result = currDist;
      result += diff;
      
      return result;
     }
     
     public double difference(int index, double val1, double val2){
      switch(m_Data.attribute(index).type()){
      case Attribute.NOMINAL:
       return Double.NaN;
       //break;
      case Attribute.NUMERIC:
       return val1 * val2;
       //break;
      }
      return Double.NaN;
     }
     
     @Override
     public String getAttributeIndices() {
      // TODO Auto-generated method stub
      return null;
     }
    
     @Override
     public Instances getInstances() {
      // TODO Auto-generated method stub
      return m_Data;
     }
    
     @Override
     public boolean getInvertSelection() {
      // TODO Auto-generated method stub
      return false;
     }
    
     @Override
     public void postProcessDistances(double[] arg0) {
      // TODO Auto-generated method stub
      
     }
    
     @Override
     public void setAttributeIndices(String arg0) {
      // TODO Auto-generated method stub
      
     }
    
     @Override
     public void setInstances(Instances arg0) {
      // TODO Auto-generated method stub
      m_Data = arg0;
     }
    
     @Override
     public void setInvertSelection(boolean arg0) {
      // TODO Auto-generated method stub
      
      
      //do nothing
     }
    
     @Override
     public void update(Instance arg0) {
      // TODO Auto-generated method stub
      
      //do nothing
     }
    
     @Override
     public String[] getOptions() {
      // TODO Auto-generated method stub
      return null;
     }
    
     @Override
     public Enumeration listOptions() {
      // TODO Auto-generated method stub
      return null;
     }
    
     @Override
     public void setOptions(String[] arg0) throws Exception {
      // TODO Auto-generated method stub
      
     }
    
     @Override
     public String getRevision() {
      // TODO Auto-generated method stub
      return "Cosine Distance function writtern by Tom, version " + version;
     }
     
     public static void main(String[] args) throws Exception{
      String src = "sample.csv";
      DataSource source = new DataSource(src);
      Instances data = source.getDataSet();
      CosineDistance cd = new CosineDistance();
      cd.setInstances(data);
      System.out.println(cd.distance(data.instance(0), data.instance(1)));
      System.out.println(cd.distance(data.instance(1), data.instance(2)));
     }
     
    }

    然后再建立一个MyTextCluster.java文件用该类作为计算距离的实例,进行 K均值聚类。代码如下:

    package cn.csdn.test;
    
    import java.io.File;
    
    import weka.clusterers.ClusterEvaluation;
    import weka.clusterers.SimpleKMeans;
    import weka.core.Instances;
    import weka.core.converters.ArffLoader;
    import weka.filters.Filter;
    import weka.filters.unsupervised.attribute.StringToWordVector;
    
    public class MyTextCluster {
    
    	public static String arffpath="E://2.arff";  //在这里配置arff文件路径
    	
    	/**
    	 * @param args
    	 * @throws Exception 
    	 */
    	public static void main(String[] args) throws Exception {
    		// TODO Auto-generated method stub
    		ArffLoader loader = new ArffLoader();
    	    loader.setFile(new File(arffpath));
    	    Instances dataRaw = loader.getDataSet();
    
    	    StringToWordVector filter = new StringToWordVector();
    	    filter.setInputFormat(dataRaw);
    	    filter.setWordsToKeep(1000);
    	    filter.setIDFTransform(true);
    	    filter.setOutputWordCounts(true);
    	    Instances dataFiltered = Filter.useFilter(dataRaw, filter);
    
    	    SimpleKMeans skm = new SimpleKMeans();
    	    skm.setDisplayStdDevs(false);
    	    //skm.setDistanceFunction(new EuclideanDistance());
    	    skm.setDistanceFunction(new CosineDistance());
    	    skm.setMaxIterations(500);
    	    skm.setDontReplaceMissingValues(true);
    	    skm.setNumClusters(3);
    	    skm.setPreserveInstancesOrder(false);
    	    skm.setSeed(100);
    
    	    skm.buildClusterer(dataFiltered);
    	    ClusterEvaluation eval;
    	    
    	    eval = new ClusterEvaluation();
    	    eval.setClusterer(skm);
    	    eval.evaluateClusterer(dataFiltered);
    	    
    	    //System.out.println("# of clusters: " + eval.getNumClusters());
    	    String a = eval.clusterResultsToString();
    	    System.out.println(a);
    	    for(int i = 0 ; i< dataFiltered.numInstances(); i++) {
    	    	
    	    	System.out.println("Instance"+ String.valueOf(i)+" is in cluster" +skm.clusterInstance(dataFiltered.instance(i)));
    	    }
    	}
    }
    
    运行结果如下:

    kMeans
    ======


    Number of iterations: 2
    Within cluster sum of squared errors: 2.6483113613228255


    Cluster centroids:
                                   Cluster#
    Attribute          Full Data          0          1          2
                             (7)        (1)        (2)        (4)
    =============================================================
    #                     1.9459          0          0     3.4053
    +                    13.3434          0          0    23.3509
    -                      3.557     0.6729     0.3365     5.8883
    --                    0.3579     1.2528          0     0.3132
    0                     5.6761    21.2654          0     4.6168
    01                    0.7159     3.7583          0     0.3132
    1                     2.4783          0          0      4.337
    10                    0.8473          0          0     1.4828
    11                    0.4797          0          0     0.8394
    12                    1.2104     1.6946          0     1.6946
    13                    0.4842     0.8473          0     0.6355
    14                    0.3631          0          0     0.6355
    15                    0.3579     1.2528          0     0.3132
    16                    0.3579          0          0     0.6264
    17                    0.3579          0          0     0.6264
    19                     0.556          0          0      0.973
    2                     1.9187     0.5596          0     3.2178
    20                    0.3579          0          0     0.6264
    2004                  0.8948          0     0.6264     1.2528
    2005                  3.0579          0          0     5.3513
    2006                  3.4376    11.1923          0     3.2178
    21                    0.3631          0          0     0.6355
    22                    0.3579          0          0     0.6264
    23                    0.3579     1.2528          0     0.3132
    24                    0.5369          0          0     0.9396
    25                    0.3579          0          0     0.6264
    26                    0.7159          0          0     1.2528
    27                    0.7159     3.7583          0     0.3132
    28                    1.0393     5.0365          0     0.5596
    29                    0.3198     0.5596          0     0.4197
    3                     0.6249     0.3365          0     1.0094
    30                    0.5287     0.6729     0.3365     0.5888
    31                    0.4797     1.1192          0     0.5596
    36                     0.556          0          0      0.973
    37                    0.3579          0          0     0.6264
    3rd                   0.3579          0          0     0.6264
    4                     0.9593          0     0.2798     1.5389
    40                    0.3579          0          0     0.6264
    49                    0.7159          0          0     1.2528
    5                     1.0894          0          0     1.9064
    55                     0.556          0          0      0.973
    6                     1.6107          0          0     2.8187
    7                     0.7263          0          0     1.2709
    7-inch                 0.556          0          0      0.973
    7/26/06              16.9572          0          0    29.6751
    7/27/06               4.7258          0          0     8.2701
    8                     0.9683          0          0     1.6946
    9                     0.9683          0          0     1.6946
    @                     4.8321          0          0     8.4562
    A                      0.721     0.6729     0.5047     0.8412
    AM                    0.5369          0          0     0.9396
    API                   2.2239    15.5673          0          0
    About                 0.3845     0.3365          0     0.5888
    Actually               0.834          0          0     1.4594
    Add                    0.556          0          0      0.973
    All                   0.8948          0          0      1.566
    Allah                  0.556          0          0      0.973
    Also                  0.4842     0.8473          0     0.6355
    Amazon                 0.556     3.8918          0          0
    America                0.556          0          0      0.973
    An                    0.4842     1.6946     0.4236     0.2118
    And                   0.6729          0     0.1682     1.0935
    Annoucements           0.556          0          0      0.973
    Antihexe               0.556          0          0      0.973
    Anyway                0.3579          0          0     0.6264
    April                 0.3579          0          0     0.6264
    Arbogast               0.834     5.8377          0          0
    Archives              0.3631     0.8473          0     0.4236
    As                    0.3631          0          0     0.6355
    Atom                  0.5369     2.5055          0     0.3132
    August                0.9683     2.5419          0     1.0591
    Baker                  0.556     3.8918          0          0
    Bands                  0.556          0          0      0.973
    Be                    0.3579          0     0.6264     0.3132
    Because               0.5369          0          0     0.9396
    Best                   0.834          0          0     1.4594
    Bill                   0.556     3.8918          0          0
    Blog                  0.8473          0          0     1.4828
    Blogroll              0.3579     1.2528          0     0.3132
    Boondoggle             0.834          0          0     1.4594
    Brainiac              1.9459          0          0     3.4053
    (略)

    Clustered Instances


    0      1 ( 14%)
    1      2 ( 29%)
    2      4 ( 57%)


    Instance0 is in cluster 2
    Instance1 is in cluster 1
    Instance2 is in cluster 0
    Instance3 is in cluster 2
    Instance4 is in cluster 1
    Instance5 is in cluster 2
    Instance6 is in cluster 2


  • 相关阅读:
    MySQL缓存分类
    Babel 是干什么的
    npm是干什么的?
    在改变某一项目的svn的地址,relocate
    在搭建服务器的时候,svn最好与项目所部署的服务器分开
    简述负载均衡和CDN技术
    nginx介绍
    NideShop项目的安装部署教程
    Navicat破解
    当返回的不是单独的一种数据格式
  • 原文地址:https://www.cnblogs.com/rav009/p/5131103.html
Copyright © 2020-2023  润新知