2017-06-14 199 views
1

我正在嘗試使用OpenNLP對發票進行分類。根據它的描述,我將它分成兩類。我已經構建了一個包含20K描述的培訓文件,並將其標記爲正確的類。培訓OpenNLP文檔分類

訓練數據看起來像(第一列是一個代碼,即我的類中使用,而第二列是發票說明):

85171231 IPHONE 5S CINZA ESPACIAL 16GB (ME432BZA) 
85171231 Galaxy S6 SM-G920I 
85171231 motorola - MOTO G5 XT1672 
00000000 MOTONETA ITALIKA AT110 
00000000 CJ BOX UNIBOX MOLA 138X57X188 VINHO 

從OpenNLP使用DocumentCategorizer,我達到98.5%正確性。但是,爲了提高效率,我選擇了錯誤的分類文檔並用它來擴展訓練數據。

例如,當我第一次運行它時,「MOTONETA ITALIKA AT110」被分類爲「85171231」。沒關係,因爲進入第一次運行時,「MOTONETA ITALIKA AT110」未被分類。所以,我教了分類器明確地把「MOTONETA ITALIKA AT110」標記爲「00000000」。

但是,再次運行OpenNLP,即使訓練數據包含「000000」的顯式映射,OpenNLP也堅持將其歸類爲「85171231」。

所以我的問題是:我在教OpenNLP賴特嗎?我如何提高效率?

,我正在使用的代碼是:

MarkableFileInputStreamFactory dataIn = new MarkableFileInputStreamFactory("data.train"); 

ObjectStream<String> lineStream = new PlainTextByLineStream(dataIn, StandardCharsets.UTF_8); 
ObjectStream<DocumentSample> sampleStream = new DocumentSampleStream(lineStream); 

TrainingParameters params = new TrainingParameters(); 
params.put(TrainingParameters.ITERATIONS_PARAM, "100"); 
params.put(TrainingParameters.CUTOFF_PARAM, "0"); 

DoccatModel model = DocumentCategorizerME.train("pt", sampleStream, params, new DoccatFactory()); 

DocumentCategorizer doccat = new DocumentCategorizerME(model); 
double[] aProbs = doccat.categorize("MOTONETA ITALIKA AT110".replaceAll("[^A-Za-z0-9 ]", " ").split(" ")); 
doccat.getBestCategory(aProbs); 

回答

3

默認情況下,DocumentCategorizer將使用文字包。這意味着沒有考慮術語的順序。 如果在85171231組中有高頻出現MOTONETA ITALIKA AT110的任何項,分類器將傾向於使用該組。

您有幾種選擇:

  • 您可以添加的MOTONETA ITALIKA AT110更多的變種到組000000;
  • 嘗試更改特徵生成器。

第二個選擇是改變你的模型的創建,像這樣:

int minNgramSize = 2; 
int maxNgramSize = 3; 
DoccatFactory customFactory = new DoccatFactory(
    new FeatureGenerator[]{ 
     new BagOfWordsFeatureGenerator(), 
     new NGramFeatureGenerator(minNgramSize, maxNgramSize) 
    } 
); 
DoccatModel model = DocumentCategorizerME.train("pt", sampleStream, params, customFactory); 

您可以通過刪除BagOfWordsFeatureGenerator和不斷變化的最小和最大的ngram尺寸與功能發揮發電機。