resultados divergentes del entrenamiento weka y el entrenamiento java

Estoy tratando de crear un "entrenamiento automatizado" usando la API de java de weka, pero supongo que estoy haciendo algo mal, cada vez que pruebo mi archivo ARFF a través de la interfaz de weka usando MultiLayerPerceptron con 10 Cross Validation o 66% Percentage Split obtengo algunos resultados satisfactorios (alrededor del 90%), pero cuando trato de probar el mismo archivo a través de la API de weka, cada prueba devuelve básicamente una coincidencia del 0% (cada fila devuelve falso)

aquí está el resultado de la interfaz gráfica de usuario de weka:

=== Evaluación en la división de prueba === === Resumen ===

Correctly Classified Instances          78               91.7647 %
Incorrectly Classified Instances         7                8.2353 %
Kappa statistic                          0.8081
Mean absolute error                      0.0817
Root mean squared error                  0.24  
Relative absolute error                 17.742  %
Root relative squared error             51.0603 %
Total Number of Instances               85     

=== Precisión detallada por clase ===

                TP Rate   FP Rate   Precision   Recall  F-Measure   ROC Area  Class
                 0.885     0.068      0.852     0.885     0.868      0.958    1
                 0.932     0.115      0.948     0.932     0.94       0.958    0
Weighted Avg.    0.918     0.101      0.919     0.918     0.918      0.958

=== Matriz de confusión ===

  a  b   <-- classified as
 23  3 |  a = 1
  4 55 |  b = 0

y aquí está el código que he usado en Java (en realidad está en .NET usando IKVM):

var classifier = new weka.classifiers.functions.MultilayerPerceptron();
classifier.setOptions(weka.core.Utils.splitOptions("-L 0.7 -M 0.3 -N 75 -V 0 -S 0 -E 20 -H a")); //these are the same options (the default options) when the test is run under weka gui

string trainingFile = Properties.Settings.Default.WekaTrainingFile; //the path to the same file I use to test on weka explorer
weka.core.Instances data = null;
data = new weka.core.Instances(new java.io.BufferedReader(new java.io.FileReader(trainingFile))); //loads the file
data.setClassIndex(data.numAttributes() - 1); //set the last column as the class attribute

cl.buildClassifier(data);

var tmp = System.IO.Path.GetTempFileName(); //creates a temp file to create an arff file with a single row with the instance I want to test taken from the arff file loaded previously
using (var f = System.IO.File.CreateText(tmp))
{
    //long code to read data from db and regenerate the line, simulating data coming from the source I really want to test
}

var dataToTest = new weka.core.Instances(new java.io.BufferedReader(new java.io.FileReader(tmp)));
dataToTest.setClassIndex(dataToTest.numAttributes() - 1);

double prediction = 0;

for (int i = 0; i < dataToTest.numInstances(); i++)
{
    weka.core.Instance curr = dataToTest.instance(i);
    weka.core.Instance inst = new weka.core.Instance(data.numAttributes());
    inst.setDataset(data);
    for (int n = 0; n < data.numAttributes(); n++)
    {
        weka.core.Attribute att = dataToTest.attribute(data.attribute(n).name());
        if (att != null)
        {
            if (att.isNominal())
            {
                if ((data.attribute(n).numValues() > 0) && (att.numValues() > 0))
                {
                    String label = curr.stringValue(att);
                    int index = data.attribute(n).indexOfValue(label);
                    if (index != -1)
                        inst.setValue(n, index);
                }
            }
            else if (att.isNumeric())
            {
                inst.setValue(n, curr.value(att));
            }
            else
            {
                throw new InvalidOperationException("Unhandled attribute type!");
            }
        }
    }
    prediction += cl.classifyInstance(inst);
}

//prediction is always 0 here, my ARFF file has two classes: 0 and 1, 92 zeroes and 159 ones

es divertido porque si cambio el clasificador a digamos NaiveBayes, los resultados coinciden con la prueba realizada a través de la interfaz gráfica de usuario de weka

preguntado el 12 de junio de 12 a las 16:06

2 Respuestas

Está utilizando una forma obsoleta de leer en archivos ARFF. Mira esto documentación. Prueba esto en su lugar:

 import weka.core.converters.ConverterUtils.DataSource;
 ...
 DataSource source = new DataSource("/some/where/data.arff");
 Instances data = source.getDataSet();

Tenga en cuenta que esa documentación también muestra cómo conectarse directamente a una base de datos y omitir la creación de archivos ARFF temporales. Además, podría leer de la base de datos y crear instancias manualmente para completar el objeto Instancias.

Finalmente, si simplemente cambiando el tipo de clasificador en la parte superior del código a NaiveBayes resolvió el problema, verifique las opciones en su weka gui para MultilayerPerceptron, para ver si son diferentes de los valores predeterminados (diferentes configuraciones pueden causar que el mismo tipo de clasificador producir resultados diferentes).

Actualizar: parece que está utilizando datos de prueba diferentes en su código que en su GUI weka (de una base de datos frente a un pliegue del archivo de entrenamiento original); también podría ser el caso de que los datos particulares en su base de datos realmente se vean como class 0 al clasificador MLP. Para verificar si este es el caso, puede usar la interfaz weka para dividir su entrenamiento arff en conjuntos de entrenamiento/prueba y luego repetir el experimento original en su código. Si los resultados son los mismos que los de la interfaz gráfica de usuario, hay un problema con sus datos. Si los resultados son diferentes, entonces debemos mirar más de cerca el código. La función que llamarías es esta (del doctor):

public Instances trainCV(int numFolds, int numFold)

Respondido el 13 de junio de 12 a las 17:06

Supongo que tuvo algo que ver con la forma en que estaba leyendo el archivo arff, simplemente cambié a la forma en que usted (y la documentación) sugirieron y está funcionando ahora, ¡muchas gracias! - leandro koiti

Yo tuve el mismo problema.

Weka me dio resultados diferentes en el Explorador en comparación con una validación cruzada en Java.

Algo que ayudó:

Instances dataSet = ...;
dataSet.stratify(numOfFolds); // use this
         //before splitting the dataset into train and test set!

Respondido el 29 de diciembre de 14 a las 18:12

Hola @Dave, ¡gracias por tu respuesta! Tu podrías querer lee esta guía sobre escribir respuestas en StackOverflow siguiendo sus pautas. También sería útil si pudiera ampliar por qué dataSet.stratify(numOfFolds) resolvió su problema o una explicación sobre lo que hace. Tal vez un enlace a la documentación al respecto :) - André

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.