Simple Time Series Pattern Recognition Source Code

There is a post about the following source code in this blog, here ... 



SimpleTimeSeries class

package com.sleptons.common; public class SimpleTimeSeries { /** * these are the maximum raw values you may send for time and value of a * time series. a maxRawValue of 100,000 means don't you have time series * value more than 100,000 if you have, we set it to 100,000 a maxRawTime of * 1339 for a period means your period has data samples from 0 to 1339 or * 1440 sample data. so if you consider the period as a day, then 1440 * sample per day means one sample per minute. */ private double maxRawValue = 100000; private int maxRawTime = 1439; /** * these are the maximum model values for you need your model use to build * the network. a maxModelValue of 9 for time series values means the model * maps the maxRawValue to 9, in another words it divides the y axis to 10 * unit. a maximum value of 23 means your model time axis resolution is * hour. note that you don't need a high resolution for both time and value * axes. */ private int maxModelValue = 9; private int maxMoldeTime = 23; /** * since the model is simple we keep the network's edge scores in a two * dimensional array. */ private double[][] scores = null; /** * setMaxRawValue sets the maximum raw value of the time series * * @param maxRawValue * is the model's maximum raw value of the time series * @return the object itself */ public SimpleTimeSeries setMaxRawValue(double maxRawValue) { this.maxRawValue = maxRawValue; return this; } /** * sets the maximum raw value of the time series value for the model * * @param maxRawTime * is the model's maximum raw value of the time * @return the object itself */ public SimpleTimeSeries setMaxRawTime(int maxRawTime) { this.maxRawTime = maxRawTime; return this; } /** * sets the maximum value of the time series value for the model * * @param maxModelValue * is the model's maximum value of the time series * @return the object itself */ public SimpleTimeSeries setMaxModelValue(int maxModelValue) { this.maxModelValue = maxModelValue; return this; } /** * sets the maximum value of time for the model * * @param maxMoldeTime * is the model's maximum value of the time * @return the object itself */ public SimpleTimeSeries setMaxMoldeTimePoints(int maxMoldeTime) { this.maxMoldeTime = maxMoldeTime; return this; } /** * trains the network by increasing the score of the given point by one * * @param rawTimePoint * is the time index in period * @param rawValue * is the value of the time series at the given time * @return the object itself */ public SimpleTimeSeries train(int rawTimePoint, double rawValue) { if (this.scores == null) { initNetwork(); } int modelValue = getModeValue(rawValue); int modelTime = getModelTime(rawTimePoint); this.scores[modelTime][modelValue] += 1; return this; } /** * trains the network form the given complete period of sample data, if you * send wrong number of sample data it doesn't train the network * * @param rawValuesOfAPeriod * is the an array of doubles for whole period data * @return the object itself */ public SimpleTimeSeries train(double[] rawValuesOfAPeriod) { if (rawValuesOfAPeriod.length == (this.maxMoldeTime + 1)) { for (int i = 0; i < rawValuesOfAPeriod.length; i++) { this.train(i, rawValuesOfAPeriod[i]); } } return this; } /** * returns the probability of having the given point in the stored network * * @param rawTime * is the raw time index in period * @param rawValue * is the raw value of the time series at the given time * @return the probability of having the point in network */ public double getProbability(int rawTime, double rawValue) { if (this.scores == null || rawTime < 0 || rawValue < 0) { return 0; } int modelValue = getModeValue(rawValue); int modelTime = getModelTime(rawTime); double p = 0; int sum = 0; for (int i = 0; i < this.maxModelValue; i++) { sum += this.scores[modelTime][i]; } if (sum != 0) { p = this.scores[modelTime][modelValue] / sum; } return p; } /** * gets the probability of having the given point in the stored network * * @param modelTime * is the model time index in period * @param modelValue * is the model value of the time series at the given time * @return the probability of having the point in network */ private double getModelProbability(int modelTime, int modelValue) { if (this.scores == null || modelTime < 0 || modelTime > this.maxMoldeTime || modelValue < 0 || modelValue > this.maxModelValue) { return 0; } double p = 0; int sum = 0; for (int i = 0; i < this.maxModelValue; i++) { sum += this.scores[modelTime][i]; } if (sum != 0) { p = this.scores[modelTime][modelValue] / sum; } return p; } /** * returns all possible model points for the given raw time * * @param rawTime * is the raw time index in period * @return the possible model values as an array */ public ModelPoint[] getAllPossibleValues(int rawTime) { int modelTime = getModelTime(rawTime); int count = 0; for (int i = 0; i < this.maxModelValue; i++) { if (this.scores[modelTime][i] > 0) { count += 1; } } ModelPoint[] possibleValues = null; if (count > 0) { possibleValues = new ModelPoint[count]; count = 0; for (int i = 0; i < this.maxModelValue; i++) { if (this.scores[modelTime][i] > 0) { possibleValues[count] = new ModelPoint(); possibleValues[count].time = modelTime; possibleValues[count].value = i; possibleValues[count].probability = this.getModelProbability(modelTime, i); count += 1; } } } return possibleValues; } /** * initialize the network and sets all scores to zero * * @param rawValue * is the value of the time series * @return the model value index */ private void initNetwork() { this.scores = new double[this.maxMoldeTime + 1][this.maxModelValue + 1]; for (int i = 0; i < this.maxMoldeTime + 1; i++) { for (int j = 0; j < this.maxModelValue; j++) { this.scores[i][j] = 0; } } } /** * converts the given raw value to the model value to put it in network * * @param rawValue * is the value of the time series * @return the model value index */ private int getModeValue(double rawValue) { if (rawValue > this.maxRawValue) { rawValue = this.maxRawValue; } if (rawValue < 0) { rawValue = 0; } return (int) (rawValue * (this.maxModelValue) / this.maxRawValue); } /** * converts the given raw time to model time to put it in network * * @param rawTimePoint * is the time index in period * @return the model time index */ private int getModelTime(int rawTime) { rawTime = rawTime % this.maxRawTime; return (rawTime * this.maxMoldeTime) / this.maxRawTime; } /** * a class to hold a model point time, value and probability * */ public class ModelPoint { int time; int value; double probability; public String toString() { return "[ time:" + this.time + " , value:" + this.value + " , probability: " + this.probability + " ]"; } } }
Test class and main() function

