An easy way to do this would be to use the Accord ID3 decision tree.
The trick is to work out which materials to use - you can't just train on X - the tree won't learn anything about future X values ββfrom this - however, you can build some functions derived from X (or previous Y values) that will useful.
Usually for such tasks, you make each prediction based on the characteristics obtained from the previous values ββof Y (the predicted thing), and not X. However, it is assumed that you can observe Y sequentially between each prediction (then you cannot predict for any arbitary X), therefore I will stick to the question presented.
I decided to build the Accord ID3 decision tree to solve this problem below. I used several different x % n values ββas functions - hoping the tree could solve the answer from this. In fact, if I added (x-1) % 4 as a function, it could do it at the same level with this attribute only, but I think that the point allows the tree to find patterns more.
And here is the code for this:
// this is the sequence y follows int[] ysequence = new int[] { 1, 2, 3, 2 }; // this generates the correct Y for a given X int CalcY(int x) => ysequence[(x - 1) % 4]; // this generates some inputs - just a few differnt mod of x int[] CalcInputs(int x) => new int[] { x % 2, x % 3, x % 4, x % 5, x % 6 }; // for http://stackoverflow.com/questions/40573388/simple-accord-net-machine-learning-example [TestMethod] public void AccordID3TestStackOverFlowQuestion2() { // build the training data set int numtrainingcases = 12; int[][] inputs = new int[numtrainingcases][]; int[] outputs = new int[numtrainingcases]; Console.WriteLine("\t\t\t\tx \ty"); for (int x = 1; x <= numtrainingcases; x++) { int y = CalcY(x); inputs[x-1] = CalcInputs(x); outputs[x-1] = y; Console.WriteLine("TrainingData \t " +x+"\t "+y); } // define how many values each input can have DecisionVariable[] attributes = { new DecisionVariable("Mod2",2), new DecisionVariable("Mod3",3), new DecisionVariable("Mod4",4), new DecisionVariable("Mod5",5), new DecisionVariable("Mod6",6) }; // define how many outputs (+1 only because y doesn't use zero) int classCount = outputs.Max()+1; // create the tree DecisionTree tree = new DecisionTree(attributes, classCount); // Create a new instance of the ID3 algorithm ID3Learning id3learning = new ID3Learning(tree); // Learn the training instances! Populates the tree id3learning.Learn(inputs, outputs); Console.WriteLine(); // now try to predict some cases that werent in the training data for (int x = numtrainingcases+1; x <= 2* numtrainingcases; x++) { int[] query = CalcInputs(x); int answer = tree.Decide(query); // makes the prediction Assert.AreEqual(CalcY(x), answer); // check the answer is what we expected - ie the tree got it right Console.WriteLine("Prediction \t\t " + x+"\t "+answer); } }
This is the result that it produces:
xy TrainingData 1 1 TrainingData 2 2 TrainingData 3 3 TrainingData 4 2 TrainingData 5 1 TrainingData 6 2 TrainingData 7 3 TrainingData 8 2 TrainingData 9 1 TrainingData 10 2 TrainingData 11 3 TrainingData 12 2 Prediction 13 1 Prediction 14 2 Prediction 15 3 Prediction 16 2 Prediction 17 1 Prediction 18 2 Prediction 19 3 Prediction 20 2 Prediction 21 1 Prediction 22 2 Prediction 23 3 Prediction 24 2
Hope this helps.
EDIT: After the comments below, the example is modified to teach the previous values ββof the target (Y), and not the traits derived from the time index (X). This means that you cannot start training at the beginning of your series - since you need the background of previous Y values. In this example, I started with x = 9 only because it keeps the same sequence.
// this is the sequence y follows int[] ysequence = new int[] { 1, 2, 3, 2 }; // this generates the correct Y for a given X int CalcY(int x) => ysequence[(x - 1) % 4]; // this generates some inputs - just a few differnt mod of x int[] CalcInputs(int x) => new int[] { CalcY(x-1), CalcY(x-2), CalcY(x-3), CalcY(x-4), CalcY(x - 5) }; //int[] CalcInputs(int x) => new int[] { x % 2, x % 3, x % 4, x % 5, x % 6 }; // for http://stackoverflow.com/questions/40573388/simple-accord-net-machine-learning-example [TestMethod] public void AccordID3TestTestStackOverFlowQuestion2() { // build the training data set int numtrainingcases = 12; int starttrainingat = 9; int[][] inputs = new int[numtrainingcases][]; int[] outputs = new int[numtrainingcases]; Console.WriteLine("\t\t\t\tx \ty"); for (int x = starttrainingat; x < numtrainingcases + starttrainingat; x++) { int y = CalcY(x); inputs[x- starttrainingat] = CalcInputs(x); outputs[x- starttrainingat] = y; Console.WriteLine("TrainingData \t " +x+"\t "+y); } // define how many values each input can have DecisionVariable[] attributes = { new DecisionVariable("y-1",4), new DecisionVariable("y-2",4), new DecisionVariable("y-3",4), new DecisionVariable("y-4",4), new DecisionVariable("y-5",4) }; // define how many outputs (+1 only because y doesn't use zero) int classCount = outputs.Max()+1; // create the tree DecisionTree tree = new DecisionTree(attributes, classCount); // Create a new instance of the ID3 algorithm ID3Learning id3learning = new ID3Learning(tree); // Learn the training instances! Populates the tree id3learning.Learn(inputs, outputs); Console.WriteLine(); // now try to predict some cases that werent in the training data for (int x = starttrainingat+numtrainingcases; x <= starttrainingat + 2 * numtrainingcases; x++) { int[] query = CalcInputs(x); int answer = tree.Decide(query); // makes the prediction Assert.AreEqual(CalcY(x), answer); // check the answer is what we expected - ie the tree got it right Console.WriteLine("Prediction \t\t " + x+"\t "+answer); } }
You can also consider learning the differences between previous Y values ββthat will work better if the absolute Y value is not as important as the relative change.