我使用了Weka Explorer:
在我的java代码中,我反模型化了模型:
URL curl = ClassUtility.findClasspathResource( "models/my_model.model" );
final Classifier cls = (Classifier) weka.core.SerializationHelper.read( curl.openConnection().getInputStream() );
现在,我有分类器,但我需要以某种方式获取有关过滤器的信息。我得到的是:如何通过我的反序列化模型准备要分类的实例(如何在分类之前应用过滤器) - (我必须分类的原始实例有一个带有标记的字段文本。过滤器应该将其转换为新的属性列表)
我甚至尝试使用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代码中进行培训。它可能非常慢,前景是我可能有多个分类器来训练(不同的算法),我希望我的应用程序能够快速启动。
答案 0 :(得分:1)
您的问题是您的模型对过滤器对数据的处理方式一无所知。 StringToWordVector
过滤器会更改数据,但会根据输入(训练)数据进行更改。在此转换数据集上训练的模型仅适用于经历完全相同转换的数据。为了保证这一点,过滤器需要成为模型的一部分。
使用FilteredClassifier
是正确的想法,但您必须从头开始使用它:
FilteredClassifier
作为分类器StringToWordVector
作为过滤器IBk
作为FilteredClassifier
经过训练和序列化的模型还将包含初始化过滤器,包括有关如何转换数据的信息。
答案 1 :(得分:1)
另一种方法是对测试数据使用与训练数据相同的过滤器。我分析地描述了这个过程。在您的情况下,您只需在加载序列化分类器后按照步骤操作。
Instances trainingData = ..
示例代码:
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);
分类<!/ p>
示例代码
for (int j = 0; j < testingData.numInstances(); j++) {
double res = myCls.classifyInstance(testingData.get(j));
}