package com.sleptons.common; import com.sleptons.common.SimpleTimeSeries.ModelPoint; public class Test { // simply set sampleCountPerHour to the number of the samples you want in an // hour, defiantly not more than 60. if you set it to 60 the maxRawTime will // be 1439 or 1440 sample per day. you can manually set maxRawTime to any // value, there is no need to consider it as a day. private final static int sampleCountPerHour = 12; private final static int maxRawTime = 24 * sampleCountPerHour - 1; // it should be the maximum value your time series may take private final static double maxRawValue = 200; private SimpleTimeSeries simpleTimeSeries = new SimpleTimeSeries(); // this is just a function that generates data for training the network, you // can consider it as your time series function. it is a simple sinusoidal // function, the first parameter is the raw time index and the second one is // for making some modification the out put of the function. private double myTimeSeriesFunction(int rawTime, int timeShift) { return 100 + 80 * Math.sin(2 * Math.PI * (rawTime + timeShift) / Test.maxRawTime); } void testPoint(int testTime, double testValue) { System.out.print("time: " + testTime + " , value: " + testValue + " => "); System.out.println("probability: " + simpleTimeSeries.getProbability(testTime, testValue)); } public static void main(String[] args) { Test test = new Test(); test.simpleTimeSeries.setMaxRawTime(Test.maxRawTime).setMaxRawValue(Test.maxRawValue); // train the first period for (int t = 0; t < Test.maxRawTime + 1; t++) { test.simpleTimeSeries.train(t, test.myTimeSeriesFunction(t, 0)); } // train the second period for (int t = 0; t < Test.maxRawTime + 1; t++) { test.simpleTimeSeries.train(t, test.myTimeSeriesFunction(t, 5)); } // train the third period for (int t = 0; t < Test.maxRawTime + 1; t++) { test.simpleTimeSeries.train(t, test.myTimeSeriesFunction(t, -5)); } // matched points with the stored network test.testPoint(20, test.myTimeSeriesFunction(20, 0)); test.testPoint(20, test.myTimeSeriesFunction(20, 3)); test.testPoint(20, test.myTimeSeriesFunction(20, 5)); test.testPoint(20, test.myTimeSeriesFunction(20, 0) + 10); // not matched points with the stored network test.testPoint(20, 0); test.testPoint(20, test.myTimeSeriesFunction(20, 30)); test.testPoint(20, test.myTimeSeriesFunction(20, 0) * 2); ModelPoint[] modelPointes = test.simpleTimeSeries.getAllPossibleValues(20); for (ModelPoint mp : modelPointes) { System.out.println(mp.toString()); } } }