2014-02-05 40 views
1

我用Weka的資源管理器:WEKA:分類實例與反序列化模型

  • 加載的ARFF文件
  • 應用StringToWordVector過濾
  • 選擇IBK作爲最好的分類
  • 生成/保存my_model.model二進制

在我的java代碼我反序列化模型:

URL curl = ClassUtility.findClasspathResource("models/my_model.model"); 
    final Classifier cls = (Classifier) weka.core.SerializationHelper.read(curl.openConnection().getInputStream()); 

現在,我有分類器,但我需要以某種方式過濾器上的信息。我得到的是:我如何準備一個實例以通過反序列化模型進行分類(我如何在分類之前應用過濾器) - (我必須分類的原始實例具有帶有令牌的字段文本。本來是要變換成新atributes列表)

我甚至嘗試,我設定的分類爲反序列化並使用FilteredClassifier過濾器StringToWordVector

的的
final StringToWordVector filter = new StringToWordVector(); 
    filter.setOptions(new String[]{"-C", "-P x_", "-L"}); 
    FilteredClassifier fcls = new FilteredClassifier(); 
    fcls.setFilter(filter); 
    fcls.setClassifier(cls); 

手動創建的實例以上也不起作用。它拋出該異常:線程「main」顯示java.lang.NullPointerException

例外:無輸出實例格式定義

我試圖避免被做在Java代碼中的訓練。它可能非常緩慢,前景是我可能有多個分類器來訓練(不同的算法),我希望我的應用程序能夠快速啓動。

回答

1

你的問題是你的模型不知道過濾器對數據做了什麼。 StringToWordVector過濾器會更改數據,但取決於輸入(訓練)數據。在此轉換數據集上訓練的模型僅適用於經過完全相同轉換的數據。爲了保證這一點,過濾器需要成爲你模型的一部分。

使用FilteredClassifier是正確的想法,但你必須從一開始就使用它:

  • 裝入ARFF文件
  • 選擇FilteredClassifier作爲分類
  • 選擇StringToWordVector作爲過濾它
  • 選擇IBk作爲FilteredClassifier的分類器
  • 生成/保存模型到my_model.binary

經過訓練和序列化的模型將包含初始化過濾器,包括有關如何轉換數據的信息。

1

另一種方法是對測試數據使用與訓練數據相同的過濾器。我通過分析來描述過程。在你的情況下,你只需要加載你的序列化分類器後的步驟。

  • 創建培訓文件(例如training.arff)
  • 創建一個從培訓文件實例。 Instances trainingData = ..
  • 使用StringToWordVector改變你的字符串屬性數表示:

示例代碼:

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分類

 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(); 
  • 創建測試文件(例如testing.arff)

  • 創建從訓練文件實例:Instances testingData=...

  • 負荷分類

示例代碼

Classifier myCls = (Classifier) weka.core.SerializationHelper.read(path+"mymodel.model"); 
  • 使用相同的StringToWordVector過濾器上面或創建testingData一個新的,但記得要使用trainingData此命令:filter.setInputFormat(trainingData);這將讓訓練集的格式,並不會增加單詞不在訓練集中。

  • 的過濾器應用到testingData:testingData = Filter.useFilter(testingData, filter);

  • 分類!

示例代碼

for (int j = 0; j < testingData.numInstances(); j++) { 
    double res = myCls.classifyInstance(testingData.get(j)); 
}