Skip to content
Snippets Groups Projects
Commit e47b38c1 authored by FRohde's avatar FRohde
Browse files

- added function to read metadata from file (item-id -> input-/output-vector position)

- added documentation to selected classes/methods
- included Kays code changes in June
parent 872a8543
No related branches found
No related tags found
No related merge requests found
Pipeline #4614 failed
...@@ -9,7 +9,7 @@ dependencies { ...@@ -9,7 +9,7 @@ dependencies {
compile group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11' compile group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
compile group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15' compile group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15'
compile group: 'org.influxdb', name: 'influxdb-java', version: '2.15' compile group: 'org.influxdb', name: 'influxdb-java', version: '2.15'
compile project(':feedbackloop.learner') // compile project(':feedbackloop.learner')
testCompile group: 'org.testcontainers', name: 'testcontainers', version: '1.11.2' testCompile group: 'org.testcontainers', name: 'testcontainers', version: '1.11.2'
testCompile group: 'org.testcontainers', name: 'influxdb', version: '1.11.2' testCompile group: 'org.testcontainers', name: 'influxdb', version: '1.11.2'
testCompile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.11.2' testCompile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.11.2'
......
...@@ -18,7 +18,7 @@ dependencies { ...@@ -18,7 +18,7 @@ dependencies {
compile project(':feedbackloop.analyze') compile project(':feedbackloop.analyze')
compile project(':feedbackloop.plan') compile project(':feedbackloop.plan')
compile project(':feedbackloop.execute') compile project(':feedbackloop.execute')
// compile project(':feedbackloop.learner') compile project(':feedbackloop.learner')
compile project(':feedbackloop.learner_backup') compile project(':feedbackloop.learner_backup')
compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.9.8' 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: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.8'
......
package de.tudresden.inf.st.eraser.feedbackloop.learner; package de.tudresden.inf.st.eraser.feedbackloop.learner;
import de.tudresden.inf.st.eraser.feedbackloop.learner.LearnerHelper;
import de.tudresden.inf.st.eraser.jastadd.model.*; import de.tudresden.inf.st.eraser.jastadd.model.*;
import java.time.Instant; import java.time.Instant;
...@@ -6,22 +7,21 @@ import java.util.ArrayList; ...@@ -6,22 +7,21 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Adapter for internally held machine learning models. * Adapter for accessing machine learning models that are used for activity recognition.
* @author MoralDav
* @author Bierzynski
* *
* @author rschoene - Initial contribution
*/ */
public class ActivityLearningHandler extends LearningHandler{ public class ActivityLearningHandler extends LearningHandler{
public ActivityLearningHandler setLearner(LearnerImpl learner) { public ActivityLearningHandler(LearnerImpl learner, OpenHAB2Model openHAB2model){
super(learner,openHAB2model);
return (ActivityLearningHandler)super.setLearner(learner);
} }
public ActivityLearningHandler setModel(InternalMachineLearningModel model) { public void InitActivityLearning(){}
return (ActivityLearningHandler)super.setModel(model);
}
//get items that this model is supposed to change
@Override @Override
public List<Item> getTargets() { public List<Item> getTargets() {
List<Item> targets = new ArrayList<Item>(); List<Item> targets = new ArrayList<Item>();
...@@ -32,6 +32,14 @@ public class ActivityLearningHandler extends LearningHandler{ ...@@ -32,6 +32,14 @@ public class ActivityLearningHandler extends LearningHandler{
return targets ; return targets ;
} }
/**
* Function accesses the meta-information (text file: at which position within the input vector
* are the values for a specific item id expected to be delivered?) of the activity recognition
* Network-object (managed by the Learner-object) to determine those Items whose current values
* are required by the activity recognition machine-learning model for its decision making.
*
* @return
*/
@Override @Override
public List<Item> getRelevantItems() { public List<Item> getRelevantItems() {
List<Item> relevantItems = new ArrayList<Item>(); List<Item> relevantItems = new ArrayList<Item>();
...@@ -47,17 +55,25 @@ public class ActivityLearningHandler extends LearningHandler{ ...@@ -47,17 +55,25 @@ public class ActivityLearningHandler extends LearningHandler{
this.getLogger().debug("Ignored training trigger."); this.getLogger().debug("Ignored training trigger.");
} }
//classify using the input vector given by newData /**
* Function triggers the Learner-object to estimate the current activity using the sensor data
* that are found in the activity learning input vector (which is kept up-to-date by the function
* LearningHandler.newData). The obtained result is wrapped in a PreferenceItem and ExternalMachineLearningResult.
*
* @return
*/
@Override @Override
public MachineLearningResult classify() { public MachineLearningResult classify() {
List<Item> targets = getTargets();//get items that this model is supposed to change List<Item> targets = getTargets();//get items that this model is supposed to change
//Using activity recognition to get current activity //Using activity recognition to get current activity
ActivityItem activity_item = (ActivityItem) targets.get(0);
ActivityItem activity_item = (ActivityItem) targets.get(LearnerHelper.IDX_ACTIVITY_ITEM_TARGET);
//prepare output //prepare output
List<ItemPreference> preferences = new ArrayList<ItemPreference>(); List<ItemPreference> preferences = new ArrayList<ItemPreference>();
ItemPreference preference = getPreferenceItem(activity_item, new double[] {this.getLearner().getActivity()}); double [] activity = new double[] {this.getLearner().getActivity()};
ItemPreference preference = wrapIntoPreferenceItem(activity_item, activity, LearnerHelper.ID_ACTIVITY_MODEL);
preferences.add(preference);//add preference to the preferences array preferences.add(preference);//add preference to the preferences array
......
...@@ -29,7 +29,9 @@ public class LearnerHelper { ...@@ -29,7 +29,9 @@ public class LearnerHelper {
private static DoubleArrayDoubleFunction sigmoid = inputs -> Math.signum(Arrays.stream(inputs).sum()); private static DoubleArrayDoubleFunction sigmoid = inputs -> Math.signum(Arrays.stream(inputs).sum());
private static DoubleArrayDoubleFunction tanh = inputs -> Math.tanh(Arrays.stream(inputs).sum()); private static DoubleArrayDoubleFunction tanh = inputs -> Math.tanh(Arrays.stream(inputs).sum());
private static DoubleArrayDoubleFunction function_one = inputs -> 1.0; private static DoubleArrayDoubleFunction function_one = inputs -> 1.0;
public static int ID_ACTIVITY_MODEL = 0;
public static int ID_PREFERENCE_MODEL = 1;
public static int IDX_ACTIVITY_ITEM_TARGET=0;
public static NeuralNetworkRoot transform(EncogModel encogModel) { public static NeuralNetworkRoot transform(EncogModel encogModel) {
NeuralNetworkRoot result = NeuralNetworkRoot.createEmpty(); NeuralNetworkRoot result = NeuralNetworkRoot.createEmpty();
List<Double> weights = encogModel.getWeights(); List<Double> weights = encogModel.getWeights();
......
...@@ -16,17 +16,18 @@ import org.encog.util.arrayutil.NormalizedField; ...@@ -16,17 +16,18 @@ import org.encog.util.arrayutil.NormalizedField;
import org.encog.util.csv.CSVFormat; import org.encog.util.csv.CSVFormat;
import org.encog.util.csv.ReadCSV; import org.encog.util.csv.ReadCSV;
import java.io.File; import java.io.*;
import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.*; import java.util.*;
import java.util.logging.Level;
/** /**
* Implementation of the Learner. * Implementation of the Learner.
* *
* @author Bierzyns - Initial contribution * @author Bierzyns - Initial contribution
* @author MoralDav
*/ */
public class LearnerImpl implements Learner { public class LearnerImpl implements Learner {
...@@ -38,8 +39,44 @@ public class LearnerImpl implements Learner { ...@@ -38,8 +39,44 @@ public class LearnerImpl implements Learner {
private CSVFormat format = new CSVFormat('.', ','); private CSVFormat format = new CSVFormat('.', ',');
private Map<Integer, Dataset> datasets = new HashMap<>(); private Map<Integer, Dataset> datasets = new HashMap<>();
private Map<Integer, Network> models = new HashMap<>(); private Map<Integer, Network> models = new HashMap<>();
// maps a model-id to an input vector, i.e., to a vector that contains those
// sensor-values/activities that this model will be applied to when LearnerImpl.computeResult
// is called.
private Map<Integer, List<Double>> inputVectors = new HashMap<>(); private Map<Integer, List<Double>> inputVectors = new HashMap<>();
public Map<String, Integer> readMapFromFile(String string_relative_path){
// create and load properties from file
Properties properties = new Properties();
try{
Path relative_path = Paths.get(string_relative_path);
Path absolute_path = relative_path.toAbsolutePath();
FileInputStream inputStream = new FileInputStream(String.valueOf(absolute_path));
if (inputStream != null) {
properties.load(inputStream);
} else {
throw new FileNotFoundException("property file '" + absolute_path.toString() + "' not found ");
}
inputStream.close();
}catch (IOException e){
System.out.println("error");
}
Map<String, Integer> map = new HashMap<>();
for (final String itemId: properties.stringPropertyNames())
map.put(itemId, Integer.parseInt(properties.getProperty(itemId)));
return map;
}
public void InitModelsVectors(String fileInputVector, String fileOutputVector, int modelId){
Network network = models.get(modelId);
Map<String, Integer> mapInput = readMapFromFile(fileInputVector);
network.setIndexInputvector(mapInput);
Map<String, Integer> mapOutput = readMapFromFile(fileOutputVector);
network.setIndexOutputvector(mapOutput);
}
@Override @Override
public void setKnowledgeBase(Root knowledgeBase) { public void setKnowledgeBase(Root knowledgeBase) {
this.knowledgeBase = knowledgeBase; this.knowledgeBase = knowledgeBase;
...@@ -67,46 +104,64 @@ public class LearnerImpl implements Learner { ...@@ -67,46 +104,64 @@ public class LearnerImpl implements Learner {
return true; return true;
} }
public boolean loadModelFromFile(String path, int modelID, List<Integer> inputMaxes,
List<Integer> inputMins, List<Integer> targetMaxes, List<Integer> targetMins) {
logger.debug("Load model from file {}", path);
models.put(modelID, new Network(path, modelID, inputMaxes, inputMins, targetMaxes, targetMins));
return true;
}
@Override @Override
public boolean loadModelFromFile(File file, int modelID, List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes, public boolean loadModelFromFile(File file, int modelID, List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes,
List<Integer> targetMins,List<String> listInputIndex, List<String> listOutputIndex) { List<Integer> targetMins) {
logger.debug("Load model from file {}", file); logger.debug("Load model from file {}", file);
models.put(modelID, new Network(file.getAbsolutePath(), modelID, inputMaxes, inputMins, targetMaxes, targetMins, listInputIndex, listOutputIndex)); models.put(modelID, new Network(file.getAbsolutePath(), modelID, inputMaxes, inputMins, targetMaxes, targetMins));
inputVectors.put(modelID,new ArrayList<>()); inputVectors.put(modelID,new ArrayList<>());
return true; return true;
} }
@Override @Override
public boolean loadModelFromFile(InputStream input, int modelID, List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes, public boolean loadModelFromFile(InputStream input, int modelID, List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes,
List<Integer> targetMins,List<String> listInputIndex, List<String> listOutputIndex) { List<Integer> targetMins) {
logger.debug("Load model from input stream"); logger.debug("Load model from input stream");
models.put(modelID, new Network(input, modelID, inputMaxes, inputMins, targetMaxes, targetMins, listInputIndex, listOutputIndex)); models.put(modelID, new Network(input, modelID, inputMaxes, inputMins, targetMaxes, targetMins));
inputVectors.put(modelID,new ArrayList<>()); inputVectors.put(modelID,new ArrayList<>());
return true; return true;
} }
@Override @Override
public boolean train(int inputCount, int outputCount, int hiddenCount, int hiddenNeuronCount, int modelID, public boolean train(int inputCount, int outputCount, int hiddenCount, int hiddenNeuronCount,
List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes, int modelID, List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes,
List<Integer> targetMins,List<String> listInputIndex, List<String> listOutputIndex) { List<Integer> targetMins) {
// Method for the initial training of algorithms and models. That uses external data set for training. // Method for the initial training of algorithms and models. That uses external data set for training.
double learningrate = 0.07;
double momentum = 0.02;
if (datasets.get(modelID) != null) { if (datasets.get(modelID) != null) {
Dataset set = datasets.get(modelID); Dataset set = datasets.get(modelID);
ReadCSV csv = set.getCsv(); ReadCSV csv = set.getCsv();
Network model = new Network(inputCount, outputCount, hiddenCount, hiddenNeuronCount, modelID, inputMaxes, Network model = new Network(inputCount, outputCount, hiddenCount, hiddenNeuronCount, modelID, inputMaxes,
inputMins, targetMaxes, targetMins, listInputIndex, listOutputIndex); inputMins, targetMaxes, targetMins);
model.setLearningrate(learningrate);
model.setMomentum(momentum);
ArrayList<Double> input = new ArrayList<>(); // double[][] input = new double[rowCount][inputMins.size()];
ArrayList<Double> target = new ArrayList<>(); // double[][] target = new double[rowCount][targetMins.size()];
List<Double> input = new ArrayList<>();
List<Double> target = new ArrayList<>();
int countRows = 0;
logger.debug("read csv");
// LOGGER.log(Level.WARNING, "tcol size: " + set.getTargetColumns().size() + "tcol0: " + set.getTargetColumns().get(0) + "tcol1: " + set.getTargetColumns().get(1) + "tcol2: " + set.getTargetColumns().get(2));
while (csv.next()) { while (csv.next()) {
logger.debug("Train next csv row");
// train one row after another
for (int i = 0; i < csv.getColumnCount(); i++) { for (int i = 0; i < csv.getColumnCount(); i++) {
int col_nr = i + 1; if (set.getTargetColumns().contains(i)) {
if (set.getTargetColumns().contains(col_nr)) {
target.add(csv.getDouble(i)); target.add(csv.getDouble(i));
} else { } else {
input.add(csv.getDouble(i)); input.add(csv.getDouble(i));
...@@ -116,11 +171,29 @@ public class LearnerImpl implements Learner { ...@@ -116,11 +171,29 @@ public class LearnerImpl implements Learner {
model.train(input, target); model.train(input, target);
input.clear(); input.clear();
target.clear(); target.clear();
// train with all rows at same time
/* int tar_nr = 0;
int in_nr = 0;
for (int i = 0; i < csv.getColumnCount(); i++) {
if (set.getTargetColumns().contains(i)) {
target[countRows][tar_nr]= csv.getDouble(i);
tar_nr++;
} else {
input[countRows][in_nr]= csv.getDouble(i);
in_nr++;
}
} }
countRows++; */
}
// model.train(input, target);
models.put(modelID, model); models.put(modelID, model);
inputVectors.put(modelID,new ArrayList<>()); model.saveModel(this.modelFolderPath);
model.saveModel(modelFolderPath);
return true; return true;
} }
...@@ -130,10 +203,10 @@ public class LearnerImpl implements Learner { ...@@ -130,10 +203,10 @@ public class LearnerImpl implements Learner {
@Override @Override
public boolean train(double[][] data, int inputCount, int outputCount, int hiddenCount, int hiddenNeuronCount, int modelID, public boolean train(double[][] data, int inputCount, int outputCount, int hiddenCount, int hiddenNeuronCount, int modelID,
List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes, List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes,
List<Integer> targetMins, List<Integer> targetColumns, List<String> listInputIndex, List<String> listOutputIndex) { List<Integer> targetMins, List<Integer> targetColumns) {
Network model = new Network(inputCount, outputCount, hiddenCount, hiddenNeuronCount, modelID, inputMaxes, Network model = new Network(inputCount, outputCount, hiddenCount, hiddenNeuronCount, modelID, inputMaxes,
inputMins, targetMaxes, targetMins, listInputIndex, listOutputIndex); inputMins, targetMaxes, targetMins);
return reTrainModel(model, data, targetColumns, modelID); return reTrainModel(model, data, targetColumns, modelID);
} }
...@@ -249,12 +322,12 @@ public class LearnerImpl implements Learner { ...@@ -249,12 +322,12 @@ public class LearnerImpl implements Learner {
} }
public double getActivity(){ public double getActivity(){
double[] output_activity_recognition = this.models.get(0).computeResult(this.inputVectors.get(0)); double[] output_activity_recognition = this.models.get(LearnerHelper.ID_ACTIVITY_MODEL).computeResult(this.inputVectors.get(LearnerHelper.ID_ACTIVITY_MODEL));
return output_activity_recognition[0]; return output_activity_recognition[0];
} }
public double[] getPreferencesForCurrentActivity(){ public double[] getPreferencesForCurrentActivity(){
return this.models.get(1).computeResult(this.inputVectors.get(1)); return this.models.get(LearnerHelper.ID_PREFERENCE_MODEL).computeResult(this.inputVectors.get(LearnerHelper.ID_PREFERENCE_MODEL));
} }
//prepare input vector for classify //prepare input vector for classify
...@@ -277,7 +350,7 @@ public class LearnerImpl implements Learner { ...@@ -277,7 +350,7 @@ public class LearnerImpl implements Learner {
int n_models = this.models.size(); int n_models = this.models.size();
for(Item item:changedItems){ for(Item item:changedItems){
for(int i = 0; i< n_models ;i++){ for(int i = 0; i< n_models ;i++){
if(this.models.get(i).itemRelevant(item.getID())) { if(this.models.get(i).isRelevantItem(item.getID())) {
updateInputVector(item, i); updateInputVector(item, i);
} }
} }
...@@ -285,21 +358,28 @@ public class LearnerImpl implements Learner { ...@@ -285,21 +358,28 @@ public class LearnerImpl implements Learner {
} }
public List<String> getTargetItemsIdsPreferenceLearning() { public List<String> getTargetItemsIdsPreferenceLearning() {
return this.models.get(1).getTargetItemsIds(); return this.models.get(LearnerHelper.ID_PREFERENCE_MODEL).getTargetItemsIds();
} }
public List<String> getRelevantItemsIdsPrefenceLearning() { public List<String> getRelevantItemsIdsPrefenceLearning() {
return this.models.get(1).getRelevantItemsIds(); return this.models.get(LearnerHelper.ID_PREFERENCE_MODEL).getRelevantItemsIds();
} }
public List<String> getTargetItemsIdsActivityLearning() { public List<String> getTargetItemsIdsActivityLearning() {
return this.models.get(0).getTargetItemsIds(); return this.models.get(LearnerHelper.ID_ACTIVITY_MODEL).getTargetItemsIds();
} }
public List<String> getRelevantItemsIdsActivityLearning() { public List<String> getRelevantItemsIdsActivityLearning() {
return this.models.get(0).getRelevantItemsIds(); return this.models.get(LearnerHelper.ID_ACTIVITY_MODEL).getRelevantItemsIds();
}
public double[] computeResult(int modelID, List<Double> inputVector) {
Network model = this.models.get(modelID);
return model.computeResult(inputVector);
} }
} }
...@@ -7,36 +7,44 @@ import java.time.Instant; ...@@ -7,36 +7,44 @@ import java.time.Instant;
import java.util.List; import java.util.List;
/** /**
* Adapter for internally held machine learning models. * Adapter for accessing machine learning models that are held outside of the knowledge base.
* Class contains functions that are commonly used by ActivityLearningHandler and
* PreferenceLearningHandler. It accesses a Learner-object to update all input vectors of the
* associated machine-learning models (function: newData) and the openHAB2model-object to
* obtain references to the Item-objects * of the individual sensors/actuators (function: resolve)
* *
* @author rschoene - Initial contribution * @author MoralDav
* @author Bierzynski
*/ */
public abstract class LearningHandler implements MachineLearningEncoder, MachineLearningDecoder { public abstract class LearningHandler implements MachineLearningEncoder, MachineLearningDecoder {
private static final Logger logger = LogManager.getLogger(LearningHandler.class); private static final Logger logger = LogManager.getLogger(LearningHandler.class);
private LearnerImpl Learner; private LearnerImpl Learner;
private InternalMachineLearningModel model; //private InternalMachineLearningModel model;
private OpenHAB2Model openHAB2model; private OpenHAB2Model openHAB2model;
public LearnerImpl getLearner() {
return this.Learner;
}
public LearningHandler setLearner(LearnerImpl learner) { public LearningHandler(LearnerImpl learner, OpenHAB2Model openHAB2model){
this.Learner = learner; this.Learner = learner;
return this; this.openHAB2model = openHAB2model;
} }
public LearnerImpl getLearner() {
return this.Learner;
}
public OpenHAB2Model getOpenHAB2model(){return this.openHAB2model;}
/**
* Function triggers the Learner to update the input vectors of all Networks (i.e.,
* machine-learning models) that it manages with the item values that have changed
*
* @param changedItems A list of items whose state has changed
*/
@Override @Override
public void newData(List<Item> changedItems) { public void newData(List<Item> changedItems) {
//prepare input vector for each model and each item //prepare input vector for each model and each item
this.getLearner().updateLearner(changedItems); this.getLearner().updateLearner(changedItems);
} }
public LearningHandler setModel(InternalMachineLearningModel model) {
this.model = model;
return this;
}
public static Logger getLogger() { public static Logger getLogger() {
return logger; return logger;
...@@ -47,6 +55,13 @@ public abstract class LearningHandler implements MachineLearningEncoder, Machin ...@@ -47,6 +55,13 @@ public abstract class LearningHandler implements MachineLearningEncoder, Machin
// ignored // ignored
} }
/**
* Function allows for accessing the Item-object that is associated in the knowledge base
* to the given itemId.
*
* @param itemId
* @return
*/
public Item resolve(String itemId) { public Item resolve(String itemId) {
java.util.Optional<Item> maybeItem = this.openHAB2model.resolveItem(itemId); java.util.Optional<Item> maybeItem = this.openHAB2model.resolveItem(itemId);
...@@ -74,9 +89,9 @@ public abstract class LearningHandler implements MachineLearningEncoder, Machin ...@@ -74,9 +89,9 @@ public abstract class LearningHandler implements MachineLearningEncoder, Machin
@Override @Override
public abstract MachineLearningResult classify(); public abstract MachineLearningResult classify();
public ItemPreference getPreferenceItem(Item item, double[] output_preferenceLearning){ public ItemPreference wrapIntoPreferenceItem(Item item, double[] output_preferenceLearning, int modelId){
ItemPreference preference; ItemPreference preference;
int index = this.Learner.getOutputIndex(item.getID(),1); int index = this.Learner.getOutputIndex(item.getID(),modelId);
if(item.getClass().getName()=="ColorItem"){ if(item.getClass().getName()=="ColorItem"){
preference = new ItemPreferenceColor(item, TupleHSB.of( (int)Math.round(output_preferenceLearning[index]), (int)Math.round(output_preferenceLearning[index+1]), (int)Math.round(output_preferenceLearning[index+2]))); preference = new ItemPreferenceColor(item, TupleHSB.of( (int)Math.round(output_preferenceLearning[index]), (int)Math.round(output_preferenceLearning[index+1]), (int)Math.round(output_preferenceLearning[index+2])));
}else{ }else{
......
...@@ -2,9 +2,9 @@ package de.tudresden.inf.st.eraser.feedbackloop.learner; ...@@ -2,9 +2,9 @@ package de.tudresden.inf.st.eraser.feedbackloop.learner;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -18,14 +18,13 @@ import org.encog.neural.networks.training.propagation.back.Backpropagation; ...@@ -18,14 +18,13 @@ import org.encog.neural.networks.training.propagation.back.Backpropagation;
import org.encog.persist.EncogDirectoryPersistence; import org.encog.persist.EncogDirectoryPersistence;
import org.encog.util.arrayutil.NormalizationAction; import org.encog.util.arrayutil.NormalizationAction;
import org.encog.util.arrayutil.NormalizedField; import org.encog.util.arrayutil.NormalizedField;
import java.util.HashMap;
import java.util.Map;
import org.encog.util.simple.EncogUtility; import org.encog.util.simple.EncogUtility;
/** /**
* Network class serves as interface to encog BasicNetwork and holdsfunctions for handling the BasicNetwork (training, input, output and inference) * Network class serves as interface to encog BasicNetwork and holdsfunctions for handling the BasicNetwork (training, input, output and inference)
* *
* @author Bierzynski - initial contribution * @author Bierzynski - initial contribution
* @author MoralDav
*/ */
public class Network { public class Network {
private static final Logger logger = LogManager.getLogger(Network.class); private static final Logger logger = LogManager.getLogger(Network.class);
...@@ -33,8 +32,17 @@ public class Network { ...@@ -33,8 +32,17 @@ public class Network {
private int modelID; private int modelID;
private ArrayList<NormalizedField> normalizersIn; private ArrayList<NormalizedField> normalizersIn;
private ArrayList<NormalizedField> normalizersTar; private ArrayList<NormalizedField> normalizersTar;
// maps item-ids to the index positions at which the values of those items
// are expected to be placed in the input-vector of this model (see LearnerImpl.InputVectors)
// TODO: use LearnerImpl.InitModelsVectors to update indexInputvector/indexOutputvector
private Map<String, Integer> indexInputvector = new HashMap<>(); private Map<String, Integer> indexInputvector = new HashMap<>();
// maps item-ids to the index positions at which the values of those items will be placed within
// the output of this model (see e.g.: PreferenceLearningHandler.classify, Network.computeResult)
private Map<String, Integer> indexOutputvector = new HashMap<>(); private Map<String, Integer> indexOutputvector = new HashMap<>();
private Double learningrate=3.5;
private Double momentum=0.3;
/** /**
* Constructor for when the neural network is created from data. * Constructor for when the neural network is created from data.
...@@ -48,12 +56,14 @@ public class Network { ...@@ -48,12 +56,14 @@ public class Network {
* @param inputMins list that contains min values of all input columns (sensors) e.g. light intensity 0 * @param inputMins list that contains min values of all input columns (sensors) e.g. light intensity 0
* @param targetMaxes list that contains max values of all output columns (results) e.g. brightness 100 for preference learning * @param targetMaxes list that contains max values of all output columns (results) e.g. brightness 100 for preference learning
* @param targetMins list that contains min values of all output columns (results) e.g. brightness 0 for preference learning * @param targetMins list that contains min values of all output columns (results) e.g. brightness 0 for preference learning
* @param listInputIndex list that containg the item's Ids to initialize the map indexInputvector
* @param listOutputIndex list that containg the item's Ids to initialize the map indexOutpurvector
*/ */
public Network(int inputCount, int outputCount, int hiddenCount, int hiddenNeuronCount, int modelID, public Network(int inputCount, int outputCount, int hiddenCount, int hiddenNeuronCount, int modelID,
List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes, List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes,
List<Integer> targetMins,List<String> listInputIndex,List<String> listOutputIndex) { List<Integer> targetMins) {
learningrate = 3.5;
momentum = 0.3;
normalizersIn = new ArrayList<>(); normalizersIn = new ArrayList<>();
normalizersTar = new ArrayList<>(); normalizersTar = new ArrayList<>();
...@@ -73,17 +83,15 @@ public class Network { ...@@ -73,17 +83,15 @@ public class Network {
addNormalizer(inputMaxes, inputMins, normalizersIn); addNormalizer(inputMaxes, inputMins, normalizersIn);
addNormalizer(targetMaxes, targetMins, normalizersTar); addNormalizer(targetMaxes, targetMins, normalizersTar);
initializeMaps(listInputIndex,listOutputIndex);
}
private void initializeMaps(List<String> listInputIndex, List<String> listOutputIndex){
for(int i = 0; i < listInputIndex.size();i++){
this.indexInputvector.put(listInputIndex.get(i),i);
} }
for(int i = 0; i < listOutputIndex.size();i++){
this.indexOutputvector.put(listOutputIndex.get(i),i); public void setIndexInputvector(Map<String, Integer> indexInputvector) {
this.indexInputvector = indexInputvector;
} }
public void setIndexOutputvector(Map<String, Integer> indexOutputvector) {
this.indexOutputvector = indexOutputvector;
} }
public List<String> getTargetItemsIds(){ public List<String> getTargetItemsIds(){
...@@ -121,12 +129,22 @@ public class Network { ...@@ -121,12 +129,22 @@ public class Network {
* @param inputMins list that contains min values of all input columns (sensors) e.g. light intensity 0 * @param inputMins list that contains min values of all input columns (sensors) e.g. light intensity 0
* @param targetMaxes list that contains max values of all output columns (results) e.g. brightness 100 for preference learning * @param targetMaxes list that contains max values of all output columns (results) e.g. brightness 100 for preference learning
* @param targetMins list that contains min values of all output columns (results) e.g. brightness 0 for preference learning * @param targetMins list that contains min values of all output columns (results) e.g. brightness 0 for preference learning
* @param listInputIndex list that containg the item's Ids to initialize the map indexInputvector
* @param listOutputIndex list that containg the item's Ids to initialize the map indexOutpurvector
*/ */
public Network(String path, int modelID, List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes, public Network(String path, int modelID, List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes,
List<Integer> targetMins, List<String> listInputIndex,List<String> listOutputIndex) { List<Integer> targetMins) {
this(() -> (BasicNetwork) EncogDirectoryPersistence.loadObject(new File(path, "NN_" + modelID)), modelID, inputMaxes, inputMins, targetMaxes, targetMins,listInputIndex,listOutputIndex); learningrate = 3.5;
momentum = 0.3;
this.modelID = modelID;
normalizersIn = new ArrayList<>();
normalizersTar = new ArrayList<>();
network = (BasicNetwork) EncogDirectoryPersistence.loadObject(new File(path + "NN_" + modelID));
addNormalizer(inputMaxes, inputMins, normalizersIn);
addNormalizer(targetMaxes, targetMins, normalizersTar);
} }
/** /**
...@@ -139,16 +157,16 @@ public class Network { ...@@ -139,16 +157,16 @@ public class Network {
* @param inputMins list that contains min values of all input columns (sensors) e.g. light intensity 0 * @param inputMins list that contains min values of all input columns (sensors) e.g. light intensity 0
* @param targetMaxes list that contains max values of all output columns (results) e.g. brightness 100 for preference learning * @param targetMaxes list that contains max values of all output columns (results) e.g. brightness 100 for preference learning
* @param targetMins list that contains min values of all output columns (results) e.g. brightness 0 for preference learning * @param targetMins list that contains min values of all output columns (results) e.g. brightness 0 for preference learning
* @param listInputIndex list that containg the item's Ids to initialize the map indexInputvector
* @param listOutputIndex list that containg the item's Ids to initialize the map indexOutpurvector
*/ */
public Network(InputStream input, int modelID, List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes, public Network(InputStream input, int modelID, List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes,
List<Integer> targetMins, List<String> listInputIndex,List<String> listOutputIndex) { List<Integer> targetMins) {
this(() -> (BasicNetwork) EncogDirectoryPersistence.loadObject(input), modelID, inputMaxes, inputMins, targetMaxes, targetMins, listInputIndex,listOutputIndex); this(() -> (BasicNetwork) EncogDirectoryPersistence.loadObject(input), modelID, inputMaxes, inputMins, targetMaxes, targetMins);
} }
private Network(LoadEncogModel loader, int modelID, List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes, private Network(LoadEncogModel loader, int modelID, List<Integer> inputMaxes, List<Integer> inputMins, List<Integer> targetMaxes,
List<Integer> targetMins, List<String> listInputIndex,List<String> listOutputIndex) { List<Integer> targetMins) {
learningrate = 3.5;
momentum = 0.3;
this.modelID = modelID; this.modelID = modelID;
normalizersIn = new ArrayList<>(); normalizersIn = new ArrayList<>();
...@@ -158,7 +176,7 @@ public class Network { ...@@ -158,7 +176,7 @@ public class Network {
addNormalizer(inputMaxes, inputMins, normalizersIn); addNormalizer(inputMaxes, inputMins, normalizersIn);
addNormalizer(targetMaxes, targetMins, normalizersTar); addNormalizer(targetMaxes, targetMins, normalizersTar);
initializeMaps(listInputIndex,listOutputIndex);
} }
@FunctionalInterface @FunctionalInterface
...@@ -204,7 +222,36 @@ public class Network { ...@@ -204,7 +222,36 @@ public class Network {
train.finishTraining(); train.finishTraining();
} }
// method to train with all rows
public void train(double[][] input, double[][] target) {
double[][] INPUT_ = new double[input.length][input[0].length];
double[][] IDEAL = new double[target.length][target[0].length];
for(int i = 0; i<input.length; i++) {
for (int j = 0; j < input[0].length; j++) {
INPUT_[i][j] = normalizersIn.get(j).normalize(input[i][j]);
}
}
for(int a = 0; a<target.length; a++) {
for (int b = 0; b < target[0].length; b++) {
IDEAL[a][b] = normalizersTar.get(b).normalize(target[a][b]);
}
}
MLDataSet trainingSet = new BasicMLDataSet(INPUT_, IDEAL);
MLTrain train = new Backpropagation(network, trainingSet, learningrate, momentum);
//int epoch = 1;
do {
train.iteration();
// LOGGER.log(Level.WARNING, "Epoch #" + epoch + " Error:" + train.getError());
// epoch++;
} while (train.getError() > 0.005);
train.finishTraining();
}
/** /**
* Method that uses the {@link BasicNetwork} to predict/classify/.. something based on an input. * Method that uses the {@link BasicNetwork} to predict/classify/.. something based on an input.
* *
...@@ -239,7 +286,15 @@ public class Network { ...@@ -239,7 +286,15 @@ public class Network {
return normalizersTar; return normalizersTar;
} }
public boolean itemRelevant(String itemId){ public boolean isRelevantItem(String itemId){
return this.indexInputvector.containsKey(itemId); return this.indexInputvector.containsKey(itemId);
} }
public void setMomentum(Double momentum) {
this.momentum = momentum;
}
public void setLearningrate(Double learningrate) {
this.learningrate = learningrate;
}
} }
...@@ -7,18 +7,18 @@ import java.util.List; ...@@ -7,18 +7,18 @@ import java.util.List;
/** /**
* Adapter for internally held machine learning models. * Adapter for internally held machine learning models.
* *
* @author rschoene - Initial contribution * @author MoralDav
* @author Bierzynski
* @
*/ */
public class PreferenceLearningHandler extends ActivityLearningHandler implements MachineLearningEncoder, MachineLearningDecoder { public class PreferenceLearningHandler extends ActivityLearningHandler implements MachineLearningEncoder, MachineLearningDecoder {
public PreferenceLearningHandler setLearner(LearnerImpl learner) {
return (PreferenceLearningHandler) super.setLearner(learner);
}
public PreferenceLearningHandler setModel(InternalMachineLearningModel model) { public PreferenceLearningHandler(LearnerImpl learner, OpenHAB2Model openHAB2model){
return (PreferenceLearningHandler) super.setModel(model); super(learner,openHAB2model);
} }
@Override @Override
public List<Item> getTargets() { public List<Item> getTargets() {
List<Item> targets = new ArrayList<Item>(); List<Item> targets = new ArrayList<Item>();
...@@ -29,6 +29,15 @@ public class PreferenceLearningHandler extends ActivityLearningHandler implement ...@@ -29,6 +29,15 @@ public class PreferenceLearningHandler extends ActivityLearningHandler implement
return targets ; return targets ;
} }
/**
* Function accesses the meta-information (text file: at which position within the input vector
* are the values for a specific item id expected to be delivered?) of the preference learning
* Network-object (managed by the Learner-object) to determine those Items whose current values
* are required by the preference learning machine-learning model for its decision making.
*
* @return
*/
@Override @Override
public List<Item> getRelevantItems() { public List<Item> getRelevantItems() {
List<Item> relevantItems = new ArrayList<Item>(); List<Item> relevantItems = new ArrayList<Item>();
...@@ -44,12 +53,22 @@ public class PreferenceLearningHandler extends ActivityLearningHandler implement ...@@ -44,12 +53,22 @@ public class PreferenceLearningHandler extends ActivityLearningHandler implement
getLogger().debug("Ignored training trigger."); getLogger().debug("Ignored training trigger.");
} }
//classify using the input vector given by newData /**
* Function triggers the Learner-object to estimate the currently preferred lighting configuration
* using the sensor data that are found in the preference learning input vector (which is kept
* up-to-date by the function LearningHandler.newData). To further update this input vector the
* currently performed activity is estimated first and written into the preference learning input
* vector (this.getLearner().updateLearner(changedItems)).
*
* @return
*/
@Override @Override
public MachineLearningResult classify() { public MachineLearningResult classify() {
//Using activity recognition to get current activity //Using activity recognition to get current activity
MachineLearningResult resultActivityRecognition = super.classify(); MachineLearningResult resultActivityRecognition = super.classify();
ActivityItem current_activity = (ActivityItem) resultActivityRecognition.getPreferences(); List<ItemPreference> preferencesList = resultActivityRecognition.getPreferences();
Item item = preferencesList.get(LearnerHelper.IDX_ACTIVITY_ITEM_TARGET).getItem();
ActivityItem current_activity = (ActivityItem) item ;
//update Learner's state //update Learner's state
List<Item> changedItems = new ArrayList<>(); List<Item> changedItems = new ArrayList<>();
...@@ -64,7 +83,7 @@ public class PreferenceLearningHandler extends ActivityLearningHandler implement ...@@ -64,7 +83,7 @@ public class PreferenceLearningHandler extends ActivityLearningHandler implement
List<ItemPreference> preferences = new ArrayList<ItemPreference>(); List<ItemPreference> preferences = new ArrayList<ItemPreference>();
List<Item> targets = getTargets();//get items that this model is supposed to change List<Item> targets = getTargets();//get items that this model is supposed to change
for (Item i:targets){ for (Item i:targets){
ItemPreference preference = getPreferenceItem(i,output_preferenceLearning); ItemPreference preference = wrapIntoPreferenceItem(i,output_preferenceLearning, LearnerHelper.ID_PREFERENCE_MODEL);
preferences.add(preference);//add preference to the preferences array preferences.add(preference);//add preference to the preferences array
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment