我有一组观测值对(值,类别)。值是自然数。只有两个类别。我预期在单一决策点上很容易区分这些类别,例如,如果值<10,则为类别A,如果值>=10,则为类别B。唯一的难点是类别之间在决策边界附近有一些重叠。
对于这个问题,有没有一种快速且轻量级的方法来更新观测值并在Java中对新数据点进行分类?理想的情况是这样的:
classifier.addObservation(observation);classifier.classify(value);
解决方案将展示一个用于此目的的Java包,并说明你选择该算法的理由。
回答:
经过一番搜索后,我最终使用了Weka。特别是,我使用了朴素贝叶斯分类器。他们的数据结构有点特别,但它有效且速度很快。
package agent.agenttype.ijcai;import weka.classifiers.Classifier;import weka.classifiers.bayes.NaiveBayes;import weka.core.Attribute;import weka.core.FastVector;import weka.core.Instance;import weka.core.Instances;import weka.core.SparseInstance;public class Example { public static enum ClassLabel {A, B}; Instances trainingSet; FastVector att = new FastVector(2); FastVector cl = new FastVector(2); public Example(){ //添加类别标签 cl.addElement(ClassLabel.values()[0].name()); cl.addElement(ClassLabel.values()[1].name()); //设置我们的值属性的名称 Attribute Attribute1 = new Attribute("Value"); //设置我们的类别标签属性的名称 Attribute ClassAttribute = new Attribute("Label", cl); att.addElement(Attribute1); att.addElement(ClassAttribute); //创建使用我们的属性来解释实例的训练集 trainingSet = new Instances("TrainingSet", att, 2); trainingSet.setClassIndex(1);//告诉我们的训练集,实例的索引2是类别标签 } public void addObservationToEdge(int value, ClassLabel classLabel){ Instance instance = new SparseInstance(2); instance.setValue((Attribute)att.elementAt(0), value); //设置值 instance.setValue((Attribute)att.elementAt(1), classLabel.name());//设置我们的 trainingSet.add(instance); } public ClassLabel classifyValue( int value) throws Exception{ Instance instanceForClassification = new SparseInstance(1); instanceForClassification.setValue((Attribute)att.elementAt(0), value); instanceForClassification.setDataset(trainingSet);//使实例从训练集中继承属性标签 Classifier cModel = (Classifier)new NaiveBayes();//创建朴素贝叶斯分类器 cModel.buildClassifier(trainingSet); int labelNumber = (int) cModel.classifyInstance(instanceForClassification); return ClassLabel.values()[labelNumber]; } public static void main(String[] args){ Example example = new Example(); example.addObservationToEdge(1, ClassLabel.A); example.addObservationToEdge(2, ClassLabel.A); example.addObservationToEdge(5, ClassLabel.A); example.addObservationToEdge(11, ClassLabel.A); example.addObservationToEdge(9, ClassLabel.B); example.addObservationToEdge(12, ClassLabel.B); example.addObservationToEdge(15, ClassLabel.B); example.addObservationToEdge(20, ClassLabel.B); try { //打印分类结果 for(int i = 0; i<20; i++){ System.out.println("Value: " + i + " Class Label:" + example.classifyValue(i)); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
输出:
Value: 0 Class Label:AValue: 1 Class Label:AValue: 2 Class Label:AValue: 3 Class Label:AValue: 4 Class Label:AValue: 5 Class Label:AValue: 6 Class Label:AValue: 7 Class Label:AValue: 8 Class Label:AValue: 9 Class Label:AValue: 10 Class Label:BValue: 11 Class Label:BValue: 12 Class Label:BValue: 13 Class Label:BValue: 14 Class Label:BValue: 15 Class Label:BValue: 16 Class Label:BValue: 17 Class Label:BValue: 18 Class Label:BValue: 19 Class Label:B