def predict_proportional(self, input_data, path=None, missing_found=False, median=False, parent=None): """Makes a prediction based on a number of field values averaging the predictions of the leaves that fall in a subtree. Each time a splitting field has no value assigned, we consider both branches of the split to be true, merging their predictions. The function returns the merged distribution and the last node reached by a unique path. """ if path is None: path = [] final_distribution = {} if not self.children: distribution = self.distribution if not self.weighted else \ self.weighted_distribution return (merge_distributions({}, dict((x[0], x[1]) for x in distribution)), self.min, self.max, self, self.count, parent) if one_branch(self.children, input_data) or \ self.fields[split(self.children)]["optype"] in \ ["text", "items"]: for child in self.children: if child.predicate.apply(input_data, self.fields): new_rule = child.predicate.to_rule(self.fields) if new_rule not in path and not missing_found: path.append(new_rule) return child.predict_proportional(input_data, path, missing_found, median, parent=self) else: # missing value found, the unique path stops missing_found = True minimums = [] maximums = [] population = 0 for child in self.children: (subtree_distribution, subtree_min, subtree_max, _, subtree_pop, _) = \ child.predict_proportional(input_data, path, missing_found, median, parent=self) if subtree_min is not None: minimums.append(subtree_min) if subtree_max is not None: maximums.append(subtree_max) population += subtree_pop final_distribution = merge_distributions( final_distribution, subtree_distribution) return (final_distribution, min(minimums) if minimums else None, max(maximums) if maximums else None, self, population, self)