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));
至此分類處理完成。