From b59e8a1605f5cdb4d75837b82c90cdfdb9351098 Mon Sep 17 00:00:00 2001 From: rschoene <rene.schoene@tu-dresden.de> Date: Fri, 22 Nov 2019 17:22:20 +0100 Subject: [PATCH] WIP: Begin to integrate new datasets for learner. - LearnerScenarioDefinition: Add csv-format, output-mappings and base-location (definition- and data-files are now relative paths) - LearnerSettings: Merge columns (now stored as "kind" in column), verbosity of training - LearnerTest: - Ignore long-running and failing tests, add new tests for datasets - Reuse item names from scenario settings - Support csv-format --- .../src/main/resources/activity_network.eg | 1 + .../main/resources/activity_normalizer.json | 1 + ...aded_learner_activity_phone_and_watch.json | 1 + ...d_learner_preferences_brightness_iris.json | 1 + .../main/resources/preference_definition.json | 1 + .../src/main/resources/preference_network.eg | 1 + .../main/resources/preference_normalizer.json | 1 + eraser.starter/starter-setting.yaml | 9 +- .../feedbackloop.learner_backup/Learner.java | 48 ++-- .../MachineLearningImpl.java | 14 +- .../feedbackloop.learner_backup/Main.java | 62 ++++- .../data/LearnerScenarioDefinition.java | 41 ++- .../learner_backup/data/LearnerSettings.java | 12 +- .../data/SimpleColumnDefinition.java | 8 + .../2019-oct-28-activity_definition.json | 41 +++ .../resources/2019-oct-28-activity_network.eg | 24 ++ .../2019-oct-28-activity_normalizer.json | 238 ++++++++++++++++++ .../main/resources/2019-oct-28-learner.json | 25 ++ .../resources/2019-oct-28-loaded_learner.json | 26 ++ .../main/resources/activity_definition.json | 33 ++- .../learner_activity_phone_and_watch.json | 7 +- .../learner_preferences_brightness_iris.json | 4 +- ...aded_learner_activity_phone_and_watch.json | 9 +- ...d_learner_preferences_brightness_iris.json | 6 +- .../main/resources/preference_definition.json | 15 +- .../LearnerSubjectUnderTest.java | 4 +- .../learner_backup/LearnerTest.java | 27 +- .../learner_backup/LearnerTestConstants.java | 27 +- .../learner_backup/LearnerTestSettings.java | 12 +- .../learner_backup/LearnerTestUtils.java | 208 ++++++++------- .../learner_backup/LearnerTestUtilsTest.java | 88 +++++++ .../2019-oct-28-activity_definition.json | 1 + .../resources/2019-oct-28-activity_network.eg | 1 + .../2019-oct-28-activity_normalizer.json | 1 + .../test/resources/2019-oct-28-learner.json | 1 + .../resources/2019-oct-28-loaded_learner.json | 1 + 36 files changed, 788 insertions(+), 212 deletions(-) create mode 120000 eraser.starter/src/main/resources/activity_network.eg create mode 120000 eraser.starter/src/main/resources/activity_normalizer.json create mode 120000 eraser.starter/src/main/resources/loaded_learner_activity_phone_and_watch.json create mode 120000 eraser.starter/src/main/resources/loaded_learner_preferences_brightness_iris.json create mode 120000 eraser.starter/src/main/resources/preference_definition.json create mode 120000 eraser.starter/src/main/resources/preference_network.eg create mode 120000 eraser.starter/src/main/resources/preference_normalizer.json create mode 100644 feedbackloop.learner_backup/src/main/resources/2019-oct-28-activity_definition.json create mode 100644 feedbackloop.learner_backup/src/main/resources/2019-oct-28-activity_network.eg create mode 100644 feedbackloop.learner_backup/src/main/resources/2019-oct-28-activity_normalizer.json create mode 100644 feedbackloop.learner_backup/src/main/resources/2019-oct-28-learner.json create mode 100644 feedbackloop.learner_backup/src/main/resources/2019-oct-28-loaded_learner.json create mode 100644 feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestUtilsTest.java create mode 120000 feedbackloop.learner_backup/src/test/resources/2019-oct-28-activity_definition.json create mode 120000 feedbackloop.learner_backup/src/test/resources/2019-oct-28-activity_network.eg create mode 120000 feedbackloop.learner_backup/src/test/resources/2019-oct-28-activity_normalizer.json create mode 120000 feedbackloop.learner_backup/src/test/resources/2019-oct-28-learner.json create mode 120000 feedbackloop.learner_backup/src/test/resources/2019-oct-28-loaded_learner.json diff --git a/eraser.starter/src/main/resources/activity_network.eg b/eraser.starter/src/main/resources/activity_network.eg new file mode 120000 index 00000000..3c37b327 --- /dev/null +++ b/eraser.starter/src/main/resources/activity_network.eg @@ -0,0 +1 @@ +../../../../feedbackloop.learner_backup/src/main/resources/activity_network.eg \ No newline at end of file diff --git a/eraser.starter/src/main/resources/activity_normalizer.json b/eraser.starter/src/main/resources/activity_normalizer.json new file mode 120000 index 00000000..edc204d0 --- /dev/null +++ b/eraser.starter/src/main/resources/activity_normalizer.json @@ -0,0 +1 @@ +../../../../feedbackloop.learner_backup/src/main/resources/activity_normalizer.json \ No newline at end of file diff --git a/eraser.starter/src/main/resources/loaded_learner_activity_phone_and_watch.json b/eraser.starter/src/main/resources/loaded_learner_activity_phone_and_watch.json new file mode 120000 index 00000000..152f4382 --- /dev/null +++ b/eraser.starter/src/main/resources/loaded_learner_activity_phone_and_watch.json @@ -0,0 +1 @@ +../../../../feedbackloop.learner_backup/src/main/resources/loaded_learner_activity_phone_and_watch.json \ No newline at end of file diff --git a/eraser.starter/src/main/resources/loaded_learner_preferences_brightness_iris.json b/eraser.starter/src/main/resources/loaded_learner_preferences_brightness_iris.json new file mode 120000 index 00000000..154e9040 --- /dev/null +++ b/eraser.starter/src/main/resources/loaded_learner_preferences_brightness_iris.json @@ -0,0 +1 @@ +../../../../feedbackloop.learner_backup/src/main/resources/loaded_learner_preferences_brightness_iris.json \ No newline at end of file diff --git a/eraser.starter/src/main/resources/preference_definition.json b/eraser.starter/src/main/resources/preference_definition.json new file mode 120000 index 00000000..a8dfc425 --- /dev/null +++ b/eraser.starter/src/main/resources/preference_definition.json @@ -0,0 +1 @@ +../../../../feedbackloop.learner_backup/src/main/resources/preference_definition.json \ No newline at end of file diff --git a/eraser.starter/src/main/resources/preference_network.eg b/eraser.starter/src/main/resources/preference_network.eg new file mode 120000 index 00000000..c3ee89df --- /dev/null +++ b/eraser.starter/src/main/resources/preference_network.eg @@ -0,0 +1 @@ +../../../../feedbackloop.learner_backup/src/main/resources/preference_network.eg \ No newline at end of file diff --git a/eraser.starter/src/main/resources/preference_normalizer.json b/eraser.starter/src/main/resources/preference_normalizer.json new file mode 120000 index 00000000..3ff4cdb3 --- /dev/null +++ b/eraser.starter/src/main/resources/preference_normalizer.json @@ -0,0 +1 @@ +../../../../feedbackloop.learner_backup/src/main/resources/preference_normalizer.json \ No newline at end of file diff --git a/eraser.starter/starter-setting.yaml b/eraser.starter/starter-setting.yaml index 8c1aa978..1326620d 100644 --- a/eraser.starter/starter-setting.yaml +++ b/eraser.starter/starter-setting.yaml @@ -26,7 +26,7 @@ load: activity: factory: de.tudresden.inf.st.eraser.feedbackloop.learner_backup.MachineLearningHandlerFactoryImpl # File to read in. Expected format depends on factory - file: ../datasets/backup/activity_definition.json + file: src/main/resources/loaded_learner_activity_phone_and_watch.json external: true # Use dummy model in which the current activity is directly editable. Default: false. dummy: false @@ -36,10 +36,11 @@ activity: # Model for preference learning. If dummy is true, then the file parameter is ignored. preference: - factory: de.tudresden.inf.st.eraser.starter.TestMachineLearningHandlerFactory +# factory: de.tudresden.inf.st.eraser.starter.TestMachineLearningHandlerFactory + factory: de.tudresden.inf.st.eraser.feedbackloop.learner_backup.MachineLearningHandlerFactoryImpl # File to read in. Expected format depends on factory - file: src/main/resources/testHandler.properties -# file: ../datasets/backup/preference_data.csv +# file: src/main/resources/testHandler.properties + file: src/main/resources/loaded_learner_preferences_brightness_iris.json external: true # Use dummy model in which the current activity is directly editable. Default: false. dummy: false diff --git a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/Learner.java b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/Learner.java index cc4c9fa5..6954c37d 100644 --- a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/Learner.java +++ b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/Learner.java @@ -5,6 +5,7 @@ import de.tudresden.inf.st.eraser.feedbackloop.learner_backup.data.LearnerSettin import de.tudresden.inf.st.eraser.feedbackloop.learner_backup.data.SimpleColumnDefinition; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.encog.ConsoleStatusReportable; import org.encog.Encog; import org.encog.ml.data.MLData; import org.encog.ml.data.versatile.NormalizationHelper; @@ -60,34 +61,44 @@ public class Learner { modelFile.deleteOnExit(); } - /** - * Begin training using the training set specified in settings. - * @throws MalformedURLException if the location of the training set in the settings is malformed - */ - void train() throws MalformedURLException { - URL location = new File(settings.initialDataFile).toURI().toURL(); - train(location); - } +// /** +// * Begin training using the training set specified in settings. +// * @throws MalformedURLException if the location of the training set in the settings is malformed +// */ +// void train() throws MalformedURLException { +// URL location = new File(settings.initialDataFile).toURI().toURL(); +// train(location); +// } /** * Begin training with the given initial training set. * @param location the location of the training set */ - void train(URL location) { + void train(URL location, String csvFormatString) { logger.info("Training for {} begins using {}", settings.name, location); VersatileDataSource source; File csvFile = new File(location.getFile()); - source = new CSVDataSource(csvFile, true, CSVFormat.DECIMAL_POINT); + CSVFormat csvFormat; + switch (csvFormatString) { + case "DECIMAL_POINT": csvFormat = CSVFormat.DECIMAL_POINT; break; + case "DECIMAL_COMMA": csvFormat = CSVFormat.DECIMAL_COMMA; break; + default: + logger.warn("Unknown CSV format, using default decimal point"); + csvFormat = CSVFormat.DECIMAL_POINT; + } + source = new CSVDataSource(csvFile, true, csvFormat); VersatileMLDataSet data = new VersatileMLDataSet(source); - final int inputSize = settings.inputColumns.size(); + List<ColumnDefinition> targets = new ArrayList<>(); + final int inputSize = settings.columns.size(); for (int index = 0; index < inputSize; index++) { - SimpleColumnDefinition columnDefinition = settings.inputColumns.get(index); - data.defineSourceColumn(columnDefinition.name, index, columnDefinition.type); + SimpleColumnDefinition columnDefinition = settings.columns.get(index); + ColumnDefinition sourceColumn = data.defineSourceColumn(columnDefinition.name, index, columnDefinition.type); + if (columnDefinition.kind == SimpleColumnDefinition.ColumnKind.target) { + targets.add(sourceColumn); + } } - List<ColumnDefinition> targets = new ArrayList<>(); - for (int targetIndex = 0; targetIndex < settings.targetColumns.size(); targetIndex++) { - SimpleColumnDefinition columnDefinition = settings.targetColumns.get(targetIndex); - targets.add(data.defineSourceColumn(columnDefinition.name, inputSize + targetIndex, columnDefinition.type)); + if (targets.isEmpty()) { + logger.warn("No targets specified for {}!", settings.name); } if (targets.size() == 1) { data.defineSingleOutputOthersInput(targets.get(0)); @@ -96,6 +107,9 @@ public class Learner { } data.analyze(); EncogModel model = new EncogModel(data); + if (settings.verboseTraining) { + model.setReport(new ConsoleStatusReportable()); + } model.selectMethod(data, settings.trainingMethod); data.normalize(); normalizationHelper = data.getNormHelper(); diff --git a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/MachineLearningImpl.java b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/MachineLearningImpl.java index f729b0f8..b1f0062b 100644 --- a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/MachineLearningImpl.java +++ b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/MachineLearningImpl.java @@ -5,9 +5,7 @@ import de.tudresden.inf.st.eraser.jastadd.model.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.io.File; import java.io.IOException; -import java.net.MalformedURLException; import java.net.URL; import java.time.Instant; import java.util.*; @@ -45,7 +43,7 @@ public class MachineLearningImpl implements MachineLearningDecoder, MachineLearn */ public MachineLearningImpl(LearnerGoal goal, URL configURL) throws IOException { scenarioDefinition = LearnerScenarioDefinition.loadFrom(configURL); - URL learnerSettingsURL = filenameToURL(scenarioDefinition.definitionFile); + URL learnerSettingsURL = scenarioDefinition.getDefinitionFileAsURL(); this.learner = new Learner(learnerSettingsURL); this.goal = goal; } @@ -189,11 +187,11 @@ public class MachineLearningImpl implements MachineLearningDecoder, MachineLearn void startTraining() throws IOException, ClassNotFoundException { switch (this.scenarioDefinition.kind) { case normal: - learner.train(filenameToURL(this.scenarioDefinition.dataFiles.get(0))); + learner.train(this.scenarioDefinition.getDataFilesAsURL().get(0), this.scenarioDefinition.csvFormat); break; case loaded: - learner.load(filenameToURL(this.scenarioDefinition.dataFiles.get(0)), - filenameToURL(this.scenarioDefinition.dataFiles.get(1)), true); + List<URL> dataFilesAsURL = this.scenarioDefinition.getDataFilesAsURL(); + learner.load(dataFilesAsURL.get(0), dataFilesAsURL.get(1), true); } this.lastModelUpdate = Instant.now(); } @@ -204,8 +202,4 @@ public class MachineLearningImpl implements MachineLearningDecoder, MachineLearn } learner.shutdown(); } - - private static URL filenameToURL(String filename) throws MalformedURLException { - return new File(filename).toURI().toURL(); - } } diff --git a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/Main.java b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/Main.java index 4aa97dab..d8ff6ed7 100644 --- a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/Main.java +++ b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/Main.java @@ -1,7 +1,10 @@ package de.tudresden.inf.st.eraser.feedbackloop.learner_backup; import com.fasterxml.jackson.databind.ObjectMapper; +import de.tudresden.inf.st.eraser.feedbackloop.learner_backup.data.LearnerScenarioDefinition; import de.tudresden.inf.st.eraser.feedbackloop.learner_backup.data.LearnerSettings; +import de.tudresden.inf.st.eraser.jastadd.model.*; +import de.tudresden.inf.st.eraser.util.ParserUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.encog.ml.data.versatile.NormalizationHelper; @@ -10,11 +13,16 @@ import org.encog.util.csv.ReadCSV; import java.io.File; import java.io.IOException; +import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.stream.Collectors; +import static de.tudresden.inf.st.eraser.jastadd.model.MachineLearningHandlerFactory.MachineLearningHandlerFactoryTarget.ACTIVITY_RECOGNITION; + @SuppressWarnings("unused") public class Main { @@ -28,7 +36,49 @@ public class Main { // learner.train("datasets/backup/activity_data.csv","datasets/backup/preference_data.csv"); // activity_validation_learner(); // testSettings(); - testLoadNormalizationHelper(); +// testLoadNormalizationHelper(); + testLearnerWithDatasetFromMunich(); + } + + private static void testLearnerWithDatasetFromMunich() { + MachineLearningHandlerFactory factory = new MachineLearningHandlerFactoryImpl(); + try { + URL configURL = Paths.get("src", "main", "resources", "activity_definition-2019-oct-28.json").toUri().toURL(); + LearnerScenarioDefinition scenarioDefinition = LearnerScenarioDefinition.loadFrom(configURL); + Root model = createRootWithItemsFrom(scenarioDefinition); + factory.setKnowledgeBaseRoot(model); + factory.initializeFor(ACTIVITY_RECOGNITION, configURL); + MachineLearningModel mlModel = factory.createModel(); + List<Item> changedItems = new ArrayList<>(); // TODO + mlModel.getEncoder().newData(changedItems); + MachineLearningResult result = mlModel.getDecoder().classify(); + } catch (IOException | ClassNotFoundException e) { + logger.catching(e); + } + } + + private static Root createRootWithItemsFrom(LearnerScenarioDefinition scenarioDefinition) { + Root result = Root.createEmptyRoot(); + ParserUtils.createUnknownGroup( + result.getSmartHomeEntityModel(), + scenarioDefinition.relevantItemNames.stream().map(Main::createItem).collect(Collectors.toList())); + return result; + } + + private static Item createItem(String itemName) { + Item item; + if (itemName.contains("OpenClose")) { + // contact item + item = new ContactItem(); + } else if (itemName.contains("Fibaro")) { + // boolean item + item = new SwitchItem(); + } else { + // double item + item = new NumberItem(); + } + item.setID(itemName); + return item; } private static void testLoadNormalizationHelper() { @@ -52,13 +102,9 @@ public class Main { return; } System.out.println("settings.name = " + settings.name); - System.out.println("settings.inputColumns = " + settings.inputColumns - .stream() - .map(col -> "(" + col.name + "," + col.type + ")") - .collect(Collectors.joining(";"))); - System.out.println("settings.targetColumns = " + settings.targetColumns + System.out.println("settings.columns = " + settings.columns .stream() - .map(col -> "(" + col.name + "," + col.type + ")") + .map(col -> "(" + col.kind + ": " + col.name + "," + col.type + ")") .collect(Collectors.joining(";"))); } @@ -68,7 +114,7 @@ public class Main { Learner learner = new Learner(new ObjectMapper().readValue( Paths.get("src", "main", "resources", "activity_definition.json").toFile(), LearnerSettings.class)); - learner.train(Paths.get("src", "test", "activity_data.csv").toUri().toURL()); + learner.train(Paths.get("src", "test", "activity_data.csv").toUri().toURL(), "DECIMAL_POINT"); // learner.preference_train("../datasets/backup/preference_data.csv"); int wrong = 0; int right = 0; diff --git a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/data/LearnerScenarioDefinition.java b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/data/LearnerScenarioDefinition.java index c6151128..5d7d511b 100644 --- a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/data/LearnerScenarioDefinition.java +++ b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/data/LearnerScenarioDefinition.java @@ -5,9 +5,15 @@ import de.tudresden.inf.st.eraser.feedbackloop.learner_backup.LearnerKind; import de.tudresden.inf.st.eraser.feedbackloop.learner_backup.MachineLearningImpl; import de.tudresden.inf.st.eraser.util.ParserUtils; +import java.io.File; import java.io.IOException; +import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * Settings to initialize {@link MachineLearningImpl}. @@ -18,13 +24,46 @@ import java.util.List; public class LearnerScenarioDefinition { public List<String> relevantItemNames; public List<String> targetItemNames; + public Map<String, String> nonTrivialOutputMappings = new HashMap<>(); public String definitionFile; + public String csvFormat = "DECIMAL_POINT"; public List<String> dataFiles; public LearnerKind kind = LearnerKind.normal; /** Save models at shutdown */ public boolean saveModels = false; + public transient URL myBaseLocation; public static LearnerScenarioDefinition loadFrom(URL location) throws IOException { - return ParserUtils.loadFrom(location, LearnerScenarioDefinition.class); + LearnerScenarioDefinition result = ParserUtils.loadFrom(location, LearnerScenarioDefinition.class); + result.myBaseLocation = new URL(location.getProtocol(), location.getHost(), location.getPort(), new File(location.getFile()).getParent(), null); + return result; + } + + public URL getDefinitionFileAsURL() throws MalformedURLException { + return filenameToURL(definitionFile); + } + + public List<URL> getDataFilesAsURL() throws MalformedURLException { + List<URL> result = new ArrayList<>(); + for (String dataFile : dataFiles) { + URL url = filenameToURL(dataFile); + result.add(url); + } + return result; + } + + private URL filenameToURL(URL base, String filename) throws MalformedURLException { + // construct new URL with same content except for file part + String newFilePart; + if (filename.startsWith("/")) { + newFilePart = filename; + } else { + newFilePart = (base.getFile().endsWith("/") ? base.getFile() : base.getFile() + "/" ) + filename; + } + return new URL(base.getProtocol(), base.getHost(), base.getPort(), newFilePart, null); + } + + private URL filenameToURL(String filename) throws MalformedURLException { + return filenameToURL(myBaseLocation, filename); } } diff --git a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/data/LearnerSettings.java b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/data/LearnerSettings.java index f849873c..ff1b5636 100644 --- a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/data/LearnerSettings.java +++ b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/data/LearnerSettings.java @@ -19,10 +19,10 @@ import java.util.List; public class LearnerSettings { /** Description what this learner is about to learn */ public String name; - /** Input columns (of the CSV used for training) */ - public List<SimpleColumnDefinition> inputColumns; - /** Target columns (of the CSV used for training) */ - public List<SimpleColumnDefinition> targetColumns; + /** All available columns (of the CSV used for training, may be set to be ignored) */ + public List<SimpleColumnDefinition> columns; + /** Whether to be verbose while training */ + public boolean verboseTraining = false; /** Training method */ public String trainingMethod = MLMethodFactory.TYPE_FEEDFORWARD; /** Training parameter. Used in {@link EncogModel#holdBackValidation(double, boolean, int)} */ @@ -35,11 +35,7 @@ public class LearnerSettings { /** Training parameter. Used in {@link EncogModel#crossvalidate(int, boolean)} */ public int validationFolds = 5; - /** Filename to load initial data from. Should be in another settings file! */ - public String initialDataFile = null; - public static LearnerSettings loadFrom(URL location) throws IOException { return ParserUtils.loadFrom(location, LearnerSettings.class); } - } diff --git a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/data/SimpleColumnDefinition.java b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/data/SimpleColumnDefinition.java index 17e6109c..e8d1f905 100644 --- a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/data/SimpleColumnDefinition.java +++ b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/data/SimpleColumnDefinition.java @@ -23,4 +23,12 @@ public class SimpleColumnDefinition { public double mean = Double.NaN; public double sd = Double.NaN; public List<String> classes = new ArrayList<>(); + /** {@link ColumnKind} is either input, target, or ignored */ + public ColumnKind kind; + + public enum ColumnKind { + input, + target, + ignored + } } diff --git a/feedbackloop.learner_backup/src/main/resources/2019-oct-28-activity_definition.json b/feedbackloop.learner_backup/src/main/resources/2019-oct-28-activity_definition.json new file mode 100644 index 00000000..1078c7fd --- /dev/null +++ b/feedbackloop.learner_backup/src/main/resources/2019-oct-28-activity_definition.json @@ -0,0 +1,41 @@ +{ + "name": "activity", + "columns": [ + { "kind": "input", "name": "Date", "type": "ignore" }, + { "kind": "input", "name": "time", "type": "ignore" }, + { "kind": "target", "name": "activity_label", "type": "nominal" }, + { "kind": "input", "name": "grideye_room_window", "type": "ignore" }, + { "kind": "input", "name": "grideye_room_door", "type": "ignore" }, + { "kind": "input", "name": "Fibaro_2_work_motion", "type": "nominal" }, + { "kind": "input", "name": "H2_weather_temp", "type": "ignore" }, + { "kind": "input", "name": "H2_weather_pressure", "type": "ignore" }, + { "kind": "input", "name": "H2_weather_hum", "type": "ignore" }, + { "kind": "input", "name": "Fibaro_4_TV_motion", "type": "nominal" }, + { "kind": "input", "name": "Fibaro_3_door_motion", "type": "nominal" }, + { "kind": "input", "name": "Fibaro_11_OpenClose", "type": "nominal" }, + { "kind": "input", "name": "Aeotec_8_room_Temp", "type": "ignore" }, + { "kind": "input", "name": "Aeotec_8_room_lum", "type": "ignore" }, + { "kind": "input", "name": "Aeotec_8_room_Hum", "type": "ignore" }, + { "kind": "input", "name": "Aeotec_8_room_uv", "type": "ignore" }, + { "kind": "input", "name": "Fibaro_5_room_Temp", "type": "ignore" }, + { "kind": "input", "name": "Fibaro_5_room_lum", "type": "ignore" }, + { "kind": "input", "name": "Fibaro_3_door_lum", "type": "ignore" }, + { "kind": "input", "name": "Fibaro_3_door_Temp", "type": "ignore" }, + { "kind": "input", "name": "Fibaro_2_work_lum", "type": "ignore" }, + { "kind": "input", "name": "Fibaro_4_TV_Temp", "type": "ignore" }, + { "kind": "input", "name": "Fibaro_4_TV_lum", "type": "ignore" }, + { "kind": "input", "name": "Fibaro_2_work_Temp", "type": "ignore" }, + { "kind": "input", "name": "TV_OnOff", "type": "ignore" }, + { "kind": "input", "name": "DPS310_pressure_room", "type": "ignore" }, + { "kind": "input", "name": "DPS310_temp_room", "type": "ignore" }, + { "kind": "input", "name": "DPS310_altitude_room", "type": "ignore" }, + { "kind": "input", "name": "work_device_online_state", "type": "nominal" }, + { "kind": "input", "name": "Fibaro_15_OpenClose", "type": "ignore" }, + { "kind": "input", "name": "GridEye_room_window_x", "type": "continuous" }, + { "kind": "input", "name": "GridEye_room_door_y", "type": "continuous" }, + { "kind": "input", "name": "GridEye_room_door_x", "type": "continuous" }, + { "kind": "input", "name": "GridEye_room_window_y", "type": "continuous"} + ], + "verboseTraining": true, + "validationFolds": 3 +} diff --git a/feedbackloop.learner_backup/src/main/resources/2019-oct-28-activity_network.eg b/feedbackloop.learner_backup/src/main/resources/2019-oct-28-activity_network.eg new file mode 100644 index 00000000..f2cf7839 --- /dev/null +++ b/feedbackloop.learner_backup/src/main/resources/2019-oct-28-activity_network.eg @@ -0,0 +1,24 @@ +encog,BasicNetwork,java,3.4.0,1,1574428376334 +[BASIC] +[BASIC:PARAMS] +[BASIC:NETWORK] +beginTraining=0 +connectionLimit=0 +contextTargetOffset=0,0,0 +contextTargetSize=0,0,0 +endTraining=2 +hasContext=f +inputCount=19 +layerCounts=7,16,20 +layerFeedCounts=7,15,19 +layerContextCount=0,0,0 +layerIndex=0,7,23 +output=-0.340836329,-0.3423459838,-0.9971504865,-0.994969938,-1,-0.9999999999,-0.3279989961,-0.9797933007,-0.9984924393,-0.9999897248,-0.9998031211,-0.9898578199,0.9998409154,0.9972211116,0.9805206206,-0.9932796274,-0.9544652313,0.9968045856,-0.9445173438,-0.9995702614,-0.9977451063,0.9999910694,1,-1,1,-1,-1,-1,1,1,-1,-1,-1,1,-1,-1,-1,1,0.9921568627,0.3833992095,0.1529411765,-1,1 +outputCount=7 +weightIndex=0,112,412 +weights=-0.404137706,-0.2885181231,0.9668734481,0.0062269301,1.0128231886,0.0089469213,0.4585189612,-0.0894394019,-0.0797318623,-0.3468553546,-1.2300755961,-0.3468429248,-0.5145871857,-0.2848383941,-0.3264209087,0.5741982601,0.27127421,-0.5434136125,0.5485149158,0.5003078803,-0.2698965768,0.7983927357,-0.0333252064,0.3447572796,-0.1882659481,0.7247422012,0.3064477151,-1.0138871821,0.1416051,0.6583373536,0.2705332613,-1.1855603499,0.9929388464,0.5796871274,-0.3399669435,0.8569628254,0.2075255413,-0.5600042384,-0.4138292438,0.6538720983,-0.6923520436,-0.3319059439,-0.4537568575,-0.0025677392,-0.6905085845,0.9053047001,-0.6162521138,-0.3960775091,-0.4368636028,-0.9001436588,1.0750416574,0.7660161008,-0.5990507184,-0.2425415361,0.0274320766,-0.3558952255,-0.71936614,0.5830552943,-0.171895279,0.1974145518,0.7948972407,1.0487310214,-0.566601431,0.1010319343,0.172866604,3.0551601629,3.0000824008,0.3866019399,2.7196342543,-13.0154758675,-6.9544569017,4.3141833144,-2.4103093678,0.2125104309,0.7730445211,-7.4019442181,0.099425633,-10.1082331563,-3.2519692,-4.1723085126,1.1032763871,1.434494168,1.0655828482,2.259228432,0.4309682109,0.8421555229,-1.2418354028,-0.7857195285,-0.1460260544,5.7534066269,-2.0174021556,0.9996651657,-3.1600904683,-3.926442431,-0.780245191,-2.6582836523,-0.3842677407,0.8001100617,0.0932911402,0.8260885108,0.3243592641,0.929464689,0.0688818482,0.2795366272,-0.8677541061,0.1766944912,-0.5401835409,-0.1872442079,0.7241379909,-0.4751260736,-0.7012144045,0.6693119708,0.9182400855,-0.8851888016,0.4365092184,0.2855724153,-0.5807331971,-0.5545832569,-0.4287869651,-0.4256322973,-0.1423483588,0.3741760439,0.0626357057,-0.2969373002,0.1952954195,0.3347612998,-0.319608364,-0.0253925855,-0.25709248,0.0673034925,-0.0089497179,1.0365875369,-0.3911295373,-0.077826642,0.5508385817,-0.3285681225,0.5657971033,-0.2066801958,0.1686295498,0.2070775065,0.9912375579,-0.4753575264,-0.2726487663,0.2664021737,1.3515632261,0.4126524074,0.1782886902,-0.0285599614,-0.0603748382,-0.0374828481,-0.0914111075,-0.268271809,0.0852087324,0.5126836126,0.2546340519,0.2746173051,2.817153954,0.7249724018,-0.6981285839,-0.4985126373,0.8604969349,0.2037431513,2.7264477402,1.2330380603,-0.0167592164,-0.144188394,-0.7301846959,0.4337688818,0.1298617096,-0.4470460904,-0.1921802707,-4.1597800015,-0.4025492346,0.0229041912,1.306807566,0.3525340482,0.6127139965,0.5393598738,0.6929584822,0.7056334137,1.1994301985,0.4496289046,0.2941309986,-0.2056291639,1.251880871,-0.010770356,-0.9810071383,0.0064674917,-0.0176386919,-0.048016511,-0.0107097517,0.0753283256,0.7404769463,-0.5929286192,-0.5078274499,0.4259262815,0.143754059,0.1359612229,0.2541697513,0.2510065262,0.6709506571,-0.148350937,1.1900545736,0.749742294,-0.6287601463,0.6900848995,-0.2690878318,0.0001816587,0.0455003469,0.0309224531,-0.0076091205,-1.0006871788,0.2681613331,0.1833383853,-0.5172206492,0.6892488375,-0.7451485095,0.4276582331,0.3742194161,0.4014722088,1.0994959368,0.847787554,0.7638290785,-0.7914432342,-0.4420336184,-0.9158573706,2.6389325839,0.0887550998,-0.0569580742,-0.0392462129,-0.0239489707,0.1418880057,1.0896267359,0.9904016473,-1.0607560941,1.6784823518,-0.9433720747,0.0257586137,0.4714302624,0.4166775721,-0.6066347851,1.6444284094,0.9257977982,-1.0381297318,-1.7311006544,1.1774799465,1.877862961,-0.2855399619,0.0755531811,0.0424919604,0.2678753077,0.1398908597,0.8214292233,0.9009702295,0.1469390864,0.4637993899,-0.2313547534,0.1448407563,1.0392025508,0.9881708464,-0.7406734936,0.4983164436,0.2939713585,-0.1343176987,-1.112507143,0.3883191946,0.1738987071,-0.07073642,0.050403588,0.0765184646,-0.0005174206,0.8847534729,0.7436968164,-1.0771556764,0.1100227689,-0.0614329979,-0.1622374928,-0.1525778093,-0.6077259941,-0.619774004,0.3603468196,-0.2009073954,-0.3733319916,-0.0788296869,0.6074303689,-0.4126291585,-0.9028665297,-0.0099997932,-0.0001654564,0.0148504563,-0.0231406351,0.5377204482,-0.5777914567,-0.1781865678,1.1415129984,0.2834037016,-0.5539063514,-0.4515762597,0.1404508438,0.1187112233,0.6532769069,-1.2829520787,-0.5799936288,-0.2116382272,0.2306003109,1.0953413393,-0.3323463029,0.0225181859,0.0589642565,0.0426297362,-0.040109034,0.3269351263,-0.5321326898,0.9175722208,-0.6271480872,-0.7459771441,0.0158692044,0.0311943145,-0.5266229614,-0.5225480734,-0.330023217,-0.5138457028,-0.0246451645,-0.2378591164,-0.8257893027,-0.1187365978,-0.8009636381,0.0004696224,0.0525540439,0.015912768,0.0008598419,-0.8381211463,-0.4135458004,0.0319505462,0.4168831222,-1.6027457971,-0.726313219,-0.3371409293,-1.942373089,-1.9681611004,0.3375429492,0.0455411676,0.2193321201,0.5576102386,0.2043673413,0.5864664222,-1.9789533345,0.0541247202,0.0236840469,-0.0086069514,-0.0407470423,-0.4357306331,1.9243856045,-1.3208328316,-0.0954191506,0.0808587123,0.3690795603,0.1095208965,-0.0382497008,-0.0336668021,-0.2167623054,0.0806856928,-0.6457893128,-0.6880786727,0.1245176541,-0.2603043844,-0.8839399611,-0.0815347261,-0.202848777,0.1924881481,-0.1531643391,-0.1819825028,-0.7487125691,-1.0617607253,-0.0682555272,0.1203110094,-0.0307641525,-0.6370047961,0.3619059939,0.3858454328,-0.1968004594,-0.4804011029,-0.3394977591,-0.0261051038,0.1742859157,0.5756254766,-2.5706321037,0.0797072295,0.3687297587,0.0907303422,-0.0206407321,0.3037126261,-0.9534375329,0.8626140311,0.2956554426,0.2553834042,-0.8520628339,-0.8594849437,-0.0600253851,-0.0390563524,-1.4805598205,-0.2333029476,-0.8993510452,-0.9759839461,0.0934807631,-1.6299950666,0.5668144115,0.0068186589,-0.0746488856,0.0060924025,-0.0051572226,1.0449041956 +biasActivation=0,1,1 +[BASIC:ACTIVATION] +"org.encog.engine.network.activation.ActivationTANH" +"org.encog.engine.network.activation.ActivationTANH" +"org.encog.engine.network.activation.ActivationLinear" diff --git a/feedbackloop.learner_backup/src/main/resources/2019-oct-28-activity_normalizer.json b/feedbackloop.learner_backup/src/main/resources/2019-oct-28-activity_normalizer.json new file mode 100644 index 00000000..a3be23ca --- /dev/null +++ b/feedbackloop.learner_backup/src/main/resources/2019-oct-28-activity_normalizer.json @@ -0,0 +1,238 @@ +{ + "sourceColumns" : [ { + "name" : "Date", + "type" : "ignore", + "index" : 0 + }, { + "name" : "time", + "type" : "ignore", + "index" : 1 + }, { + "name" : "activity_label", + "type" : "nominal", + "index" : 2, + "classes" : [ "DoorClosedPOut", "DoorOpenedPOut", "DoorClosedPIn", "Working", "Reading", "TVWatching", "DoorOpenedPIn" ] + }, { + "name" : "grideye_room_window", + "type" : "ignore", + "index" : 3 + }, { + "name" : "grideye_room_door", + "type" : "ignore", + "index" : 4 + }, { + "name" : "Fibaro_2_work_motion", + "type" : "nominal", + "index" : 5, + "classes" : [ "ON", "OFF", "\\N" ] + }, { + "name" : "H2_weather_temp", + "type" : "ignore", + "index" : 6 + }, { + "name" : "H2_weather_pressure", + "type" : "ignore", + "index" : 7 + }, { + "name" : "H2_weather_hum", + "type" : "ignore", + "index" : 8 + }, { + "name" : "Fibaro_4_TV_motion", + "type" : "nominal", + "index" : 9, + "classes" : [ "\\N", "ON", "OFF" ] + }, { + "name" : "Fibaro_3_door_motion", + "type" : "nominal", + "index" : 10, + "classes" : [ "OFF", "ON", "\\N" ] + }, { + "name" : "Fibaro_11_OpenClose", + "type" : "nominal", + "index" : 11, + "classes" : [ "CLOSED", "OPEN", "\\N" ] + }, { + "name" : "Aeotec_8_room_Temp", + "type" : "ignore", + "index" : 12 + }, { + "name" : "Aeotec_8_room_lum", + "type" : "ignore", + "index" : 13 + }, { + "name" : "Aeotec_8_room_Hum", + "type" : "ignore", + "index" : 14 + }, { + "name" : "Aeotec_8_room_uv", + "type" : "ignore", + "index" : 15 + }, { + "name" : "Fibaro_5_room_Temp", + "type" : "ignore", + "index" : 16 + }, { + "name" : "Fibaro_5_room_lum", + "type" : "ignore", + "index" : 17 + }, { + "name" : "Fibaro_3_door_lum", + "type" : "ignore", + "index" : 18 + }, { + "name" : "Fibaro_3_door_Temp", + "type" : "ignore", + "index" : 19 + }, { + "name" : "Fibaro_2_work_lum", + "type" : "ignore", + "index" : 20 + }, { + "name" : "Fibaro_4_TV_Temp", + "type" : "ignore", + "index" : 21 + }, { + "name" : "Fibaro_4_TV_lum", + "type" : "ignore", + "index" : 22 + }, { + "name" : "Fibaro_2_work_Temp", + "type" : "ignore", + "index" : 23 + }, { + "name" : "TV_OnOff", + "type" : "ignore", + "index" : 24 + }, { + "name" : "DPS310_pressure_room", + "type" : "ignore", + "index" : 25 + }, { + "name" : "DPS310_temp_room", + "type" : "ignore", + "index" : 26 + }, { + "name" : "DPS310_altitude_room", + "type" : "ignore", + "index" : 27 + }, { + "name" : "work_device_online_state", + "type" : "nominal", + "index" : 28, + "classes" : [ "ON", "OFF", "\\N" ] + }, { + "name" : "Fibaro_15_OpenClose", + "type" : "ignore", + "index" : 29 + }, { + "name" : "GridEye_room_window_x", + "type" : "continuous", + "count" : 195108, + "index" : 30, + "low" : 0.0, + "high" : 255.0, + "mean" : 187.7175666810177, + "sd" : 84.78936592617109 + }, { + "name" : "GridEye_room_door_y", + "type" : "continuous", + "count" : 195108, + "index" : 31, + "low" : 0.0, + "high" : 253.0, + "mean" : 180.47390163396682, + "sd" : 45.67432497413589 + }, { + "name" : "GridEye_room_door_x", + "type" : "continuous", + "count" : 195108, + "index" : 32, + "low" : 0.0, + "high" : 255.0, + "mean" : 159.02686717100272, + "sd" : 53.62353439276967 + }, { + "name" : "GridEye_room_window_y", + "type" : "continuous", + "count" : 195108, + "index" : 33, + "low" : 0.0, + "high" : 252.0, + "mean" : 123.94642966972138, + "sd" : 81.4972896448954 + } ], + "inputColumns" : [ { + "name" : "Fibaro_2_work_motion", + "type" : "nominal", + "index" : 5, + "classes" : [ "ON", "OFF", "\\N" ] + }, { + "name" : "Fibaro_4_TV_motion", + "type" : "nominal", + "index" : 9, + "classes" : [ "\\N", "ON", "OFF" ] + }, { + "name" : "Fibaro_3_door_motion", + "type" : "nominal", + "index" : 10, + "classes" : [ "OFF", "ON", "\\N" ] + }, { + "name" : "Fibaro_11_OpenClose", + "type" : "nominal", + "index" : 11, + "classes" : [ "CLOSED", "OPEN", "\\N" ] + }, { + "name" : "work_device_online_state", + "type" : "nominal", + "index" : 28, + "classes" : [ "ON", "OFF", "\\N" ] + }, { + "name" : "GridEye_room_window_x", + "type" : "continuous", + "count" : 195108, + "index" : 30, + "low" : 0.0, + "high" : 255.0, + "mean" : 187.7175666810177, + "sd" : 84.78936592617109 + }, { + "name" : "GridEye_room_door_y", + "type" : "continuous", + "count" : 195108, + "index" : 31, + "low" : 0.0, + "high" : 253.0, + "mean" : 180.47390163396682, + "sd" : 45.67432497413589 + }, { + "name" : "GridEye_room_door_x", + "type" : "continuous", + "count" : 195108, + "index" : 32, + "low" : 0.0, + "high" : 255.0, + "mean" : 159.02686717100272, + "sd" : 53.62353439276967 + }, { + "name" : "GridEye_room_window_y", + "type" : "continuous", + "count" : 195108, + "index" : 33, + "low" : 0.0, + "high" : 252.0, + "mean" : 123.94642966972138, + "sd" : 81.4972896448954 + } ], + "outputColumns" : [ { + "name" : "activity_label", + "type" : "nominal", + "index" : 2, + "classes" : [ "DoorClosedPOut", "DoorOpenedPOut", "DoorClosedPIn", "Working", "Reading", "TVWatching", "DoorOpenedPIn" ] + } ], + "inputLow" : -1.0, + "inputHigh" : 1.0, + "outputLow" : -1.0, + "outputHigh" : 1.0, + "unknownValues" : [ null ] +} \ No newline at end of file diff --git a/feedbackloop.learner_backup/src/main/resources/2019-oct-28-learner.json b/feedbackloop.learner_backup/src/main/resources/2019-oct-28-learner.json new file mode 100644 index 00000000..2b7359f3 --- /dev/null +++ b/feedbackloop.learner_backup/src/main/resources/2019-oct-28-learner.json @@ -0,0 +1,25 @@ +{ + "relevantItemNames": [ + "Fibaro_2_work_motion", + "Fibaro_4_TV_motion", + "Fibaro_3_door_motion", + "Fibaro_11_OpenClose", + "work_device_online_state", + "GridEye_room_window_x", + "GridEye_room_door_y", + "GridEye_room_door_x", + "GridEye_room_window_y" + ], + "targetItemNames": [ + "activity" + ], + "nonTrivialOutputMappings": { + "activity_label": "activity" + }, + "definitionFile": "./2019-oct-28-activity_definition.json", + "dataFiles": [ + "activity_data/28_08_2019_H14_14/result_all_items_EVERYTHING.csv" + ], + "csvFormat": "DECIMAL_COMMA", + "saveModels": true +} diff --git a/feedbackloop.learner_backup/src/main/resources/2019-oct-28-loaded_learner.json b/feedbackloop.learner_backup/src/main/resources/2019-oct-28-loaded_learner.json new file mode 100644 index 00000000..f476f357 --- /dev/null +++ b/feedbackloop.learner_backup/src/main/resources/2019-oct-28-loaded_learner.json @@ -0,0 +1,26 @@ +{ + "relevantItemNames": [ + "Fibaro_2_work_motion", + "Fibaro_4_TV_motion", + "Fibaro_3_door_motion", + "Fibaro_11_OpenClose", + "work_device_online_state", + "GridEye_room_window_x", + "GridEye_room_door_y", + "GridEye_room_door_x", + "GridEye_room_window_y" + ], + "targetItemNames": [ + "activity" + ], + "nonTrivialOutputMappings": { + "activity_label": "activity" + }, + "definitionFile": "./2019-oct-28-activity_definition.json", + "dataFiles": [ + "./2019-oct-28-activity_network.eg", + "./2019-oct-28-activity_normalizer.json" + ], + "csvFormat": "DECIMAL_COMMA", + "kind": "loaded" +} diff --git a/feedbackloop.learner_backup/src/main/resources/activity_definition.json b/feedbackloop.learner_backup/src/main/resources/activity_definition.json index 49325fc7..9c4a9ea5 100644 --- a/feedbackloop.learner_backup/src/main/resources/activity_definition.json +++ b/feedbackloop.learner_backup/src/main/resources/activity_definition.json @@ -1,21 +1,18 @@ { "name": "activity", - "inputColumns": [ - { "name": "m_accel_x", "type":"continuous" }, - { "name": "m_accel_y", "type": "continuous" }, - { "name": "m_accel_z", "type": "continuous" }, - { "name": "m_rotation_x", "type": "continuous" }, - { "name": "m_rotation_y", "type": "continuous" }, - { "name": "m_rotation_z", "type": "continuous" }, - { "name": "w_accel_x", "type": "continuous" }, - { "name": "w_accel_y", "type": "continuous" }, - { "name": "w_accel_z", "type": "continuous" }, - { "name": "w_rotation_x", "type": "continuous" }, - { "name": "w_rotation_y", "type": "continuous" }, - { "name": "w_rotation_z", "type": "continuous" } - ], - "targetColumns": [ - { "name": "labels", "type": "nominal" } - ], - "initialDataFile": "src/test/resources/activity_data.csv" + "columns": [ + { "kind": "input", "name": "m_accel_x", "type":"continuous" }, + { "kind": "input", "name": "m_accel_y", "type": "continuous" }, + { "kind": "input", "name": "m_accel_z", "type": "continuous" }, + { "kind": "input", "name": "m_rotation_x", "type": "continuous" }, + { "kind": "input", "name": "m_rotation_y", "type": "continuous" }, + { "kind": "input", "name": "m_rotation_z", "type": "continuous" }, + { "kind": "input", "name": "w_accel_x", "type": "continuous" }, + { "kind": "input", "name": "w_accel_y", "type": "continuous" }, + { "kind": "input", "name": "w_accel_z", "type": "continuous" }, + { "kind": "input", "name": "w_rotation_x", "type": "continuous" }, + { "kind": "input", "name": "w_rotation_y", "type": "continuous" }, + { "kind": "input", "name": "w_rotation_z", "type": "continuous" }, + { "kind": "target", "name": "labels", "type": "nominal" } + ] } diff --git a/feedbackloop.learner_backup/src/main/resources/learner_activity_phone_and_watch.json b/feedbackloop.learner_backup/src/main/resources/learner_activity_phone_and_watch.json index acabbdd4..189a3c95 100644 --- a/feedbackloop.learner_backup/src/main/resources/learner_activity_phone_and_watch.json +++ b/feedbackloop.learner_backup/src/main/resources/learner_activity_phone_and_watch.json @@ -16,9 +16,12 @@ "targetItemNames": [ "activity" ], - "definitionFile": "src/test/resources/activity_definition.json", + "nonTrivialOutputMappings": { + "labels": "activity" + }, + "definitionFile": "./activity_definition.json", "dataFiles": [ - "src/test/resources/activity_data.csv" + "./activity_data.csv" ], "saveModels": false } diff --git a/feedbackloop.learner_backup/src/main/resources/learner_preferences_brightness_iris.json b/feedbackloop.learner_backup/src/main/resources/learner_preferences_brightness_iris.json index 8b2c9ad3..b035fe92 100644 --- a/feedbackloop.learner_backup/src/main/resources/learner_preferences_brightness_iris.json +++ b/feedbackloop.learner_backup/src/main/resources/learner_preferences_brightness_iris.json @@ -6,9 +6,9 @@ "targetItemNames": [ "iris1_item" ], - "definitionFile": "src/test/resources/preference_definition.json", + "definitionFile": "./preference_definition.json", "dataFiles": [ - "src/test/resources/preference_data.csv" + "./preference_data.csv" ], "saveModels": false } diff --git a/feedbackloop.learner_backup/src/main/resources/loaded_learner_activity_phone_and_watch.json b/feedbackloop.learner_backup/src/main/resources/loaded_learner_activity_phone_and_watch.json index 3ce0a511..ea4d6263 100644 --- a/feedbackloop.learner_backup/src/main/resources/loaded_learner_activity_phone_and_watch.json +++ b/feedbackloop.learner_backup/src/main/resources/loaded_learner_activity_phone_and_watch.json @@ -16,10 +16,13 @@ "targetItemNames": [ "activity" ], - "definitionFile": "src/test/resources/activity_definition.json", + "nonTrivialOutputMappings": { + "labels": "activity" + }, + "definitionFile": "./activity_definition.json", "dataFiles": [ - "src/test/resources/activity_network.eg", - "src/test/resources/activity_normalizer.json" + "./activity_network.eg", + "./activity_normalizer.json" ], "kind": "loaded" } diff --git a/feedbackloop.learner_backup/src/main/resources/loaded_learner_preferences_brightness_iris.json b/feedbackloop.learner_backup/src/main/resources/loaded_learner_preferences_brightness_iris.json index 2ec4d871..f06dd1e5 100644 --- a/feedbackloop.learner_backup/src/main/resources/loaded_learner_preferences_brightness_iris.json +++ b/feedbackloop.learner_backup/src/main/resources/loaded_learner_preferences_brightness_iris.json @@ -6,10 +6,10 @@ "targetItemNames": [ "iris1_item" ], - "definitionFile": "src/test/resources/preference_definition.json", + "definitionFile": "./preference_definition.json", "dataFiles": [ - "src/test/resources/preference_network.eg", - "src/test/resources/preference_normalizer.json" + "./preference_network.eg", + "./preference_normalizer.json" ], "kind": "loaded" } diff --git a/feedbackloop.learner_backup/src/main/resources/preference_definition.json b/feedbackloop.learner_backup/src/main/resources/preference_definition.json index 0d0d5011..6ac043cd 100644 --- a/feedbackloop.learner_backup/src/main/resources/preference_definition.json +++ b/feedbackloop.learner_backup/src/main/resources/preference_definition.json @@ -1,12 +1,9 @@ { "name": "preference", - "inputColumns": [ - { "name": "activity", "type":"nominal" }, - { "name": "w_brightness", "type": "nominal" } - ], - "targetColumns": [ - { "name": "label1", "type": "continuous" }, - { "name": "label2", "type": "continuous" } - ], - "initialDataFile": "src/test/resources/preference_data.csv" + "columns": [ + { "kind": "input", "name": "activity", "type":"nominal" }, + { "kind": "input", "name": "w_brightness", "type": "nominal" }, + { "kind": "target", "name": "label1", "type": "continuous" }, + { "kind": "target", "name": "label2", "type": "continuous" } + ] } diff --git a/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerSubjectUnderTest.java b/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerSubjectUnderTest.java index 69ca8bd7..3a42297c 100644 --- a/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerSubjectUnderTest.java +++ b/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerSubjectUnderTest.java @@ -19,8 +19,8 @@ class LearnerSubjectUnderTest { Root root; private MachineLearningHandlerFactoryImpl factory; - void init() { - root = LearnerTestUtils.createKnowledgeBase(); + void init(LearnerTestSettings settings) { + root = LearnerTestUtils.createKnowledgeBase(settings); factory = new MachineLearningHandlerFactoryImpl(); factory.setKnowledgeBaseRoot(root); } diff --git a/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTest.java b/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTest.java index 75d162aa..7457ed7a 100644 --- a/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTest.java +++ b/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTest.java @@ -29,6 +29,9 @@ public class LearnerTest { private static URL PREFERENCE_CONFIG; private static URL LOADED_PREFERENCE_CONFIG; private static URL PREFERENCE_DATA; + private static URL OCT_ACTIVITY_CONFIG; + private static URL OCT_LOADED_ACTIVITY_CONFIG; + private static URL OCT_ACTIVITY_DATA; private LearnerSubjectUnderTest sut; @BeforeClass @@ -39,6 +42,10 @@ public class LearnerTest { PREFERENCE_CONFIG = resolveFromBaseURL("learner_preferences_brightness_iris.json"); LOADED_PREFERENCE_CONFIG = resolveFromBaseURL("loaded_learner_preferences_brightness_iris.json"); PREFERENCE_DATA = resolveFromBaseURL("preference_data.csv"); + + OCT_ACTIVITY_CONFIG = resolveFromBaseURL("2019-oct-28-learner.json"); + OCT_LOADED_ACTIVITY_CONFIG = resolveFromBaseURL("2019-oct-28-loaded_learner.json"); + OCT_ACTIVITY_DATA = resolveFromBaseURL("activity_data/28_08_2019_H14_14/result_all_items_EVERYTHING.csv"); } private static URL resolveFromBaseURL(String filename) throws MalformedURLException { @@ -48,7 +55,6 @@ public class LearnerTest { @Before public void initLearner() { sut = new LearnerSubjectUnderTest(); - sut.init(); } @Test @@ -56,6 +62,7 @@ public class LearnerTest { LearnerTestUtils.testLearner(sut, settingsActivities()); } + @Ignore @Test public void testPreferences() throws IOException { LearnerTestUtils.testLearner(sut, settingsPreferences()); @@ -73,11 +80,27 @@ public class LearnerTest { .setConfigURL(LOADED_PREFERENCE_CONFIG)); } + @Ignore // takes longer than 10min + @Test + public void testOctoberActivities() throws IOException { + LearnerTestUtils.testLearner(sut, settingsActivities() + .setConfigURL(OCT_ACTIVITY_CONFIG) + .setDataURL(OCT_ACTIVITY_DATA)); + } + + @Ignore // not working currently + @Test + public void testLoadedOctoberActivities() throws IOException { + LearnerTestUtils.testLearner(sut, settingsActivities() + .setConfigURL(OCT_LOADED_ACTIVITY_CONFIG) + .setDataURL(OCT_ACTIVITY_DATA) + .setVerbose(true)); + } + private LearnerTestSettings settingsActivities() throws IOException { return new LearnerTestSettings() .setConfigURL(ACTIVITY_CONFIG) .setDataURL(ACTIVITY_DATA) - .setExpectedOutput(line -> line[12]) .setOutputItemProvider(() -> sut.root.getSmartHomeEntityModel().getActivityItem()) .setStateOfOutputItem(item -> sut.root.currentActivityName()) .setFactoryTarget(ACTIVITY_RECOGNITION) diff --git a/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestConstants.java b/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestConstants.java index 27785f59..5ba44038 100644 --- a/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestConstants.java +++ b/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestConstants.java @@ -12,19 +12,22 @@ public interface LearnerTestConstants { double MAX_COLOR_DIFFERENCE = 0.2; /** Weights for difference (in order: Hue, Saturation, Brightness) when comparing colors */ double[] COLOR_WEIGHTS = new double[]{0.8/360, 0.1/100, 0.1/100}; - /** Names of item names for activity recognition, in test data */ - String[] ACTIVITY_INPUT_ITEM_NAMES = new String[]{"m_accel_x", "m_accel_y", "m_accel_z", "m_rotation_x", "m_rotation_y", - "m_rotation_z", "w_accel_x", "w_accel_y", "w_accel_z", "w_rotation_x", "w_rotation_y", "w_rotation_z"}; - /** Names of item names for preference learning, in test data */ - String[] PREFERENCE_INPUT_ITEM_NAMES = new String[]{"activity", "w_brightness"}; /** Name of the item which is targeted by preference learning, in test data */ String PREFERENCE_OUTPUT_ITEM_NAME = "iris1_item"; /** Labels of activities, in test data */ - String[] ACTIVITY_NAMES = new String[]{"working", - "walking", - "dancing", - "lying", - "getting up", - "reading" - }; + String[] ACTIVITY_NAMES = new String[]{ + "working", + "walking", + "dancing", + "lying", + "getting up", + "reading", + "DoorClosedPIn", + "DoorClosedPOut", + "DoorOpenedPIn", + "DoorOpenedPOut", + "Reading", + "TVWatching", + "Working", + }; } diff --git a/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestSettings.java b/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestSettings.java index d1751330..c016f604 100644 --- a/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestSettings.java +++ b/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestSettings.java @@ -24,17 +24,18 @@ import java.util.function.Supplier; class LearnerTestSettings { private URL configURL; private URL dataURL; - private Function<String[], String> expectedOutput; + private Function<List<String>, String> expectedOutput = targetValues -> targetValues.get(0); private final Map<String, BiConsumer<Item, String>> specialInputHandler = new HashMap<>(); private Supplier<Item> outputItemProvider; private Function<Item, String> stateOfOutputItem; private CheckUpdate checkUpdate = String::equals; private MachineLearningHandlerFactory.MachineLearningHandlerFactoryTarget factoryTarget; private boolean singleUpdateList; + private boolean verbose = false; @Getter(AccessLevel.NONE) @Setter(AccessLevel.NONE) - private transient LearnerScenarioDefinition settings; + private transient LearnerScenarioDefinition scenarioSettings; @SuppressWarnings("SameParameterValue") LearnerTestSettings putSpecialInputHandler(String itemName, BiConsumer<Item, String> handler) { @@ -43,13 +44,12 @@ class LearnerTestSettings { } LearnerTestSettings setConfigURL(URL configURL) throws IOException { - settings = LearnerScenarioDefinition.loadFrom(configURL); + scenarioSettings = LearnerScenarioDefinition.loadFrom(configURL); this.configURL = configURL; return this; } - List<String> getInputItemNames() { - return settings.relevantItemNames; + LearnerScenarioDefinition getScenarioSettings() { + return scenarioSettings; } - } diff --git a/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestUtils.java b/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestUtils.java index 0e864cbb..5f693e29 100644 --- a/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestUtils.java +++ b/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestUtils.java @@ -1,24 +1,30 @@ package de.tudresden.inf.st.eraser.feedbackloop.learner_backup; +import com.opencsv.CSVParserBuilder; import com.opencsv.CSVReader; +import com.opencsv.CSVReaderBuilder; +import de.tudresden.inf.st.eraser.feedbackloop.learner_backup.data.LearnerScenarioDefinition; +import de.tudresden.inf.st.eraser.feedbackloop.learner_backup.data.LearnerSettings; +import de.tudresden.inf.st.eraser.feedbackloop.learner_backup.data.SimpleColumnDefinition; import de.tudresden.inf.st.eraser.jastadd.model.*; import de.tudresden.inf.st.eraser.util.ParserUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.junit.Test; +import org.encog.ml.data.versatile.columns.ColumnType; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.stream.Stream; import static de.tudresden.inf.st.eraser.feedbackloop.learner_backup.LearnerTestConstants.COLOR_WEIGHTS; import static de.tudresden.inf.st.eraser.feedbackloop.learner_backup.LearnerTestConstants.MAX_COLOR_DIFFERENCE; -import static org.hamcrest.Matchers.greaterThan; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; /** * Utility methods to keep test code clean. @@ -29,24 +35,17 @@ public class LearnerTestUtils { private static final Logger logger = LogManager.getLogger(LearnerTestUtils.class); - static Root createKnowledgeBase() { + static Root createKnowledgeBase(LearnerTestSettings settings) { Root result = Root.createEmptyRoot(); Group group = new Group(); result.getSmartHomeEntityModel().addGroup(group); // init items - Stream.concat(Arrays.stream(LearnerTestConstants.ACTIVITY_INPUT_ITEM_NAMES), - Stream.concat(Arrays.stream(LearnerTestConstants.PREFERENCE_INPUT_ITEM_NAMES), Stream.of(LearnerTestConstants.PREFERENCE_OUTPUT_ITEM_NAME))) + Stream.concat(settings.getScenarioSettings().relevantItemNames.stream(), + settings.getScenarioSettings().targetItemNames.stream()) .distinct().forEach( itemName -> { if (itemName.equals("activity")) return; - Item item; - switch(itemName) { - case LearnerTestConstants.PREFERENCE_OUTPUT_ITEM_NAME: item = new ColorItem(); break; - case "w_brightness": item = new StringItem(); break; - default: - item = new NumberItem(); - } - item.setID(itemName); + Item item = createItem(itemName); ParserUtils.createMqttTopic(item, itemName, result); group.addItem(item); } @@ -58,36 +57,90 @@ public class LearnerTestUtils { return result; } + private static Item createItem(String itemName) { + Item item; + if (itemName.contains("OpenClose")) { + // contact item + item = new ContactItem(); + } else if (itemName.contains("Fibaro")) { + // boolean item + item = new SwitchItem(); + } else { + switch (itemName) { + case "work_device_online_state": + item = new SwitchItem(); + break; + case LearnerTestConstants.PREFERENCE_OUTPUT_ITEM_NAME: + item = new ColorItem(); + break; + case "w_brightness": + item = new StringItem(); + break; + default: item = new NumberItem(); + } + } + item.setID(itemName); + return item; + } + static void testLearner(LearnerSubjectUnderTest sut, LearnerTestSettings settings) { + sut.init(settings); // maybe use factory.createModel() here instead // go through same csv as for training and test some of the values int correct = 0, wrong = 0; try(InputStream is = settings.getDataURL().openStream(); Reader reader = new InputStreamReader(is); - CSVReader csvreader = new CSVReader(reader)) { + CSVReader csvreader = createCSVReader(reader, settings)) { sut.initFor(settings.getFactoryTarget(), settings.getConfigURL()); int index = 0; + LearnerScenarioDefinition scenarioSettings = settings.getScenarioSettings(); + LearnerSettings definition = LearnerSettings.loadFrom(scenarioSettings.getDefinitionFileAsURL()); + List<String> targetValues; for (String[] line : csvreader) { + // only check every 10th line, push an update for every input column if (++index % 10 == 0) { - // only check every 10th line, push an update for every 12 input columns - List<Item> itemsToUpdate = new ArrayList<>(settings.getInputItemNames().size()); - for (int i = 0; i < settings.getInputItemNames().size(); i++) { - String itemName = settings.getInputItemNames().get(i); + // Attention: Not every column might be relevant + targetValues = new ArrayList<>(); + int lineSize = line.length; + int inputSize = scenarioSettings.relevantItemNames.size(); + List<Item> itemsToUpdate = new ArrayList<>(inputSize); + for (int i = 0; i < lineSize; i++) { + SimpleColumnDefinition column = definition.columns.get(i); + switch (column.kind) { + case input: + // do nothing + break; + case target: + targetValues.add(line[i]); + continue; + case ignored: + continue; + } + if (column.type == ColumnType.ignore) { + continue; + } + // use itemName == name of column (or a non-trivial mapping, if any) + String itemName = scenarioSettings.nonTrivialOutputMappings.getOrDefault(column.name, column.name); Item item = sut.root.getSmartHomeEntityModel().resolveItem(itemName) .orElseThrow(() -> new AssertionError("Item " + itemName + " not found")); if (settings.getSpecialInputHandler().containsKey(itemName)) { + if (settings.isVerbose()) { + logger.debug("Setting {} {} using special handler and value '{}' (column {})", + item, item.getID(), line[i], i); + } settings.getSpecialInputHandler().get(itemName).accept(item, line[i]); } else { + if (settings.isVerbose()) { + logger.debug("Setting {} {} using '{}' (column {})", item, item.getID(), line[i], i); + } item.setStateFromString(line[i]); } - if (settings.isSingleUpdateList()) { - itemsToUpdate.add(item); - } else { - sut.encoder.newData(Collections.singletonList(item)); - } + itemsToUpdate.add(item); } if (settings.isSingleUpdateList()) { sut.encoder.newData(itemsToUpdate); + } else { + itemsToUpdate.forEach(item -> sut.encoder.newData(Collections.singletonList(item))); } MachineLearningResult result = sut.decoder.classify(); // check if only one item is to be updated @@ -97,16 +150,19 @@ public class LearnerTestUtils { assertEquals("Output item not to be updated!", settings.getOutputItemProvider().get(), update.getItem()); update.apply(); // check if the correct new state was set - String expected = settings.getExpectedOutput().apply(line); + assertThat("No target values found in this row!", targetValues, not(empty())); + String expected = settings.getExpectedOutput().apply(targetValues); String actual = settings.getStateOfOutputItem().apply(update.getItem()); if (settings.getCheckUpdate().assertEquals(expected, actual)) { correct++; } else { wrong++; - logger.debug("Result not equal, expected '{}' but was '{}'", expected, actual); + if (settings.isVerbose()) { + logger.debug("Result not equal, expected '{}' but was '{}'", expected, actual); + } } - } - } + } // end if index % 10 == 0 + } // end for } catch (IOException | ClassNotFoundException e) { throw new AssertionError(e); } finally { @@ -118,14 +174,28 @@ public class LearnerTestUtils { assertThat(accuracy, greaterThan(LearnerTestConstants.MIN_ACCURACY)); } + private static CSVReader createCSVReader(Reader reader, LearnerTestSettings settings) { + char separator; + switch(settings.getScenarioSettings().csvFormat) { + case "DECIMAL_POINT": separator=','; break; + case "DECIMAL_COMMA": separator=';'; break; + default: + logger.warn("Unknown CSV format, using default comma as separator"); + separator=','; + } + return new CSVReaderBuilder(reader) + .withCSVParser(new CSVParserBuilder().withSeparator(separator).build()) + .build(); + } + @FunctionalInterface public interface CheckUpdate { boolean assertEquals(String expected, String actual); } - static String decodeOutput(String[] line) { - int color = Integer.parseInt(line[2]); - int brightness = Integer.parseInt(line[3]); + static String decodeOutput(List<String> targetValues) { + int color = Integer.parseInt(targetValues.get(0)); + int brightness = Integer.parseInt(targetValues.get(1)); return TupleHSB.of(color, 100, brightness).toString(); } @@ -153,76 +223,4 @@ public class LearnerTestUtils { // diffHue, diffSaturation, diffBrightness, total, MAX_COLOR_DIFFERENCE); return total < MAX_COLOR_DIFFERENCE; } - - @Test - public void testColorSimilar() { - Map<String, TupleHSB> colors = new HashMap<>(); - - // reddish target colors - colors.put("pink", TupleHSB.of(350, 100, 82)); - colors.put("orangeRed", TupleHSB.of(16, 100, 45)); - colors.put("lightPink", TupleHSB.of(351, 100, 80)); - colors.put("darkSalmon", TupleHSB.of(15, 71, 67)); - colors.put("lightCoral", TupleHSB.of(0, 78, 63)); - colors.put("darkRed", TupleHSB.of(0, 100, 16)); - colors.put("indianRed", TupleHSB.of(0, 53, 49)); - colors.put("lavenderBlush", TupleHSB.of(340, 100, 95)); - colors.put("lavender", TupleHSB.of(240, 66, 90)); - String[] targetColors = new String[]{"pink", "orangeRed", "lightPink", "darkSalmon", "lightCoral", - "darkRed", "indianRed", "lavenderBlush", "lavender"}; - - // reference colors - colors.put("blue", TupleHSB.of(240, 100, 11)); - colors.put("blueViolet", TupleHSB.of(271, 75, 36)); - colors.put("magenta", TupleHSB.of(300, 100, 41)); - colors.put("purple", TupleHSB.of(300, 100, 20)); - colors.put("red", TupleHSB.of(0, 100, 29)); - colors.put("tomato", TupleHSB.of(9, 100, 55)); - colors.put("orange", TupleHSB.of(39, 100, 67)); - colors.put("yellow", TupleHSB.of(60, 100, 88)); - colors.put("yellowGreen", TupleHSB.of(80, 60, 67)); - colors.put("green", TupleHSB.of(120, 100, 29)); - colors.put("springGreen", TupleHSB.of(150, 100, 64)); - colors.put("cyan", TupleHSB.of(180, 100, 69)); - colors.put("ivory", TupleHSB.of(60, 100, 98)); - - String[] referenceColors = new String[]{"blue", "blueViolet", "magenta", "purple", "red", "tomato", - "orange", "yellow", "yellowGreen", "green", "springGreen", "cyan", "ivory"}; - - /* Code to help producing similarity matrix */ -// for (String target : targetColors) { -// String tmp = ""; -// for (String reference : referenceColors) { -// tmp += assertColorSimilar(colors, target, reference) ? "x" : " "; -// tmp += ","; -// } -// System.out.println( "***" + target + ": " + tmp); -// } - - String[] similarityMatrix = new String[]{ - "blue, blueViolet, magenta, purple, red, tomato, orange, yellow, yellowGreen, green, springGreen, cyan, ivory", // <- reference colors - " , , x , x , x , x , x , x , , , , , x ", // pink - " , , x , x , x , x , x , x , , , , , x ", // orangeRed - " , , x , x , x , x , x , x , , , , , x ", // lightPink - " , , , , x , x , x , x , x , , , , x ", // darkSalmon - " , , x , x , x , x , x , x , x , , , , x ", // lightCoral - " , , x , x , x , x , x , , , , , , ", // darkRed - " , , x , , x , x , x , , , , , , ", // indianRed - " , , x , x , x , x , x , x , , , , , x ", // lavenderBlush - " x , x , , , , , , , , , , x , "}; // lavender - - for (int targetIndex = 0; targetIndex < targetColors.length; targetIndex++) { - String target = targetColors[targetIndex]; - String[] expectedValues = similarityMatrix[targetIndex + 1].split(","); - for (int referenceIndex = 0; referenceIndex < referenceColors.length; referenceIndex++) { - String reference = referenceColors[referenceIndex]; - boolean expectedToBeSimilar = expectedValues[referenceIndex].contains("x"); - String message = String.format("%s iss%s expected to be similar to %s, but %s!", - target, expectedToBeSimilar ? "" : " not", reference, expectedToBeSimilar ? "differs" : "it was"); - assertEquals(message, expectedToBeSimilar, - colorSimilar(colors.get(reference).toString(), colors.get(target).toString())); - } - } - } - } diff --git a/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestUtilsTest.java b/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestUtilsTest.java new file mode 100644 index 00000000..49209f2e --- /dev/null +++ b/feedbackloop.learner_backup/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/learner_backup/LearnerTestUtilsTest.java @@ -0,0 +1,88 @@ +package de.tudresden.inf.st.eraser.feedbackloop.learner_backup; + +import de.tudresden.inf.st.eraser.jastadd.model.TupleHSB; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * Tests for the utility methods. + * + * @author rschoene - Initial contribution + */ +public class LearnerTestUtilsTest { + + @Test + public void testColorSimilar() { + Map<String, TupleHSB> colors = new HashMap<>(); + + // reddish target colors + colors.put("pink", TupleHSB.of(350, 100, 82)); + colors.put("orangeRed", TupleHSB.of(16, 100, 45)); + colors.put("lightPink", TupleHSB.of(351, 100, 80)); + colors.put("darkSalmon", TupleHSB.of(15, 71, 67)); + colors.put("lightCoral", TupleHSB.of(0, 78, 63)); + colors.put("darkRed", TupleHSB.of(0, 100, 16)); + colors.put("indianRed", TupleHSB.of(0, 53, 49)); + colors.put("lavenderBlush", TupleHSB.of(340, 100, 95)); + colors.put("lavender", TupleHSB.of(240, 66, 90)); + String[] targetColors = new String[]{"pink", "orangeRed", "lightPink", "darkSalmon", "lightCoral", + "darkRed", "indianRed", "lavenderBlush", "lavender"}; + + // reference colors + colors.put("blue", TupleHSB.of(240, 100, 11)); + colors.put("blueViolet", TupleHSB.of(271, 75, 36)); + colors.put("magenta", TupleHSB.of(300, 100, 41)); + colors.put("purple", TupleHSB.of(300, 100, 20)); + colors.put("red", TupleHSB.of(0, 100, 29)); + colors.put("tomato", TupleHSB.of(9, 100, 55)); + colors.put("orange", TupleHSB.of(39, 100, 67)); + colors.put("yellow", TupleHSB.of(60, 100, 88)); + colors.put("yellowGreen", TupleHSB.of(80, 60, 67)); + colors.put("green", TupleHSB.of(120, 100, 29)); + colors.put("springGreen", TupleHSB.of(150, 100, 64)); + colors.put("cyan", TupleHSB.of(180, 100, 69)); + colors.put("ivory", TupleHSB.of(60, 100, 98)); + + String[] referenceColors = new String[]{"blue", "blueViolet", "magenta", "purple", "red", "tomato", + "orange", "yellow", "yellowGreen", "green", "springGreen", "cyan", "ivory"}; + + /* Code to help producing similarity matrix */ +// for (String target : targetColors) { +// String tmp = ""; +// for (String reference : referenceColors) { +// tmp += assertColorSimilar(colors, target, reference) ? "x" : " "; +// tmp += ","; +// } +// System.out.println( "***" + target + ": " + tmp); +// } + + String[] similarityMatrix = new String[]{ + "blue, blueViolet, magenta, purple, red, tomato, orange, yellow, yellowGreen, green, springGreen, cyan, ivory", // <- reference colors + " , , x , x , x , x , x , x , , , , , x ", // pink + " , , x , x , x , x , x , x , , , , , x ", // orangeRed + " , , x , x , x , x , x , x , , , , , x ", // lightPink + " , , , , x , x , x , x , x , , , , x ", // darkSalmon + " , , x , x , x , x , x , x , x , , , , x ", // lightCoral + " , , x , x , x , x , x , , , , , , ", // darkRed + " , , x , , x , x , x , , , , , , ", // indianRed + " , , x , x , x , x , x , x , , , , , x ", // lavenderBlush + " x , x , , , , , , , , , , x , "}; // lavender + + for (int targetIndex = 0; targetIndex < targetColors.length; targetIndex++) { + String target = targetColors[targetIndex]; + String[] expectedValues = similarityMatrix[targetIndex + 1].split(","); + for (int referenceIndex = 0; referenceIndex < referenceColors.length; referenceIndex++) { + String reference = referenceColors[referenceIndex]; + boolean expectedToBeSimilar = expectedValues[referenceIndex].contains("x"); + String message = String.format("%s iss%s expected to be similar to %s, but %s!", + target, expectedToBeSimilar ? "" : " not", reference, expectedToBeSimilar ? "differs" : "it was"); + assertEquals(message, expectedToBeSimilar, + LearnerTestUtils.colorSimilar(colors.get(reference).toString(), colors.get(target).toString())); + } + } + } +} diff --git a/feedbackloop.learner_backup/src/test/resources/2019-oct-28-activity_definition.json b/feedbackloop.learner_backup/src/test/resources/2019-oct-28-activity_definition.json new file mode 120000 index 00000000..de4c267d --- /dev/null +++ b/feedbackloop.learner_backup/src/test/resources/2019-oct-28-activity_definition.json @@ -0,0 +1 @@ +../../../src/main/resources/2019-oct-28-activity_definition.json \ No newline at end of file diff --git a/feedbackloop.learner_backup/src/test/resources/2019-oct-28-activity_network.eg b/feedbackloop.learner_backup/src/test/resources/2019-oct-28-activity_network.eg new file mode 120000 index 00000000..cc1061a8 --- /dev/null +++ b/feedbackloop.learner_backup/src/test/resources/2019-oct-28-activity_network.eg @@ -0,0 +1 @@ +../../../src/main/resources/2019-oct-28-activity_network.eg \ No newline at end of file diff --git a/feedbackloop.learner_backup/src/test/resources/2019-oct-28-activity_normalizer.json b/feedbackloop.learner_backup/src/test/resources/2019-oct-28-activity_normalizer.json new file mode 120000 index 00000000..155f7b9f --- /dev/null +++ b/feedbackloop.learner_backup/src/test/resources/2019-oct-28-activity_normalizer.json @@ -0,0 +1 @@ +../../../src/main/resources/2019-oct-28-activity_normalizer.json \ No newline at end of file diff --git a/feedbackloop.learner_backup/src/test/resources/2019-oct-28-learner.json b/feedbackloop.learner_backup/src/test/resources/2019-oct-28-learner.json new file mode 120000 index 00000000..dff51597 --- /dev/null +++ b/feedbackloop.learner_backup/src/test/resources/2019-oct-28-learner.json @@ -0,0 +1 @@ +../../../src/main/resources/2019-oct-28-learner.json \ No newline at end of file diff --git a/feedbackloop.learner_backup/src/test/resources/2019-oct-28-loaded_learner.json b/feedbackloop.learner_backup/src/test/resources/2019-oct-28-loaded_learner.json new file mode 120000 index 00000000..9fb3eb16 --- /dev/null +++ b/feedbackloop.learner_backup/src/test/resources/2019-oct-28-loaded_learner.json @@ -0,0 +1 @@ +../../../src/main/resources/2019-oct-28-loaded_learner.json \ No newline at end of file -- GitLab