2

I want to create a WEKA Java program that reads a group of newly created data that will be fed to a premade model from the GUI version.

Here is the program:

import java.util.ArrayList;
import weka.classifiers.Classifier;
import weka.core.Attribute;
import weka.core.DenseInstance;
import weka.core.Instances;
import weka.core.Utils;


public class UseModelWithData {

  public static void main(String[] args) throws Exception {
    // load model
    String rootPath = "G:/";
    Classifier classifier = (Classifier) weka.core.SerializationHelper.read(rootPath+"j48.model");

    // create instances
    Attribute attr1 = new Attribute("age");
    Attribute attr2 = new Attribute("menopause");
    Attribute attr3 = new Attribute("tumor-size");
    Attribute attr4 = new Attribute("inv-nodes");
    Attribute attr5 = new Attribute("node-caps");
    Attribute attr6 = new Attribute("deg-malig");
    Attribute attr7 = new Attribute("breast");
    Attribute attr8 = new Attribute("breast-quad");
    Attribute attr9 = new Attribute("irradiat");
    Attribute attr10 = new Attribute("Class");

    ArrayList<Attribute> attributes = new ArrayList<Attribute>();
    attributes.add(attr1);
    attributes.add(attr2);
    attributes.add(attr3);
    attributes.add(attr4);
    attributes.add(attr5);
    attributes.add(attr6);
    attributes.add(attr7);
    attributes.add(attr8);
    attributes.add(attr9);
    attributes.add(attr10);

    // predict instance class values
    Instances testing = new Instances("Test dataset", attributes, 0);

    // add data
    double[] values = new double[testing.numAttributes()];
    values[0] = testing.attribute(0).addStringValue("60-69");
    values[1] = testing.attribute(1).addStringValue("ge40");
    values[2] = testing.attribute(2).addStringValue("10-14");
    values[3] = testing.attribute(3).addStringValue("15-17");
    values[4] = testing.attribute(4).addStringValue("yes");
    values[5] = testing.attribute(5).addStringValue("2");
    values[6] = testing.attribute(6).addStringValue("right");
    values[7] = testing.attribute(7).addStringValue("right_up");
    values[8] = testing.attribute(0).addStringValue("yes");
    values[9] = Utils.missingValue();

    // add data to instance
    testing.add(new DenseInstance(1.0, values));
    // instance row to predict
    int index = 10;
    // perform prediction
    double myValue = classifier.classifyInstance(testing.instance(10));
    // get the name of class value
    String prediction = testing.classAttribute().value((int) myValue);

    System.out.println("The predicted value of the instance [" 
        + Integer.toString(index) + "]: " + prediction);

  }

}

My references include:

So far the part where I create a new Instance inside the script causes the following error:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 10, Size: 1

in the line

double myValue = classifier.classifyInstance(testing.instance(10));

I just want to use a latest row of instance values to a premade WEKA model. How do I solve this?


Resources

Community
  • 1
  • 1

1 Answers1

2

You have the error because you are trying to access the 11th instance and have only created one.

If you always want to access the last instance you might try the following:

double myValue = classifier.classifyInstance(testing.lastInstance());  

Additionally, I don't believe that you are creating the instances you hope for. After looking at your provided ".arff" file, which I believe you are trying to mimic, I think you should proceed making instances as follows:

FastVector      atts;
FastVector      attAge;

Instances       testing;
double[]        vals;

// 1. set up attributes
atts = new FastVector();

//age
attAge = new FastVector();
attAge.addElement("10-19");
attAge.addElement("20-29");
attAge.addElement("30-39");
attAge.addElement("40-49");
attAge.addElement("50-59");
attAge.addElement("60-69");
attAge.addElement("70-79");
attAge.addElement("80-89");
attAge.addElement("90-99");
atts.addElement(new Attribute("age", attAge));

// 2. create Instances object
testing = new Instances("breast-cancer", atts, 0);

// 3. fill with data
vals = new double[testing.numAttributes()];
vals[0] = attAge.indexOf("10-19");
testing.add(new DenseInstance(1.0, vals));

// 4. output data
System.out.println(testing);

Of course I did not create the whole dataset, but the technique would be the same.

Walter
  • 2,811
  • 2
  • 21
  • 23
  • Thank you but is it possible to not create an ARFF file but instead have the data just fed into a model through variables? –  Nov 20 '13 at 23:15
  • 1
    In the above code we are making an instance, not an .arff, but Weka does require that you have an instance to make predictions. However, it is possible to output the source code for J48, and you may be able to modify this to fit your prediction needs. http://stackoverflow.com/questions/19278386/weka-predict-classifcation-node/19286903#19286903 may point you in a helpful direction. – Walter Nov 20 '13 at 23:21