2017-05-19 1 views
-1

J'ai un petit problème avec mon code. J'utilise la bibliothèque WEKA dans le projet Android.WEKA sur Android: java.lang.ArrayIndexOutOfBoundsException: length = 30; index = 30

Je souhaite obtenir des données à partir d'un sqlite db.

Je ne peux pas utiliser DatabaseLoader classe, donc je créé les instances d'objets de cette manière:

public Instances getDatasetFromDB(String tableName, String[] select){ 

     Log.i(TAG, "Getting instances from Db"); 

     Instances result = null; 
     open(); 

     Cursor csr = query(tableName, select, null, null, null); 
     if(csr.getCount() != 0){ 
      Weka weka = new Weka(); 
      Instances centroids = weka.create_Instances("Centroids"); 
      List<Instance> list = new ArrayList<>(); 
      List<String> classType = new ArrayList<>(); 
      while(csr.moveToNext()){ 
       String type = csr.getString(csr.getColumnIndex("classType")); 
       classType.add(type); 
       list.add(cursorToInstance(csr)); 
      } 
      result = new Instances(weka.addInstance(centroids, list, classType)); 
     } 
     close(); 
     return result; 
    } 

/*Function of Weka Object*/ 
public Instances create_Instances(String name){ 
     FastVector wekaAttributes = new FastVector(); 

     for (int i = 0; i<ApplicationProperties.getnFeature(); i++) 
      wekaAttributes.addElement(new Attribute(GenericUtils.typeData(i))); 

     Instances dataSet = new Instances(name, wekaAttributes, 0); 

     int n_activity = ApplicationProperties.getnActivity(); 
     FastVector classNominal = new FastVector(n_activity); 
     for (int i=0; i<n_activity; i++){ 
      classNominal.addElement(GenericUtils.idToActivity(i)); 
     } 
     dataSet.insertAttributeAt(new Attribute("classType", classNominal), dataSet.numAttributes()); 

     dataSet.setClassIndex(dataSet.numAttributes() - 1); 

     return dataSet; 
    } 

public Instances addInstance(Instances instances, List<Instance> list, List<String> type){ 
     Iterator<Instance> i = list.iterator(); 
     Iterator<String> j = type.iterator(); 
     while(i.hasNext() && j.hasNext()){ 
      Instance inst = i.next(); 
      inst.setDataset(instances); 
      double[] tmp = inst.toDoubleArray(); 

      String t = j.next(); 
      tmp[tmp.length-1] = GenericUtils.activityToId(t); 

      instances.add(new Instance(1.0, tmp)); 
     } 
     return instances; 
    } 

Ce code renvoie ceci:

@relation Centroids 

@attribute acc_max_x numeric 
@attribute acc_min_x numeric 
@attribute acc_mean_x numeric 
@attribute acc_std_x numeric 
@attribute acc_rms_x numeric 
@attribute acc_max_y numeric 
@attribute acc_min_y numeric 
@attribute acc_mean_y numeric 
@attribute acc_std_y numeric 
@attribute acc_rms_y numeric 
@attribute acc_max_z numeric 
@attribute acc_min_z numeric 
@attribute acc_mean_z numeric 
@attribute acc_std_z numeric 
@attribute acc_rms_z numeric 
@attribute gyro_max_x numeric 
@attribute gyro_min_x numeric 
@attribute gyro_mean_x numeric 
@attribute gyro_std_x numeric 
@attribute gyro_rms_x numeric 
@attribute gyro_max_y numeric 
@attribute gyro_min_y numeric 
@attribute gyro_mean_y numeric 
@attribute gyro_std_y numeric 
@attribute gyro_rms_y numeric 
@attribute gyro_max_z numeric 
@attribute gyro_min_z numeric 
@attribute gyro_mean_z numeric 
@attribute gyro_std_z numeric 
@attribute gyro_rms_z numeric 
@attribute classType {Fermo,Cammino,Corro,Veicolo} 

