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); }
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); }
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, }); } }