使用 LibLinear 進行文字分類
- 從 .arff 檔案建立培訓例項
private static Instances getDataFromFile(String path) throws Exception{
DataSource source = new DataSource(path);
Instances data = source.getDataSet();
if (data.classIndex() == -1){
data.setClassIndex(data.numAttributes()-1);
//last attribute as class index
}
return data;
}
Instances trainingData = getDataFromFile(pathToArffFile);
-
使用 StringToWordVector 將字串屬性轉換為數字表示形式:
*此過濾器的重要功能:
- tf-idf 表示
- 詞幹
- 小寫的
- 停用詞
- n-gram 表示*
StringToWordVector() filter = new StringToWordVector();
filter.setWordsToKeep(1000000);
if(useIdf){
filter.setIDFTransform(true);
}
filter.setTFTransform(true);
filter.setLowerCaseTokens(true);
filter.setOutputWordCounts(true);
filter.setMinTermFreq(minTermFreq);
filter.setNormalizeDocLength(new SelectedTag(StringToWordVector.FILTER_NORMALIZE_ALL,StringToWordVector.TAGS_FILTER));
NGramTokenizer t = new NGramTokenizer();
t.setNGramMaxSize(maxGrams);
t.setNGramMinSize(minGrams);
filter.setTokenizer(t);
WordsFromFile stopwords = new WordsFromFile();
stopwords.setStopwords(new File("data/stopwords/stopwords.txt"));
filter.setStopwordsHandler(stopwords);
if (useStemmer){
Stemmer s = new /*Iterated*/LovinsStemmer();
filter.setStemmer(s);
}
filter.setInputFormat(trainingData);
-
將過濾器應用於 trainingData:
trainingData = Filter.useFilter(trainingData, filter);
-
建立 LibLinear 分類器
- 下面的 SVMType 0 對應於 L2 正則化邏輯迴歸
- 設定
setProbabilityEstimates(true)
以列印輸出 probalities
Classifier cls = null;
LibLINEAR liblinear = new LibLINEAR();
liblinear.setSVMType(new SelectedTag(0, LibLINEAR.TAGS_SVMTYPE));
liblinear.setProbabilityEstimates(true);
// liblinear.setBias(1); // default value
cls = liblinear;
cls.buildClassifier(trainingData);
- 儲存模型
System.out.println("Saving the model...");
ObjectOutputStream oos;
oos = new ObjectOutputStream(new FileOutputStream(path+"mymodel.model"));
oos.writeObject(cls);
oos.flush();
oos.close();
- 從
.arff
檔案建立測試例項
Instances trainingData = getDataFromFile(pathToArffFile);
- 載入分類器
Classifier myCls = (Classifier) weka.core.SerializationHelper.read(path+"mymodel.model");
-
使用與上面相同的 StringToWordVector 過濾器或為 testingData 建立一個新過濾器,但請記住使用 trainingData 來執行此命令:
filter.setInputFormat(trainingData);
這將使訓練和測試例項相容。或者你可以使用InputMappedClassifier
-
將過濾器應用於 testingData:
testingData = Filter.useFilter(testingData, filter);
-
分類!
1.獲取測試集中每個例項的類值
for (int j = 0; j < testingData.numInstances(); j++) {
double res = myCls.classifyInstance(testingData.get(j));
}
res
是一個 double 值,對應於 .arff
檔案中定義的標稱類。要獲得名義上的類使用:testintData.classAttribute().value((int)res)
2.獲取每個例項的概率分佈
for (int j = 0; j < testingData.numInstances(); j++) {
double[] dist = first.distributionForInstance(testInstances.get(j));
}
dist
是一個雙陣列,包含 .arff
檔案中定義的每個類的概率
注意。分類器應支援概率分佈,並使用:myClassifier.setProbabilityEstimates(true);
啟用它們