Skip to content
Snippets Groups Projects
Commit d3fefce4 authored by René Schöne's avatar René Schöne
Browse files

Progressing to integration of machine learning.

- Added setKnowledgeBase to MachineLearningEncoder and -Decoder, and removed Root argument in other methods
- Changed Learner-Impl to match new adapters
- Updated starter to new adapters, and to use CSV files for initialization of learner
parent f98023e4
Branches
No related tags found
No related merge requests found
Showing
with 246 additions and 145 deletions
......@@ -288,7 +288,7 @@ aspect ItemHandling {
//--- sendState ---
protected void Item.sendState() throws Exception {
for (MachineLearningModel model : getRelevantInMachineLearningModels()) {
model.getEncoder().newData(getRoot(), java.util.Collections.singletonList(this));
model.getEncoder().newData(Collections.singletonList(this));
}
}
......
......@@ -22,17 +22,22 @@ public class InternalMachineLearningHandler implements MachineLearningEncoder, M
}
@Override
public void newData(Root model, List<Item> changedItems) {
public void setKnowledgeBaseRoot(Root root) {
// ignored
}
@Override
public void newData(List<Item> changedItems) {
logger.debug("Ignored new data of {}", changedItems);
}
@Override
public List<Item> getTargets(Root root) {
public List<Item> getTargets() {
return model.getTargetItems();
}
@Override
public List<Item> getRelevantItems(Root root) {
public List<Item> getRelevantItems() {
return model.getRelevantItems();
}
......
......@@ -9,7 +9,7 @@ import java.time.Instant;
* @author rschoene - Initial contribution
*/
@SuppressWarnings("unused")
public interface MachineLearningDecoder {
public interface MachineLearningDecoder extends MachineLearningSetRoot {
/**
* Execute the machine learning model and returns the classification result.
......
package de.tudresden.inf.st.eraser.jastadd.model;
import de.tudresden.inf.st.eraser.jastadd.model.Item;
import de.tudresden.inf.st.eraser.jastadd.model.Root;
import java.util.List;
/**
......@@ -13,14 +10,13 @@ import java.util.List;
* @author rschoene - Initial contribution
*/
@SuppressWarnings("unused")
public interface MachineLearningEncoder {
public interface MachineLearningEncoder extends MachineLearningSetRoot {
/**
* Update when new data is available.
* @param model The underlying model
* @param changedItems A list of items whose state has changed
*/
void newData(Root model, List<Item> changedItems);
void newData(List<Item> changedItems);
// to be discussed, in which form this is specified
......@@ -28,7 +24,7 @@ public interface MachineLearningEncoder {
* Get the items that this model is supposed to change.
* @return the list of targeted items
*/
List<Item> getTargets(Root model);
List<Item> getTargets();
// to be discussed, in which form this is specified
......@@ -36,7 +32,7 @@ public interface MachineLearningEncoder {
* Get the items which are relevant for the decision making of this model.
* @return the list of items relevant for decision making
*/
List<Item> getRelevantItems(Root model);
List<Item> getRelevantItems();
// to be discussed, if this is necessary
......
package de.tudresden.inf.st.eraser.jastadd.model;
/**
* Common interface for both {@link MachineLearningDecoder} and {@link MachineLearningEncoder}.
*
* @author rschoene - Initial contribution
*/
public interface MachineLearningSetRoot {
/**
* Informs this handler of the knowledge base.
* This method is called before any other of the interface methods.
* @param root The root node of the knowledge base
*/
void setKnowledgeBaseRoot(Root root);
}
......@@ -18,7 +18,8 @@ dependencies {
compile project(':feedbackloop.analyze')
compile project(':feedbackloop.plan')
compile project(':feedbackloop.execute')
compile project(':feedbackloop.learner')
// compile project(':feedbackloop.learner')
compile project(':feedbackloop.learner_backup')
compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.9.8'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.8'
compile group: 'net.sourceforge.argparse4j', name: 'argparse4j', version: '0.8.1'
......
......@@ -6,12 +6,11 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import de.tudresden.inf.st.eraser.feedbackloop.analyze.AnalyzeImpl;
import de.tudresden.inf.st.eraser.feedbackloop.api.Analyze;
import de.tudresden.inf.st.eraser.feedbackloop.api.Execute;
import de.tudresden.inf.st.eraser.feedbackloop.api.Learner;
import de.tudresden.inf.st.eraser.feedbackloop.api.Plan;
import de.tudresden.inf.st.eraser.feedbackloop.api.EncogModel;
import de.tudresden.inf.st.eraser.feedbackloop.execute.ExecuteImpl;
import de.tudresden.inf.st.eraser.feedbackloop.learner.LearnerHelper;
import de.tudresden.inf.st.eraser.feedbackloop.learner.LearnerImpl;
import de.tudresden.inf.st.eraser.feedbackloop.learner_backup.Learner;
import de.tudresden.inf.st.eraser.feedbackloop.learner_backup.MachineLearningImpl;
import de.tudresden.inf.st.eraser.feedbackloop.plan.PlanImpl;
import de.tudresden.inf.st.eraser.jastadd.model.*;
import de.tudresden.inf.st.eraser.openhab2.OpenHab2Importer;
......@@ -113,52 +112,38 @@ public class EraserStarter {
}
}
// initialize backup learner
Learner learner = new Learner();
// initialize activity recognition
MachineLearningRoot machineLearningRoot = root.getMachineLearningRoot();
if (settings.activity.dummy) {
logger.info("Using dummy activity recognition");
logger.info("Using dummy activity recognition, ignoring other settings for this");
machineLearningRoot.setActivityRecognition(DummyMachineLearningModel.createDefault());
} else {
logger.error("Reading activity recognition from file is not supported yet!");
// TODO
MachineLearningImpl handler = new MachineLearningImpl(learner, MachineLearningImpl.GOAL_ACTIVITY_PHONE_AND_WATCH);
handler.setKnowledgeBaseRoot(root);
logger.info("Reading activity recognition from csv file {}", settings.activity.file);
handler.initActivities(settings.activity.realURL().toString());
ExternalMachineLearningModel machineLearningModel = new ExternalMachineLearningModel();
machineLearningModel.setEncoder(handler);
machineLearningModel.setDecoder(handler);
root.getMachineLearningRoot().setActivityRecognition(machineLearningModel);
}
// initialize preference learning
if (settings.preference.dummy) {
logger.info("Using dummy preference learning");
logger.info("Using dummy preference learning, ignoring other settings for this");
machineLearningRoot.setPreferenceLearning(DummyMachineLearningModel.createDefault());
} else {
logger.info("Reading preference learning from file {}", settings.preference.file);
Learner learner = new LearnerImpl();
// there should be a method to load a model using an URL
boolean loadingSuccessful = false;
try (InputStream input = settings.preference.realURL().openStream()) {
loadingSuccessful = learner.loadModelFromFile(input, settings.preference.id,
Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
} catch (IOException e) {
logger.catching(e);
loadingSuccessful = false;
}
// Model preference = learner.getTrainedModel(settings.preference.realURL(), settings.preference.id);
logger.debug("Loading of {} was {}", settings.preference.realURL(), loadingSuccessful ? "successful" : "failed");
if (loadingSuccessful) {
EncogModel preference = learner.getTrainedModel(settings.preference.id);
NeuralNetworkRoot neuralNetwork = LearnerHelper.transform(preference);
if (neuralNetwork == null) {
logger.error("Could not create preference model, see possible previous errors.");
} else {
machineLearningRoot.setPreferenceLearning(neuralNetwork);
neuralNetwork.setOutputApplication(zeroToThree -> 33 * zeroToThree);
JavaUtils.ifPresentOrElse(
model.resolveItem(settings.preference.affectedItem),
item -> neuralNetwork.getOutputLayer().setAffectedItem(item),
() -> logger.error("Output item not set from value '{}'", settings.preference.affectedItem));
}
} else {
// loading was not successful
logger.warn("Falling back to dummy preference learning");
machineLearningRoot.setPreferenceLearning(DummyMachineLearningModel.createDefault());
}
logger.info("Reading preference learning from csv file {}", settings.preference.file);
MachineLearningImpl handler = new MachineLearningImpl(learner, MachineLearningImpl.GOAL_PREFERENCE_BRIGHTNESS_IRIS);
handler.setKnowledgeBaseRoot(root);
handler.initPreferences(settings.preference.realURL().toString());
ExternalMachineLearningModel machineLearningModel = new ExternalMachineLearningModel();
machineLearningModel.setEncoder(handler);
machineLearningModel.setDecoder(handler);
root.getMachineLearningRoot().setPreferenceLearning(machineLearningModel);
}
machineLearningRoot.getPreferenceLearning().connectItems(settings.preference.items);
if (!machineLearningRoot.getActivityRecognition().check()) {
......
......@@ -24,8 +24,8 @@ load:
# Model for activity recognition. If dummy is true, then the file parameter is ignored.
activity:
# File to read in. Expected format = eg
file: activity.eg
# File to read in. Expected format = csv
file: datasets/backup/activity_data.csv
# Use dummy model in which the current activity is directly editable. Default: false.
dummy: true
# Model id. Default: 1.
......@@ -33,19 +33,16 @@ activity:
# Model for preference learning. If dummy is true, then the file parameter is ignored.
preference:
# File to read in. Expected format = eg
file: preference.eg
# File to read in. Expected format = csv
file: datasets/backup/preference_data.csv
# Use dummy model in which the current activity is directly editable. Default: false.
dummy: false
# Model id. Default: 1.
id: 1
# Items to connect to inputs
items:
- datetime_month
- datetime_day
- datetime_hour
- datetime_minute
# - activity
- activity
- brightness
# Item to change with classification result
affectedItem: iris1_item
......
package de.tudresden.inf.st.eraser.feedbackloop.learner_backup;
import de.tudresden.inf.st.eraser.jastadd.model.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.time.Instant;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class MachineLearningImpl implements MachineLearningDecoder, MachineLearningEncoder {
private String[] new_data = new String[13];
private List<Item> target_item_list;
private List<Item> relevant_item_list;
private String[] result;
private MachineLearningResult ml_result;
private List<ItemPreference> item_preference_list;
private Root root;
private final Logger logger = LogManager.getLogger(MachineLearningImpl.class);
private final Learner learner;
private final int goal;
public static final int GOAL_ACTIVITY_PHONE_AND_WATCH = 1;
public static final int GOAL_PREFERENCE_BRIGHTNESS_IRIS = 2;
public MachineLearningImpl(Learner learner, int goal) {
this.learner = learner;
this.goal = goal;
}
@Override
public void setKnowledgeBaseRoot(Root root) {
this.root = root;
updateItems();
}
private void updateItems() {
OpenHAB2Model model = root.getOpenHAB2Model();
List<String> targetItemNames, relevantItemNames;
switch (this.goal) {
case GOAL_ACTIVITY_PHONE_AND_WATCH:
targetItemNames = Collections.singletonList("activity");
relevantItemNames = Arrays.asList(
"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",
"w_brightness"
);
break;
case GOAL_PREFERENCE_BRIGHTNESS_IRIS:
targetItemNames = Collections.singletonList("iris1_item");
relevantItemNames = Arrays.asList(
"activity",
"room_brightness"
);
break;
default:
logger.error("Unknown goal value ({}) set", this.goal);
targetItemNames = Collections.emptyList();
relevantItemNames = Collections.emptyList();
}
target_item_list = targetItemNames.stream()
.map(name -> resolve(model, name))
.filter(Objects::nonNull)
.collect(Collectors.toList());
relevant_item_list = relevantItemNames.stream()
.map(name -> resolve(model, name))
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
private Item resolve(OpenHAB2Model model, String id) {
Optional<Item> maybeItem = model.resolveItem(id);
if (maybeItem.isPresent()) {
return maybeItem.get();
} else {
logger.warn("Could not find item with id {}", id);
return null;
}
}
@Override
public void newData(Root model, List<Item> changedItems) {
/**String topic = changedItems.get(0).getTopic().toString();
public void newData(List<Item> changedItems) {
/* String topic = changedItems.get(0).getTopic().toString();
if(topic.equals("oh2/samsung/items1")){
new_data[0]=changedItems.get(0).influxMeasurementName();
}
model.getOpenHAB2Model().items();
Item iris_item=model.getOpenHAB2Model().resolveItem("iris_item").get();
iris_item.getStateAsString();*/
/* FIXME either save state of unchanged items here (if only changed items are reported) <- pull model
or let knowledge base pass all relevant items <- push model
*/
String[] new_data = new String[13];
int i = 0;
for (Item item : changedItems) {
if (i < 13) {
......@@ -29,58 +108,22 @@ public class MachineLearningImpl implements MachineLearningDecoder,MachineLearni
i++;
}
}
Learner learner= new Learner();
result = learner.predictor(new_data);
}
@Override
public List<Item> getTargets(Root model) {
Item iris_item= model.getOpenHAB2Model().resolveItem("iris_item").get();
target_item_list.add(iris_item);
public List<Item> getTargets() {
return target_item_list;
}
@Override
public List<Item> getRelevantItems(Root model) {
Item m_accel_x = model.getOpenHAB2Model().resolveItem("").get();
Item m_accel_y = model.getOpenHAB2Model().resolveItem("").get();
Item m_accel_z = model.getOpenHAB2Model().resolveItem("").get();
Item m_rotation_x = model.getOpenHAB2Model().resolveItem("").get();
Item m_rotation_y = model.getOpenHAB2Model().resolveItem("").get();
Item m_rotation_z = model.getOpenHAB2Model().resolveItem("").get();
Item w_accel_x = model.getOpenHAB2Model().resolveItem("").get();
Item w_accel_y = model.getOpenHAB2Model().resolveItem("").get();
Item w_accel_z = model.getOpenHAB2Model().resolveItem("").get();
Item w_rotation_x = model.getOpenHAB2Model().resolveItem("").get();
Item w_rotation_y = model.getOpenHAB2Model().resolveItem("").get();
Item w_rotation_z = model.getOpenHAB2Model().resolveItem("").get();
Item w_brightness = model.getOpenHAB2Model().resolveItem("").get();
relevant_item_list.add(m_accel_x);
relevant_item_list.add(m_accel_y);
relevant_item_list.add(m_accel_z);
relevant_item_list.add(m_rotation_x);
relevant_item_list.add(m_rotation_y);
relevant_item_list.add(m_rotation_z);
relevant_item_list.add(w_accel_x);
relevant_item_list.add(w_accel_y);
relevant_item_list.add(w_accel_z);
relevant_item_list.add(w_rotation_x);
relevant_item_list.add(w_rotation_y);
relevant_item_list.add(w_rotation_z);
relevant_item_list.add(w_brightness);
public List<Item> getRelevantItems() {
return relevant_item_list;
}
@Override
public void triggerTraining() {
logger.debug("Ignore trigger training call");
}
@Override
......@@ -90,9 +133,40 @@ public class MachineLearningImpl implements MachineLearningDecoder,MachineLearni
@Override
public MachineLearningResult classify() {
String activity=result[0];
switch (this.goal) {
case GOAL_ACTIVITY_PHONE_AND_WATCH:
String activityStringValue = result[0];
Item activityItem = resolve(this.root.getOpenHAB2Model(), "activity");
// FIXME how to translate activityStringValue to a number? or should activity item state better be a String?
logger.debug("Classify would return activity: {}", activityStringValue);
ItemPreference classifiedActivity = new ItemPreferenceDouble(activityItem, 0);
return new MachineLearningResultImpl(classifiedActivity);
case GOAL_PREFERENCE_BRIGHTNESS_IRIS:
String[] preference = {result[1], result[2]};
ml_result.getPreferences();
return ml_result;
// FIXME what is the meaning of result[1] and result[2]
Item iris1 = resolve(this.root.getOpenHAB2Model(), "iris1_item");
ItemPreference classifiedPreference = new ItemPreferenceColor(iris1, TupleHSB.of(0, 0, 0));
return new MachineLearningResultImpl(classifiedPreference);
default:
logger.error("Unknown goal value ({}) set in classify", this.goal);
return new EmptyMachineLearningResult();
}
}
public void initActivities(String filenameOfCsv) {
learner.activity_train(filenameOfCsv);
}
public void initPreferences(String filenameOfCsv) {
learner.preference_train(filenameOfCsv);
}
class EmptyMachineLearningResult implements MachineLearningResult {
@Override
public List<ItemPreference> getPreferences() {
return Collections.emptyList();
}
}
}
package de.tudresden.inf.st.eraser.feedbackloop.learner_backup;
import de.tudresden.inf.st.eraser.jastadd.model.ItemPreference;
import de.tudresden.inf.st.eraser.jastadd.model.MachineLearningResult;
import java.util.Collections;
import java.util.List;
/**
* TODO: Add description.
*
* @author rschoene - Initial contribution
*/
public class MachineLearningResultImpl implements MachineLearningResult {
private final ItemPreference preference;
MachineLearningResultImpl(ItemPreference preference) {
this.preference = preference;
}
@Override
public List<ItemPreference> getPreferences() {
return Collections.singletonList(preference);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment