private IDecisionNode FitPolicyToHero(HeroType heroType, List <Episode> episodes, Policy policy)
        {
            DecisionNodeAccuracy rootAccuracy = CalculateDecisionTree(episodes);
            IDecisionNode        root         = rootAccuracy.Root;

            Console.WriteLine(string.Format(
                                  "GPU: Policy [{0}] ({1} leaves from {2} episodes) accuracy: {3}",
                                  heroType == HeroType.None ? "All" : heroType.ToString(),
                                  CountLeaves(root),
                                  episodes.Count,
                                  rootAccuracy.Accuracy));

            return(root);
        }
Ejemplo n.º 2
0
        private async Task <IDecisionNode> FitPolicyToHero(HeroType heroType, List <Episode> episodes, Policy policy)
        {
            double grandTotalWeight = episodes.Sum(x => x.Weight);
            DecisionNodeAccuracy decisionNodeAccuracy =
                await OptimalDecisionNode(episodes, grandTotalWeight);

            Console.WriteLine(string.Format(
                                  "CPU: Policy [{0}] ({1} leaves from {2} episodes) accuracy: {3}",
                                  heroType == HeroType.None ? "All" : heroType.ToString(),
                                  CountLeaves(decisionNodeAccuracy.DecisionNode),
                                  episodes.Count,
                                  decisionNodeAccuracy.CorrectWeight / grandTotalWeight));

            return(decisionNodeAccuracy.DecisionNode);
        }
Ejemplo n.º 3
0
        private async Task <DecisionNodeAccuracy> OptimalDecisionNode(List <Episode> episodes, double grandTotalWeight)
        {
            double[] tacticWeights = TacticEntropy.TacticFrequency(episodes);
            double   totalWeight   = tacticWeights.Sum();
            double   leafEntropy   = TacticEntropy.Entropy(tacticWeights);

            DecisionNodeAccuracy bestLeaf = OptimalLeaf(episodes, tacticWeights);

            if (bestLeaf.CorrectWeight + double.Epsilon >= totalWeight)
            {
                // We already know the perfect answer
                return(bestLeaf);
            }

            double maximumCorrectWeight = totalWeight;
            double maximumIncrease      = maximumCorrectWeight - bestLeaf.CorrectWeight;
            double requiredIncrease     = RequiredIncreaseToSplit * grandTotalWeight;

            if (maximumIncrease < requiredIncrease)
            {
                // Cannot make a big enough difference to the big picture
                return(bestLeaf);
            }



            PartitionScore partitionScore =
                _continuousLearner.Optimizers(episodes, tacticWeights)
                .Concat(_categoricalLearner.Optimizers(episodes, tacticWeights))
                .AsParallel()
                .Select(partitionEvaluator => partitionEvaluator())
                .Where(x => x != null && x.LeftEpisodes.Count > 0 && x.RightEpisodes.Count > 0)
                .MinByOrDefault(x => x.Entropy);

            if (partitionScore == null || partitionScore.Entropy >= leafEntropy)
            {
                if (partitionScore?.Entropy > leafEntropy + double.Epsilon)
                {
                    Console.WriteLine("Entropy should never increase with a split");
                }
                // No split found
                return(bestLeaf);
            }

            DecisionNodeAccuracy left = await OptimalDecisionNode(partitionScore.LeftEpisodes, grandTotalWeight);

            DecisionNodeAccuracy right = await OptimalDecisionNode(partitionScore.RightEpisodes, grandTotalWeight);

            DecisionNode splitter = new DecisionNode()
            {
                Partitioner = partitionScore.Partitioner,
                Left        = left.DecisionNode,
                Right       = right.DecisionNode,
            };
            double bestSplitCorrectWeight = left.CorrectWeight + right.CorrectWeight;
            double correctWeightIncrease  = bestSplitCorrectWeight - bestLeaf.CorrectWeight;

            if (correctWeightIncrease < requiredIncrease)
            {
                return(bestLeaf);
            }
            else
            {
                return(new DecisionNodeAccuracy {
                    DecisionNode = splitter,
                    CorrectWeight = bestSplitCorrectWeight,
                });
            }
        }