From c1906082df2246f29ece704fc1aaee0d263d6637 Mon Sep 17 00:00:00 2001 From: Size43 Date: Tue, 19 May 2015 14:07:39 +0200 Subject: neurons package --- .../main/java/org/rssin/neurons/FeedSorter.java | 95 +++++++++++++++++++ .../java/org/rssin/neurons/MultiNeuralNetwork.java | 38 ++++++++ .../neurons/MultiNeuralNetworkPrediction.java | 30 ++++++ .../main/java/org/rssin/neurons/NeuralNetwork.java | 105 +++++++++++++++++++++ .../org/rssin/neurons/NeuralNetworkPrediction.java | 34 +++++++ app/src/main/java/org/rssin/neurons/Neuron.java | 40 ++++++++ .../org/rssin/neurons/PredictionInterface.java | 9 ++ 7 files changed, 351 insertions(+) create mode 100755 app/src/main/java/org/rssin/neurons/FeedSorter.java create mode 100755 app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java create mode 100755 app/src/main/java/org/rssin/neurons/MultiNeuralNetworkPrediction.java create mode 100755 app/src/main/java/org/rssin/neurons/NeuralNetwork.java create mode 100755 app/src/main/java/org/rssin/neurons/NeuralNetworkPrediction.java create mode 100755 app/src/main/java/org/rssin/neurons/Neuron.java create mode 100755 app/src/main/java/org/rssin/neurons/PredictionInterface.java (limited to 'app') diff --git a/app/src/main/java/org/rssin/neurons/FeedSorter.java b/app/src/main/java/org/rssin/neurons/FeedSorter.java new file mode 100755 index 0000000..fee6f4d --- /dev/null +++ b/app/src/main/java/org/rssin/neurons/FeedSorter.java @@ -0,0 +1,95 @@ +package org.rssin.neurons; + +import java.util.Calendar; +import java.util.TimeZone; + +/** + * Created by Jos on 14-5-2015. + */ +public class FeedSorter { + private MultiNeuralNetwork nn = new MultiNeuralNetwork(25, 50); + + private int[] isNthMonthInput = new int[12]; + private int[] isNthWeekDayInput = new int[7]; + private int isMorning, isAfternoon, isEvening, isNight; + private Hashtable categoryInputs = new Hashtable(); + private Hashtable wordInputs = new Hashtable(); + private Hashtable feedSourceInputs = new Hashtable(); + + public FeedSorter() { + //TODO: Load Neural Network + createNewNetwork(); + } + + private void createNewNetwork() { + for(int i = 0; i < 12; i++) + { + isNthMonthInput[i] = nn.addInput(); + } + + for(int i = 0; i < 7; i++) + { + isNthWeekDayInput[i] = nn.addInput(); + } + + isMorning = nn.addInput(); + isAfternoon = nn.addInput(); + isEvening = nn.addInput(); + isNight = nn.addInput(); + } + + private PredictionInterface getPrediction(FeedItem item) { + double[] inputs = new double[nn.getInputCount()]; + + //Initialize all inputs to -1 / false + for(int i = 0; i < inputs.length; i++) + { + inputs[i] = -1; + } + + //Set month + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + for(int i = 0; i < isNthMonthInput.length; i++) + { + if(cal.get(Calendar.MONTH) - cal.getMinimum(Calendar.MONTH) == i) + { + inputs[isNthMonthInput[i]] = 1; + } + } + + //Set weekday + for(int i = 0; i < isNthWeekDayInput.length; i++) + { + if(cal.get(Calendar.DAY_OF_WEEK) - cal.getMinimum(Calendar.DAY_OF_WEEK) == i) + { + inputs[isNthMonthInput[i]] = 1; + } + } + + //Set day + int hourOfDay = cal.get(Calendar.HOUR_OF_DAY); + if(hourOfDay > 6 && hourOfDay < 12) + { + inputs[isMorning] = 1; + }else if(hourOfDay >= 12 && hourOfDay <= 6) + { + inputs[isAfternoon] = 1; + }else if(hourOfDay >= 6 && hourOfDay < 23) + { + inputs[isEvening] = 1; + }else if(hourOfDay >= 23 || hourOfDay <= 6) + { + inputs[isNight] = 1; + } + + //TODO: source, category, title, text, etc of FeedItems + + return nn.computeOutput(inputs); + } + + public List sortItems(List items) { + // Sort list based on something like date + nn.computeOutput() * DAY. + throw new NotImplementedException(); + return items; + } +} diff --git a/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java b/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java new file mode 100755 index 0000000..492f67c --- /dev/null +++ b/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java @@ -0,0 +1,38 @@ +package org.rssin.neurons; + +/** + * Created by Jos on 14-5-2015. + */ +public class MultiNeuralNetwork { + private NeuralNetwork[] networks; + + public MultiNeuralNetwork(int numNetworks, int numHiddenNodes) { + networks = new NeuralNetwork[numNetworks]; + for (int i = 0; i < networks.length; i++) { + networks[i] = new NeuralNetwork(numHiddenNodes); + } + } + + public int addInput() { + int id = 0; + for (NeuralNetwork network : networks) { + id = network.addInput(); + } + + return id; + } + + public PredictionInterface computeOutput(double[] inputs) { + PredictionInterface[] predictions = new PredictionInterface[networks.length]; + for(int i = 0; i < predictions.length; i++) + { + predictions[i] = networks[i].computeOutput(inputs); + } + + return new MultiNeuralNetworkPrediction(predictions); + } + + public int getInputCount() { + return networks[0].getInputCount(); + } +} diff --git a/app/src/main/java/org/rssin/neurons/MultiNeuralNetworkPrediction.java b/app/src/main/java/org/rssin/neurons/MultiNeuralNetworkPrediction.java new file mode 100755 index 0000000..06164d0 --- /dev/null +++ b/app/src/main/java/org/rssin/neurons/MultiNeuralNetworkPrediction.java @@ -0,0 +1,30 @@ +package org.rssin.neurons; + +/** + * Created by Jos on 14-5-2015. + */ +public class MultiNeuralNetworkPrediction implements PredictionInterface { + private PredictionInterface[] predictions; + MultiNeuralNetworkPrediction(PredictionInterface[] predictions) + { + this.predictions = predictions; + } + + public double getOutput() + { + double average = 0; + for (PredictionInterface prediction : predictions) { + average += prediction.getOutput(); + } + + return average / (double) predictions.length; + } + + public void learn(double expectedOutput) + { + for(PredictionInterface prediction : predictions) + { + prediction.learn(expectedOutput); + } + } +} diff --git a/app/src/main/java/org/rssin/neurons/NeuralNetwork.java b/app/src/main/java/org/rssin/neurons/NeuralNetwork.java new file mode 100755 index 0000000..d761e35 --- /dev/null +++ b/app/src/main/java/org/rssin/neurons/NeuralNetwork.java @@ -0,0 +1,105 @@ +package org.rssin.neurons; + +/** + * Created by Jos on 14-5-2015. + */ +public class NeuralNetwork { + private Neuron[] hiddenNodes; + private Neuron outputNode; + + public NeuralNetwork(int numHiddenNodes) { + if(numHiddenNodes < 1) + { + throw new IllegalArgumentException("numHiddenNodes must be > 0"); + } + + hiddenNodes = new Neuron[numHiddenNodes]; + + for (int i = 0; i < hiddenNodes.length; i++) { + hiddenNodes[i] = new Neuron(); + } + + outputNode = new Neuron(numHiddenNodes + 1); + } + + public int addInput() { + int result = 0; + for (int i = 0; i < hiddenNodes.length; i++) { + result = hiddenNodes[i].AddWeight(); + } + + return result; + } + + public PredictionInterface computeOutput(double[] inputs) { + double[] intermediateValues = new double[outputNode.getWeightCount()]; + + for (int neuronNum = 0; neuronNum < hiddenNodes.length; neuronNum++) { + Neuron n = hiddenNodes[neuronNum]; + + double neuronOutput = 0; + for (int i = 0; i < n.getWeightCount(); i++) { + neuronOutput += n.getWeight(i) * inputs[i]; + } + + intermediateValues[neuronNum] = HyperTan(neuronOutput); + } + + double result = 0; + for (int neuronNum = 0; neuronNum < intermediateValues.length; neuronNum++) { + result += intermediateValues[neuronNum] * outputNode.getWeight(neuronNum); + } + + return new NeuralNetworkPrediction(this, inputs, intermediateValues, HyperTan(result)); + } + + void learn(NeuralNetworkPrediction p, double expectedOutput) { + double actualOutput = p.getOutput(); + double[] intermediateValues = p.getIntermediateValues(); + double[] inputs = p.getInputs(); + + double[] hiddenGradients = new double[hiddenNodes.length]; + + //Calculate output gradients + double outputDerivative = (1 - actualOutput) * (1 + actualOutput); + + //Derivative of HyperTan function + double outputGradient = outputDerivative * (expectedOutput - actualOutput); + + //Calulate hidden gradients + for (int i = 0; i < hiddenGradients.length; i++) { + //Derivative of HyperTan function + double hiddenDerivative = (1 - intermediateValues[i]) * (1 + intermediateValues[i]); + hiddenGradients[i] = hiddenDerivative * outputGradient * outputNode.getWeight(i); + } + + //Update input => hidden weights. + final double learningRate = 0.3; + for (int neuronNum = 0; neuronNum < hiddenNodes.length; neuronNum++) { + Neuron n = hiddenNodes[neuronNum]; + + for (int i = 0; i < n.getWeightCount(); i++) { + //Calulate & apply delta + double delta = learningRate * hiddenGradients[neuronNum] * inputs[i]; + n.adjustWeight(i, delta); + } + } + + //Update hidden => output weights. + for (int i = 0; i < outputNode.getWeightCount(); i++) { + //Calulate & apply delta + double delta = learningRate * outputGradient * intermediateValues[i]; + outputNode.adjustWeight(i, delta); + } + } + + private static double HyperTan(double x) { + if (x < -10.0) return -1.0; + else if (x > 10.0) return 1.0; + else return Math.tanh(x); + } + + public int getInputCount() { + return hiddenNodes[0].getWeightCount(); + } +} diff --git a/app/src/main/java/org/rssin/neurons/NeuralNetworkPrediction.java b/app/src/main/java/org/rssin/neurons/NeuralNetworkPrediction.java new file mode 100755 index 0000000..cd34c8e --- /dev/null +++ b/app/src/main/java/org/rssin/neurons/NeuralNetworkPrediction.java @@ -0,0 +1,34 @@ +package org.rssin.neurons; + +/** + * Created by Jos on 14-5-2015. + */ +public class NeuralNetworkPrediction implements PredictionInterface { + private double[] inputs; + private double[] intermediateValues; + private double output; + private NeuralNetwork nn; + + NeuralNetworkPrediction(NeuralNetwork nn, double[] inputs, double[] intermediateValues, double output) { + this.inputs = inputs; + this.intermediateValues = intermediateValues; + this.output = output; + this.nn = nn; + } + + double[] getInputs() { + return inputs; + } + + double[] getIntermediateValues() { + return intermediateValues; + } + + public double getOutput() { + return output; + } + + public void learn(double expectedOutput) { + nn.learn(this, expectedOutput); + } +} diff --git a/app/src/main/java/org/rssin/neurons/Neuron.java b/app/src/main/java/org/rssin/neurons/Neuron.java new file mode 100755 index 0000000..5df9d47 --- /dev/null +++ b/app/src/main/java/org/rssin/neurons/Neuron.java @@ -0,0 +1,40 @@ +package org.rssin.neurons; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * Created by Jos on 14-5-2015. + */ +class Neuron { + private static Random r = new Random(); + + private List weights = new ArrayList(); + + public Neuron() { + } + + public Neuron(int numWeights) { + for (int i = 0; i < numWeights; i++) { + addWeight(); + } + } + + public int addWeight() { + weights.add(r.nextDouble() * 2 - 1); + return weights.size() - 1; + } + + public double getWeight(int i) { + return weights.get(i); + } + + public void adjustWeight(int i, double delta) { + weights.set(i, weights.get(i) + delta); + } + + public int getWeightCount() { + return weights.size(); + } +} diff --git a/app/src/main/java/org/rssin/neurons/PredictionInterface.java b/app/src/main/java/org/rssin/neurons/PredictionInterface.java new file mode 100755 index 0000000..d2c04b9 --- /dev/null +++ b/app/src/main/java/org/rssin/neurons/PredictionInterface.java @@ -0,0 +1,9 @@ +package org.rssin.neurons; + +/** + * Created by Jos on 14-5-2015. + */ +public interface PredictionInterface { + public double getOutput(); + public void learn(double expectedOutput); +} -- cgit v1.2.3