MDL-59661 analytics: Export models training data
authorDavid Monllao <davidm@moodle.com>
Thu, 10 Aug 2017 11:43:17 +0000 (13:43 +0200)
committerDavid Monllao <david.monllao@gmail.com>
Thu, 17 Aug 2017 18:51:56 +0000 (20:51 +0200)
admin/tool/analytics/classes/output/models_list.php
admin/tool/analytics/lang/en/tool_analytics.php
admin/tool/analytics/model.php
analytics/classes/dataset_manager.php
analytics/classes/model.php

index 36f1feb..d524595 100644 (file)
@@ -139,6 +139,7 @@ class models_list implements \renderable, \templatable {
                 $actionsmenu->add($icon);
             }
 
+            // Get predictions.
             if ($modeldata->enabled && !empty($modeldata->timesplitting)) {
                 $url = new \moodle_url('model.php', array('action' => 'getpredictions', 'id' => $model->get_id()));
                 $icon = new \action_menu_link_secondary($url, new \pix_icon('i/notifications',
@@ -154,6 +155,14 @@ class models_list implements \renderable, \templatable {
                 $actionsmenu->add($icon);
             }
 
+            // Export training data.
+            if (!$model->is_static() && $model->is_trained()) {
+                $url = new \moodle_url('model.php', array('action' => 'export', 'id' => $model->get_id()));
+                $icon = new \action_menu_link_secondary($url, new \pix_icon('i/export',
+                    get_string('exporttrainingdata', 'tool_analytics')), get_string('export', 'tool_analytics'));
+                $actionsmenu->add($icon);
+            }
+
             $modeldata->actions = $actionsmenu->export_for_template($output);
 
             $data->models[] = $modeldata;
index eba2a8f..4922a51 100644 (file)
@@ -36,13 +36,16 @@ $string['enabled'] = 'Enabled';
 $string['errorcantenablenotimesplitting'] = 'You need to select a time splitting method before enabling the model';
 $string['errornoenabledandtrainedmodels'] = 'There are not enabled and trained models to predict';
 $string['errornoenabledmodels'] = 'There are not enabled models to train';
+$string['errornoexport'] = 'Only trained models can be exported';
 $string['errornostaticedit'] = 'Models based on assumptions can not be edited';
 $string['errornostaticevaluated'] = 'Models based on assumptions can not be evaluated, they are always 100% correct according to how they were defined';
 $string['errornostaticlog'] = 'Models based on assumptions can not be evaluated, there is no preformance log';
+$string['errortrainingdataexport'] = 'The model training data could not be exported';
 $string['evaluate'] = 'Evaluate';
 $string['evaluatemodel'] = 'Evaluate model';
 $string['evaluationinbatches'] = 'The site contents are calculated and stored in batches, during evaluation you can stop the process at any moment, the next time you run it it will continue from the point you stopped it.';
-$string['trainandpredictmodel'] = 'Training model and calculating predictions';
+$string['export'] = 'Export';
+$string['exporttrainingdata'] = 'Export training data';
 $string['getpredictionsresultscli'] = 'Results using {$a->name} (id: {$a->id}) course duration splitting';
 $string['getpredictionsresults'] = 'Results using {$a->name} course duration splitting';
 $string['extrainfo'] = 'Info';
@@ -68,6 +71,7 @@ $string['predictionprocessfinished'] = 'Prediction process finished';
 $string['samestartdate'] = 'Current start date is good';
 $string['sameenddate'] = 'Current end date is good';
 $string['target'] = 'Target';
+$string['trainandpredictmodel'] = 'Training model and calculating predictions';
 $string['trainingprocessfinished'] = 'Training process finished';
 $string['trainingresults'] = 'Training results';
 $string['trainmodels'] = 'Train models';
index 9ef3c3d..daf62cf 100644 (file)
@@ -57,6 +57,9 @@ switch ($action) {
     case 'disable':
         $title = get_string('disable');
         break;
+    case 'export':
+        $title = get_string('export', 'tool_analytics');
+        break;
 
     default:
         throw new moodle_exception('errorunknownaction', 'analytics');
@@ -162,6 +165,22 @@ switch ($action) {
         $modellogstable = new \tool_analytics\output\model_logs('model-' . $model->get_id(), $model);
         echo $renderer->render_table($modellogstable);
         break;
+
+    case 'export':
+
+        if ($model->is_static() || !$model->is_trained()) {
+            throw new moodle_exception('errornoexport', 'tool_analytics');
+        }
+
+        $file = $model->get_training_data();
+        if (!$file) {
+            redirect(new \moodle_url('/admin/tool/analytics/index.php'), get_string('errortrainingdataexport', 'tool_analytics'),
+                null, \core\output\notification::NOTIFY_ERROR);
+        }
+
+        $filename = 'training-data.' . $model->get_id() . '.' . time() . '.csv';
+        send_file($file, $filename, null, 0, false, true);
+        break;
 }
 
 echo $OUTPUT->footer();
index 052b7ed..882d8dc 100644 (file)
@@ -91,6 +91,7 @@ class dataset_manager {
     /**
      * Constructor method.
      *
+     * @throws \coding_exception
      * @param int $modelid
      * @param int $analysableid
      * @param string $timesplittingid
@@ -320,6 +321,37 @@ class dataset_manager {
         return $fs->create_file_from_pathname($filerecord, $tmpfilepath);
     }
 
+    /**
+     * Exports the model training data.
+     *
+     * @param int $modelid
+     * @param string $timesplittingid
+     * @return \stored_file|false
+     */
+    public static function export_training_data($modelid, $timesplittingid) {
+
+        $fs = get_file_storage();
+
+        $contextid = \context_system::instance()->id;
+        $filepath = '/timesplitting/' . self::clean_time_splitting_id($timesplittingid) . '/';
+
+        $files = $fs->get_directory_files($contextid, 'analytics', self::LABELLED_FILEAREA, $modelid,
+            $filepath, true, false);
+
+        // Discard evaluation files.
+        foreach ($files as $key => $file) {
+            if ($file->get_filename() === self::EVALUATION_FILENAME) {
+                unset($files[$key]);
+            }
+        }
+
+        if (empty($files)) {
+            return false;
+        }
+
+        return self::merge_datasets($files, $modelid, $timesplittingid, self::EXPORT_FILEAREA);
+    }
+
     /**
      * Returns the dataset file data structured by sampleids using the indicators and target column names.
      *
index aae6682..f1c2708 100644 (file)
@@ -1233,6 +1233,19 @@ class model {
             $limitfrom, $limitnum);
     }
 
+    /**
+     * Merges all training data files into one and returns it.
+     *
+     * @return \stored_file|false
+     */
+    public function get_training_data() {
+
+        \core_analytics\manager::check_can_manage_models();
+
+        $timesplittingid = $this->get_time_splitting()->get_id();
+        return \core_analytics\dataset_manager::export_training_data($this->get_id(), $timesplittingid);
+    }
+
     /**
      * Flag the provided file as used for training or prediction.
      *