Простым способом сделать это было бы использование дерева решений соглашения ID3.
Трюк заключается в том, чтобы определить, какие входные данные использовать - вы не можете просто тренироваться на X - дерево не узнает ничего о будущих значениях X из этого - однако вы можете построить некоторые функции, полученные из X (или предыдущие значения Y), которые будут полезны.
Обычно для таких проблем вы делаете каждое предсказание на основе признаков, полученных из предыдущих значений Y (предсказанная вещь), а не X. Однако это предполагает, что вы можете наблюдать Y последовательно между каждым прогнозом (вы не можете затем предскажите для любого арбитанта X), поэтому я буду придерживаться вопроса, представленного.
У меня было желание построить дерево решений Accord ID3, чтобы решить эту проблему ниже. Я использовал несколько разных значений x % n
как функции - надеясь, что дерево может решить ответ на этот вопрос. На самом деле, если бы я добавил (x-1) % 4
как функцию, он мог бы сделать это на одном уровне только с этим атрибутом, но я думаю, что это больше, чтобы дерево находило шаблоны.
А вот код, который:
// 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\t x \t y");
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);
}
}
Это выход он производит:
x y
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
Надежда, что помогает.
РЕДАКТИРОВАТЬ: После комментариев ниже пример изменен для обучения по предыдущим значениям цели (Y) - вместо признаков, полученных из индекса времени (X). Это означает, что вы не можете начать обучение в начале своей серии - так как вам нужна предыстория предыдущих значений Y. В этом примере я начал с x = 9 только потому, что он сохраняет ту же последовательность.
// 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\t x \t y");
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);
}
}
Вы также могли бы рассмотреть возможность обучения на различиях между предыдущими значениями Y - которые будут работать лучше, когда абсолютное значение Y не так важно, как относительное изменение.
Это замечательно, я много наклоняюсь из этого примера (как создавать входы и выходы) Пример работал отлично. Но в «реальном случае» я не могу использовать значение X для вычислений, так как это временная серия (например, x1 = 3:00 AM, x2 = 4: 00am, x3 = 5: 00am), поэтому я только имеют временную серию всех значений Y и хотите найти здесь, чтобы помочь предсказать, что будет следующим значением Y .... если это произойдет? – RHC
Уверен - более естественно использовать предыдущие значения цели (Y) для временных рядов - по крайней мере, когда фактическое время не имеет значения, а соотношение между значениями - это место, где лежит шаблон. – reddal
Я отредактирую ответ, чтобы добавить, как пример может быть изменен для обучения по предыдущим значениям Y. – reddal