@data 
0.020366,-0.049443,9.699037,0.011994,0.020186,0.050924,-0.010524,0.035161,0.,0.038155,9.739549,9.656769,0,9.715311,9.699051,0.078441,-0.078495,0.000719,0.02763,0.027849,0.024923,-0.026115,-0.000634,0.009217,0.009327,0.023255,-0.020865,0,0.007926,0 
0.839357,-0.582571,9.413732,0.264762,0.923015,-0.825299,-1.967114,-1.385451,0.210502,1.658316,10.171442,8.569599,0,9.459311,9.443481,0.564504,-0.654348,0.000326,0.123502,0.136114,0.707076,-0.658781,0.00107,0.134813,0.137025,0.628173,-0.686233,0,0.113967,1 
0.994211,-0.382427,6.74315,0.325523,0.683864,7.406008,6.538764,6.994379,0.1867,7.035604,7.668721,5.612368,0,6.779348,6.768002,0.11319,-0.174827,0.000703,0.019038,0.030755,0.482416,-0.118256,0.004761,0.038078,0.040536,0.315722,-0.143182,0,0.03144,2 
0.60635,-1.418608,9.763421,0.315172,0.320185,0.627898,-0.514171,-0.040041,0.201248,0.20899,9.885362,9.643541,0,9.779818,9.763464,6.832833,0,-0.02351,0.395488,0.396995,4.230241,-0.002749,0.014193,0.244926,0.244967,0.000917,-5.28093,0,0.312452,3 
... 
... 

Le problème est lorsque le code arrive à ce point :

Instances data = new Instances(database.getDatasetFromDB(TrainingSetModel.TBL_NAME, TrainingSetModel.COLUMNS_DATASET)); 
data.setClassIndex(data.numAttributes()-1); 
ibk.buildClassifier(data); 

Ceci est la trace de la pile:

W/System.err: java.lang.ArrayIndexOutOfBoundsException: length=30; index=30 
W/System.err:  at weka.core.Instance.isMissing(Instance.java:395) 
W/System.err:  at weka.core.Instance.classIsMissing(Instance.java:221) 
W/System.err:  at weka.core.Capabilities.test(Capabilities.java:1132) 
W/System.err:  at weka.core.Capabilities.test(Capabilities.java:1023) 
W/System.err:  at weka.core.Capabilities.testWithFail(Capabilities.java:1302) 
W/System.err:  at weka.classifiers.lazy.IBk.buildClassifier(IBk.java:487) 
W/System.err:  at com.unipa.uniar.classification.Knn.getInstances(Knn.java:36) 
W/System.err:  at com.unipa.uniar.classification.Knn.<init>(Knn.java:26) 
W/System.err:  at com.unipa.uniar.classification.ClassificationTask.doInBackground(ClassificationTask.java:54) 
W/System.err:  at com.unipa.uniar.classification.ClassificationTask.doInBackground(ClassificationTask.java:19) 
W/System.err:  at android.os.AsyncTask$2.call(AsyncTask.java:304) 
W/System.err:  at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
W/System.err:  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
W/System.err:  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
W/System.err:  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
W/System.err:  at java.lang.Thread.run(Thread.java:762) 

Je ne comprends pas quel est le problème de mon code.

Les instances d'objets a 31 attributs [0-30], je ne comprends pas pourquoi la limite est 30.

MISE À JOUR:

je teste s'il y a des valeurs manquantes en ajoutant ce code:

private void getInstances() throws Exception { 
     UniAR_DBAdapter database = new UniAR_DBAdapter(context); 
     data = new Instances(database.getDatasetFromDB(TrainingSetModel.TBL_NAME, TrainingSetModel.COLUMNS_DATASET)); 
     data.setClassIndex(data.numAttributes()-1); 
     for (int i=0; i<data.numInstances(); i++){ 
      for (int j=0; j < data.numAttributes()-1; j++){ 
       if(data.instance(i).isMissing(j)) { 
        Log.e(TAG, "Instance: " + String.valueOf(i) + "Attribute: " + String.valueOf(j) + "Missing"); 
        data.instance(i).setClassMissing(); 
       } 
      } 
     } 
     ibk.buildClassifier(data); 
    } 

Aucun journal n'a été imprimé. Donc, il n'y a pas d'attributs manquants.

+0

Ce n'est pas le cas. Il a 30 attributs, 0-29. 30 est hors limites. C'est ce que ça veut dire quand on dit longueur: 30 –

+0

Je sais que ça veut dire "longueur: 30". Si vous comptez le nombre d'attributs, il est 31, y compris l'attribut de classe. Pourquoi dites-vous que sont 30 [0-29]? Ai-je tort de compter? – Federico

Répondre

0

À partir du journal, vous semblez avoir une valeur non définie ou manquante. vous devez utiliser

data.setClassMissing(); 

définir la valeur de classe instances à manquer.

+0

J'ajoute du code pour vérifier tous les attributs et pour trouver si certaines valeurs ne sont pas définies ou manquantes. Il n'y a pas de valeur manquante. – Federico