现在的位置: 首页 > 综合 > 正文

采用Weka中的KNN算法进行文本分类

2013年11月05日 ⁄ 综合 ⁄ 共 3211字 ⁄ 字号 评论关闭
      Weka是新西兰Waikato大学开发的一款开源的基于Java的数据挖掘工具,其官方网址为http://www.cs.waikato.ac.nz/ml/weka/。Weka作为一个公共的数据挖掘的平台,集成了大量的机器学习的算法,包括对数据进行预处理、分类、聚类、回归关联规则等。Weka支持可视化界面操作以及API方式的调用,本文采用API调用方式,基于Weka中集成的KNN算法进行文本分类。

1.语料预处理

        文本分类作为监督学习的一种需要提供训练语料,对每一个输入语料文本进行分词处理。

2.特征属性的选取

        对于所有的输入语料中的词语,计算其TF*IDF数值,并对每一个词语根据其TF*IDF的数值由高到低排序,选取TOP N(此处N=200)的词语作为特征词语。

3.每一篇语料文档的处理

       根据上面统计处理的特征词语,计算每一篇文章中特征词语的TF*IDF数值。

4.CSV文件的生产

        CSV文件中每一个语料文本作为一行,形如下图所示:

        其中第一行的数据为特征属性,第一列为语料的类别属性。

5.CSV文件转为ARFF文件

        在此Weka最终接收的格式为ARFF文件,因此我先把CSV文件转为ARFF文件。ARFF文件格式如下:

        其中@relation traindata表示关心的名称 ,@attribute class {food,military,sports,computer,economy}表示类别属性可以的取值,@attribute 农夫山 numeric表示类别属性,@data以下的内容表示对应特征属性的取值。
        首先生成ARFF文件的属性信息
			InputStreamReader isr = new InputStreamReader(new FileInputStream(csvFile), "UTF-8");
			BufferedReader in = new BufferedReader(isr);
			String lineStr = in.readLine();
			FastVector atts = new FastVector();
			List attsList = new ArrayList<Attribute>();
			int attrLen = 0;
			FastVector attVals = new FastVector();
			File clsTypeFile = new File(GlobalUtil.CORPUS_CLS_TYPE);
			List<String> clsTypeList = readCorpusFileList(clsTypeFile);
			List<String> attrList = new ArrayList<String>();//存放数据所有的属性
			if(lineStr!= null){
				String[] attr = lineStr.split(",");
				attrList = Arrays.asList(attr);
				for(String clsType : clsTypeList){
					attVals.addElement(clsType);
				}
				String clsAttr = attr[0];
				Attribute classAtts = new Attribute(clsAttr, attVals);
				atts.addElement(classAtts);
				attsList.add(classAtts);
				for(int i = 1;i < attr.length; i++){
					Attribute headAtts = new Attribute(attr[i]);
					atts.addElement(headAtts);
					attsList.add(headAtts);
				}
				
			}

        读取CSV文件中第一行的内容(特征属性所在行),依次生成每一个特征属性。

       下面的代码生成Instance实例,设置关系名称以及类别属性所在列。
			Instances instances = new Instances("traindata", atts, 0);
			instances.setClassIndex(0);

         然后依次读取每一篇语料文本的特征值,为对应的特征属性赋值。

			while (lineStr != null) {
				if (!lineStr.trim().equals("")) {
					logger.info("当前处理的数据是: "+lineStr);
					Instance inst = new Instance(attrLen);
					String[] dataValue = lineStr.split(",");
					Attribute firstAtt = attsList.get(0);
					String firstVal = dataValue[0];
					inst.setValue(firstAtt, firstVal);
					for(int k = 1; k < attrLen; k++ ){
						Attribute numAttr = attsList.get(k);
						double numVal = Double.parseDouble(dataValue[k]);
						inst.setValue(numAttr, numVal);
					}
					instances.add(inst);
				}
				lineStr = in.readLine();
			}

6.采用Weka中的KNN算法处理ARFF文件

       KNN算法在Weka中对应的类名称为IBK,首先读取ARFF文件
			
			File inputFile = new File(GlobalUtil.ARFF_FILE_NAME);// 训练语料文件
			ArffLoader arffLoader = new ArffLoader();
			arffLoader.setFile(inputFile);

      加载KNN,设置需要考察的最近邻的数目,进行分类处理。

			IBk classifier = (IBk)Class.forName("weka.classifiers.lazy.IBk").newInstance();//KNN算法分类器
			classifier.setKNN(GlobalUtil.NEIGHBOR_NUMS);
			classifier.buildClassifier(instancesTrain);

      此处我将生成的分类信息保存为模型文件储存起来,方便下次直接进行分类处理,而不必再次进行分类器的训练。

SerializationHelper.write(GlobalUtil.MODEL_FILE_NAME , classifier);//将训练结果保存为模型文件

       也可以直接进行分类处理,以当前文件为训练文件,另外选取测试文件进行分类结果测试。

			for (int i = 0; i < sum; i++){// 测试分类结果
				int preIndex = i + 1;
				logger.info("第"+ preIndex +"个样本的判断结果是:" + classifier.classifyInstance(instancesTest.instance(i)));
				logger.info("第"+ preIndex +"个样本的类别属性是:" + instancesTest.instance(i).classValue());
				boolean flag = false;
				
				if (classifier.classifyInstance(instancesTest.instance(i)) == instancesTest.instance(i).classValue()){// 如果预测值和答案值相等(测试语料中的分类列提供的须为正确答案,结果才有意义)
					right++;// 正确值加1
					flag = true;
				}
				logger.info("第"+ preIndex +"个样本的判断结果是否正确:" + flag);
			}
			System.out.println("KNN classification precision:" + (right / sum));

至此分类处理完成。

抱歉!评论已关闭.