Proyectos de Subversion Moodle

Rev

Rev 11 | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 11 Rev 1441
Línea 29... Línea 29...
29
require_once(__DIR__ . '/fixtures/test_target_shortname_multiclass.php');
29
require_once(__DIR__ . '/fixtures/test_target_shortname_multiclass.php');
30
require_once(__DIR__ . '/fixtures/test_static_target_shortname.php');
30
require_once(__DIR__ . '/fixtures/test_static_target_shortname.php');
Línea 31... Línea 31...
31
 
31
 
Línea -... Línea 32...
-
 
32
require_once(__DIR__ . '/../../course/lib.php');
-
 
33
 
32
require_once(__DIR__ . '/../../course/lib.php');
34
use core_analytics\tests\mlbackend_helper_trait;
33
 
35
 
34
/**
36
/**
35
 * Unit tests for evaluation, training and prediction.
37
 * Unit tests for evaluation, training and prediction.
36
 *
38
 *
Línea 44... Línea 46...
44
 *
46
 *
45
 * @package   core_analytics
47
 * @package   core_analytics
46
 * @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
48
 * @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
47
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
49
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
48
 */
50
 */
49
class prediction_test extends \advanced_testcase {
51
final class prediction_test extends \advanced_testcase {
-
 
52
 
-
 
53
    use mlbackend_helper_trait;
Línea 50... Línea 54...
50
 
54
 
51
    /**
55
    /**
52
     * Purge all the mlbackend outputs.
56
     * Purge all the mlbackend outputs.
53
     *
57
     *
Línea 61... Línea 65...
61
 
65
 
62
        $models = \core_analytics\manager::get_all_models();
66
        $models = \core_analytics\manager::get_all_models();
63
        foreach ($models as $model) {
67
        foreach ($models as $model) {
64
            $model->delete();
68
            $model->delete();
-
 
69
        }
65
        }
70
        parent::tearDown();
Línea 66... Línea 71...
66
    }
71
    }
67
 
72
 
68
    /**
73
    /**
Línea 339... Línea 344...
339
    /**
344
    /**
340
     * provider_ml_training_and_prediction
345
     * provider_ml_training_and_prediction
341
     *
346
     *
342
     * @return array
347
     * @return array
343
     */
348
     */
344
    public function provider_ml_training_and_prediction() {
349
    public static function provider_ml_training_and_prediction(): array {
345
        $cases = array(
350
        $cases = array(
346
            'no_splitting' => array('\core\analytics\time_splitting\no_splitting', 0, 1),
351
            'no_splitting' => array('\core\analytics\time_splitting\no_splitting', 0, 1),
347
            'quarters' => array('\core\analytics\time_splitting\quarters', 3, 4)
352
            'quarters' => array('\core\analytics\time_splitting\quarters', 3, 4)
348
        );
353
        );
Línea 349... Línea 354...
349
 
354
 
350
        // We need to test all system prediction processors.
355
        // We need to test all system prediction processors.
351
        return $this->add_prediction_processors($cases);
356
        return static::add_prediction_processors($cases);
Línea 352... Línea 357...
352
    }
357
    }
353
 
358
 
354
    /**
359
    /**
Línea 415... Línea 420...
415
    /**
420
    /**
416
     * provider_ml_processors
421
     * provider_ml_processors
417
     *
422
     *
418
     * @return array
423
     * @return array
419
     */
424
     */
420
    public function provider_ml_processors() {
425
    public static function provider_ml_processors(): array {
421
        $cases = [
426
        $cases = [
422
            'case' => [],
427
            'case' => [],
423
        ];
428
        ];
Línea 424... Línea 429...
424
 
429
 
425
        // We need to test all system prediction processors.
430
        // We need to test all system prediction processors.
426
        return $this->add_prediction_processors($cases);
431
        return static::add_prediction_processors($cases);
427
    }
432
    }
428
    /**
433
    /**
429
     * Test the system classifiers returns.
434
     * Test the system classifiers returns.
430
     *
435
     *
Línea 505... Línea 510...
505
     * mlbackend plugins behave and expected and control properly backend errors even
510
     * mlbackend plugins behave and expected and control properly backend errors even
506
     * under weird situations.
511
     * under weird situations.
507
     *
512
     *
508
     * @return array
513
     * @return array
509
     */
514
     */
510
    public function provider_ml_classifiers_return() {
515
    public static function provider_ml_classifiers_return(): array {
511
        // Using verbose options as the first argument for readability.
516
        // Using verbose options as the first argument for readability.
512
        $cases = array(
517
        $cases = array(
513
            '1-samples' => array('maybe', 1, [0]),
518
            '1-samples' => array('maybe', 1, [0]),
514
            '2-samples-same-class' => array('maybe', 2, [0]),
519
            '2-samples-same-class' => array('maybe', 2, [0]),
515
            '2-samples-different-classes' => array('yes', 2, [0, 1]),
520
            '2-samples-different-classes' => array('yes', 2, [0, 1]),
516
            '4-samples-different-classes' => array('yes', 4, [0, 1])
521
            '4-samples-different-classes' => array('yes', 4, [0, 1])
517
        );
522
        );
Línea 518... Línea 523...
518
 
523
 
519
        // We need to test all system prediction processors.
524
        // We need to test all system prediction processors.
520
        return $this->add_prediction_processors($cases);
525
        return static::add_prediction_processors($cases);
Línea 521... Línea 526...
521
    }
526
    }
522
 
527
 
523
    /**
528
    /**
Línea 543... Línea 548...
543
        if ($predictionsprocessor->is_ready() !== true) {
548
        if ($predictionsprocessor->is_ready() !== true) {
544
            $this->markTestSkipped('Skipping ' . $predictionsprocessorclass . ' as the predictor is not ready.');
549
            $this->markTestSkipped('Skipping ' . $predictionsprocessorclass . ' as the predictor is not ready.');
545
        }
550
        }
546
        // Generate training courses.
551
        // Generate training courses.
547
        $ncourses = 5;
552
        $ncourses = 5;
548
        $this->generate_courses_multiclass($ncourses);
553
        $this->generate_courses(ncourses: $ncourses, ismulticlass: true);
549
        $model = $this->add_multiclass_model();
554
        $model = $this->add_multiclass_model();
550
        $model->update(true, false, $timesplittingid, get_class($predictionsprocessor));
555
        $model->update(true, false, $timesplittingid, get_class($predictionsprocessor));
551
        $results = $model->train();
556
        $results = $model->train();
Línea 552... Línea 557...
552
 
557
 
Línea 579... Línea 584...
579
    /**
584
    /**
580
     * Provider for the multi_classification test.
585
     * Provider for the multi_classification test.
581
     *
586
     *
582
     * @return array
587
     * @return array
583
     */
588
     */
584
    public function provider_test_multi_classifier() {
589
    public static function provider_test_multi_classifier(): array {
585
        $cases = array(
590
        $cases = array(
586
            'notimesplitting' => array('\core\analytics\time_splitting\no_splitting'),
591
            'notimesplitting' => array('\core\analytics\time_splitting\no_splitting'),
587
        );
592
        );
Línea 588... Línea 593...
588
 
593
 
589
        // Add all system prediction processors.
594
        // Add all system prediction processors.
590
        return $this->add_prediction_processors($cases);
595
        return static::add_prediction_processors($cases);
Línea 591... Línea 596...
591
    }
596
    }
592
 
597
 
593
    /**
598
    /**
Línea 775... Línea 780...
775
    /**
780
    /**
776
     * provider_ml_test_evaluation_configuration
781
     * provider_ml_test_evaluation_configuration
777
     *
782
     *
778
     * @return array
783
     * @return array
779
     */
784
     */
780
    public function provider_ml_test_evaluation_configuration() {
785
    public static function provider_ml_test_evaluation_configuration(): array {
781
 
-
 
782
        $cases = array(
786
        $cases = array(
783
            'bad' => array(
787
            'bad' => array(
784
                'modelquality' => 'random',
788
                'modelquality' => 'random',
785
                'ncourses' => 50,
789
                'ncourses' => 50,
786
                'expectedresults' => array(
790
                'expected' => array(
787
                    '\core\analytics\time_splitting\single_range' => \core_analytics\model::LOW_SCORE,
791
                    '\core\analytics\time_splitting\single_range' => \core_analytics\model::LOW_SCORE,
788
                    '\core\analytics\time_splitting\quarters' => \core_analytics\model::LOW_SCORE,
792
                    '\core\analytics\time_splitting\quarters' => \core_analytics\model::LOW_SCORE,
789
                )
793
                )
790
            ),
794
            ),
791
            'good' => array(
795
            'good' => array(
792
                'modelquality' => 'perfect',
796
                'modelquality' => 'perfect',
793
                'ncourses' => 50,
797
                'ncourses' => 50,
794
                'expectedresults' => array(
798
                'expected' => array(
795
                    '\core\analytics\time_splitting\single_range' => \core_analytics\model::OK,
799
                    '\core\analytics\time_splitting\single_range' => \core_analytics\model::OK,
796
                    '\core\analytics\time_splitting\quarters' => \core_analytics\model::OK,
800
                    '\core\analytics\time_splitting\quarters' => \core_analytics\model::OK,
797
                )
801
                )
798
            )
802
            )
799
        );
803
        );
800
        return $this->add_prediction_processors($cases);
804
        return static::add_prediction_processors($cases);
801
    }
805
    }
Línea 802... Línea 806...
802
 
806
 
803
    /**
807
    /**
804
     * add_random_model
808
     * add_random_model
Línea 856... Línea 860...
856
        $model = \core_analytics\model::create($target, $indicators);
860
        $model = \core_analytics\model::create($target, $indicators);
857
        return new \core_analytics\model($model->get_id());
861
        return new \core_analytics\model($model->get_id());
858
    }
862
    }
Línea 859... Línea 863...
859
 
863
 
860
    /**
-
 
861
     * Generates $ncourses courses
-
 
862
     *
-
 
863
     * @param  int $ncourses The number of courses to be generated.
-
 
864
     * @param  array $params Course params
-
 
865
     * @return null
-
 
866
     */
-
 
867
    protected function generate_courses($ncourses, array $params = []) {
-
 
868
 
-
 
869
        $params = $params + [
-
 
870
            'startdate' => mktime(0, 0, 0, 10, 24, 2015),
-
 
871
            'enddate' => mktime(0, 0, 0, 2, 24, 2016),
-
 
872
        ];
-
 
873
 
-
 
874
        for ($i = 0; $i < $ncourses; $i++) {
-
 
875
            $name = 'a' . random_string(10);
-
 
876
            $courseparams = array('shortname' => $name, 'fullname' => $name) + $params;
-
 
877
            $this->getDataGenerator()->create_course($courseparams);
-
 
878
        }
-
 
879
        for ($i = 0; $i < $ncourses; $i++) {
-
 
880
            $name = 'b' . random_string(10);
-
 
881
            $courseparams = array('shortname' => $name, 'fullname' => $name) + $params;
-
 
882
            $this->getDataGenerator()->create_course($courseparams);
-
 
883
        }
-
 
884
    }
-
 
885
 
-
 
886
    /**
-
 
887
     * Generates ncourses for multi-classification
-
 
888
     *
-
 
889
     * @param int $ncourses The number of courses to be generated.
-
 
890
     * @param array $params Course params
-
 
891
     * @return null
-
 
892
     */
-
 
893
    protected function generate_courses_multiclass($ncourses, array $params = []) {
-
 
894
 
-
 
895
        $params = $params + [
-
 
896
                'startdate' => mktime(0, 0, 0, 10, 24, 2015),
-
 
897
                'enddate' => mktime(0, 0, 0, 2, 24, 2016),
-
 
898
            ];
-
 
899
 
-
 
900
        for ($i = 0; $i < $ncourses; $i++) {
-
 
901
            $name = 'a' . random_string(10);
-
 
902
            $courseparams = array('shortname' => $name, 'fullname' => $name) + $params;
-
 
903
            $this->getDataGenerator()->create_course($courseparams);
-
 
904
        }
-
 
905
        for ($i = 0; $i < $ncourses; $i++) {
-
 
906
            $name = 'b' . random_string(10);
-
 
907
            $courseparams = array('shortname' => $name, 'fullname' => $name) + $params;
-
 
908
            $this->getDataGenerator()->create_course($courseparams);
-
 
909
        }
-
 
910
        for ($i = 0; $i < $ncourses; $i++) {
-
 
911
            $name = 'c' . random_string(10);
-
 
912
            $courseparams = array('shortname' => $name, 'fullname' => $name) + $params;
-
 
913
            $this->getDataGenerator()->create_course($courseparams);
-
 
914
        }
-
 
915
    }
-
 
916
 
-
 
917
    /**
864
    /**
918
     * Forces some configuration values.
865
     * Forces some configuration values.
919
     *
866
     *
920
     * @param array $forcedconfig
867
     * @param array $forcedconfig
921
     */
868
     */
Línea 953... Línea 900...
953
     * add_prediction_processors
900
     * add_prediction_processors
954
     *
901
     *
955
     * @param array $cases
902
     * @param array $cases
956
     * @return array
903
     * @return array
957
     */
904
     */
958
    protected function add_prediction_processors($cases) {
905
    protected static function add_prediction_processors($cases): array {
959
 
-
 
960
        $return = array();
906
        $return = array();
Línea 961... Línea 907...
961
 
907
 
962
        if (defined('TEST_MLBACKEND_PYTHON_HOST') && defined('TEST_MLBACKEND_PYTHON_PORT')
908
        if (defined('TEST_MLBACKEND_PYTHON_HOST') && defined('TEST_MLBACKEND_PYTHON_PORT')
963
                && defined('TEST_MLBACKEND_PYTHON_USERNAME') && defined('TEST_MLBACKEND_PYTHON_USERNAME')) {
909
                && defined('TEST_MLBACKEND_PYTHON_USERNAME') && defined('TEST_MLBACKEND_PYTHON_USERNAME')) {
Línea 968... Línea 914...
968
        $predictionprocessors = \core_analytics\manager::get_all_prediction_processors();
914
        $predictionprocessors = \core_analytics\manager::get_all_prediction_processors();
969
        foreach ($predictionprocessors as $classfullname => $predictionsprocessor) {
915
        foreach ($predictionprocessors as $classfullname => $predictionsprocessor) {
970
            foreach ($cases as $key => $case) {
916
            foreach ($cases as $key => $case) {
Línea 971... Línea 917...
971
 
917
 
972
                if (!$predictionsprocessor instanceof \mlbackend_python\processor || empty($testpythonserver)) {
918
                if (!$predictionsprocessor instanceof \mlbackend_python\processor || empty($testpythonserver)) {
973
                    $extraparams = ['predictionsprocessor' => $classfullname, 'forcedconfig' => null];
919
                    $extraparams = ['predictionsprocessorclass' => $classfullname, 'forcedconfig' => null];
974
                    $return[$key . '-' . $classfullname] = $case + $extraparams;
920
                    $return[$key . '-' . $classfullname] = $case + $extraparams;
Línea 975... Línea 921...
975
                } else {
921
                } else {
976
 
922
 
977
                    // We want the configuration to be forced during the test as things like importing models create new
923
                    // We want the configuration to be forced during the test as things like importing models create new
978
                    // instances of ML backend processors during the process.
924
                    // instances of ML backend processors during the process.
979
                    $forcedconfig = ['mlbackend_python' => ['useserver' => true, 'host' => TEST_MLBACKEND_PYTHON_HOST,
925
                    $forcedconfig = ['mlbackend_python' => ['useserver' => true, 'host' => TEST_MLBACKEND_PYTHON_HOST,
980
                        'port' => TEST_MLBACKEND_PYTHON_PORT, 'secure' => false, 'username' => TEST_MLBACKEND_PYTHON_USERNAME,
926
                        'port' => TEST_MLBACKEND_PYTHON_PORT, 'secure' => false, 'username' => TEST_MLBACKEND_PYTHON_USERNAME,
981
                        'password' => TEST_MLBACKEND_PYTHON_PASSWORD]];
927
                        'password' => TEST_MLBACKEND_PYTHON_PASSWORD]];
982
                    $casekey = $key . '-' . $classfullname . '-server';
928
                    $casekey = $key . '-' . $classfullname . '-server';
983
                    $return[$casekey] = $case + ['predictionsprocessor' => $classfullname, 'forcedconfig' => $forcedconfig];
929
                    $return[$casekey] = $case + ['predictionsprocessorclass' => $classfullname, 'forcedconfig' => $forcedconfig];
984
                }
930
                }
Línea 985... Línea 931...
985
            }
931
            }