Как выразить обоснование классификации экземпляров Weka? - PullRequest
0 голосов
/ 27 октября 2018

Справочная информация:

Если я открою графический интерфейс Weka Explorer, обучу дерево J48 и протестирую, используя наборы обучения и тестирования NSL-KDD, будет получено сокращенное дерево. Графический интерфейс Weka Explorer выражает алгоритмы, обосновывающие, будет ли что-то классифицироваться как аномалия или нет в терминах запросов, таких как src_bytes <= 28 </em>.

Снимок экрана графического интерфейса пользователя Weka Explorer, на котором показано обрезанное дерево

Вопрос:

Обращаясь к примеру с обрезанным деревом, созданному с помощью графического интерфейса Weka Explorer, как программно заставить weka выразить обоснование для каждой классификации экземпляров в Java?

т.е. Экземпляр A был классифицирован как аномалия как src_bytes <28 && dst_host_srv_count <88 && dst_bytes <3 и т. д. </p>

Пока я смог:

  • Обучите и протестируйте дерево J48 в наборе данных NSL-KDD.

  • Вывести описание дерева J48 в Java.

  • Возвращает дерево J48 как оператор if-then.

Но Я просто понятия не имею, как во время итерации каждого экземпляра на этапе тестирования выражать обоснование каждой классификации; без того, чтобы каждый раз вручную выводить дерево J48 в виде оператора if-then и добавлять многочисленные выражения println, когда каждое из них было запущено (что я действительно предпочел бы не делать, так как это значительно увеличило бы требования вмешательства человека в долгосрочной перспективе).

Дополнительные снимки экрана:

Снимок экрана 'описания дерева J48 в Java'

Снимок экрана 'дерева J48 как оператора if-then'

Код:

    public class Junction_Tree {

    String train_path = "KDDTrain+.arff";
    String test_path = "KDDTest+.arff";
    double accuracy;
    double recall;
    double precision;
    int correctPredictions;
    int incorrectPredictions;
    int numAnomaliesDetected;
    int numNetworkRecords;

    public void run() {
        try {
            Instances train = DataSource.read(train_path);
            Instances test = DataSource.read(test_path);
            train.setClassIndex(train.numAttributes() - 1);
            test.setClassIndex(test.numAttributes() - 1);

            if (!train.equalHeaders(test))
                throw new IllegalArgumentException("datasets are not compatible..");

            Remove rm = new Remove();
            rm.setAttributeIndices("1");

            J48 j48 = new J48();
            j48.setUnpruned(true);

            FilteredClassifier fc = new FilteredClassifier();
            fc.setFilter(rm);
            fc.setClassifier(j48);

            fc.buildClassifier(train);

            numAnomaliesDetected = 0;
            numNetworkRecords = 0;
            int n_ana_p = 0;
            int ana_p = 0;
            correctPredictions = 0;
            incorrectPredictions = 0;

            for (int i = 0; i < test.numInstances(); i++) {
                double pred = fc.classifyInstance(test.instance(i));
                String a = "anomaly";
                String actual;
                String predicted;
                actual = test.classAttribute().value((int) test.instance(i).classValue());
                predicted = test.classAttribute().value((int) pred);

                if (actual.equalsIgnoreCase(a))
                    numAnomaliesDetected++;
                if (actual.equalsIgnoreCase(predicted))
                    correctPredictions++;
                if (!actual.equalsIgnoreCase(predicted))
                    incorrectPredictions++;
                if (actual.equalsIgnoreCase(a) && predicted.equalsIgnoreCase(a))
                    ana_p++;
                if ((!actual.equalsIgnoreCase(a)) && predicted.equalsIgnoreCase(a))
                    n_ana_p++;
                numNetworkRecords++;
            }
            accuracy = (correctPredictions * 100) / (correctPredictions + incorrectPredictions);
            recall = ana_p * 100 / (numAnomaliesDetected);
            precision = ana_p * 100 / (ana_p + n_ana_p);

            System.out.println("\n\naccuracy: " + accuracy + ", Correct Predictions: " + correctPredictions
                    + ", Incorrect Predictions: " + incorrectPredictions);

        writeFile(j48.toSource(J48_if-then.java));

        writeFile(j48.toString());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Junction_Tree JT1 = new Junction_Tree();
        JT1.run();
    }

}

1 Ответ

0 голосов
/ 27 октября 2018

Я никогда не использовал его сам, но согласно документации WEKA класс J48 включает метод getMembershipValues. Этот метод должен возвращать массив, который указывает членство узла в экземпляре. Одно из немногих упоминаний этого метода, по-видимому, содержится в этой ветке на форумах WEKA.

Кроме этого, я не могу найти никакой информации о возможных альтернативах, кроме той, которую вы упомянули.

...