Wenn ich die Frage richtig verstanden habe, haben Sie einen Algorithmus trainiert, der Ihre Daten in disjunkte Cluster aufteilt. Nun mögen Sie Vorhersage zuweisen 1 zu einem gewissen Teil der Cluster und 0 auf den Rest von ihnen. Und unter diesen Teilmengen möchten Sie die pareto-optimalen finden, dh diejenigen, die die wahre positive Rate bei einer festgelegten Anzahl positiver Vorhersagen maximieren (dies entspricht der Festlegung des PPV). Ist es richtig?N10
Das klingt sehr nach einem Rucksackproblem ! Clustergrößen sind "Gewichte" und die Anzahl der positiven Stichproben in einem Cluster sind "Werte". Sie möchten Ihren Rucksack mit fester Kapazität mit so viel Wert wie möglich füllen.
Das Rucksackproblem hat mehrere Algorithmen, um exakte Lösungen zu finden (z. B. durch dynamische Programmierung). Aber eine nützliche gierig Lösung ist Ihre Cluster in absteigender Reihenfolge der sortieren (d. h. Anteil positiver Proben) und nimm das erstek. Wenn Siekvon0nachN nehmen, können Sie Ihre ROC-Kurve sehr billig skizzieren.v a l u ew e i gh tkk0N
Und wenn Sie den ersten k - 1 - Clustern und dem Zufallsbruchteil p ∈ [ 0 , 1 ] der Stichproben im k - ten Cluster zuweisen , erhalten Sie die Obergrenze für das Rucksackproblem. Hiermit können Sie die Obergrenze für Ihre ROC-Kurve zeichnen.1k - 1p ∈ [ 0 , 1 ]k
Hier ist ein Python-Beispiel:
import numpy as np
from itertools import combinations, chain
import matplotlib.pyplot as plt
np.random.seed(1)
n_obs = 1000
n = 10
# generate clusters as indices of tree leaves
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_predict
X, target = make_classification(n_samples=n_obs)
raw_clusters = DecisionTreeClassifier(max_leaf_nodes=n).fit(X, target).apply(X)
recoding = {x:i for i, x in enumerate(np.unique(raw_clusters))}
clusters = np.array([recoding[x] for x in raw_clusters])
def powerset(xs):
""" Get set of all subsets """
return chain.from_iterable(combinations(xs,n) for n in range(len(xs)+1))
def subset_to_metrics(subset, clusters, target):
""" Calculate TPR and FPR for a subset of clusters """
prediction = np.zeros(n_obs)
prediction[np.isin(clusters, subset)] = 1
tpr = sum(target*prediction) / sum(target) if sum(target) > 0 else 1
fpr = sum((1-target)*prediction) / sum(1-target) if sum(1-target) > 0 else 1
return fpr, tpr
# evaluate all subsets
all_tpr = []
all_fpr = []
for subset in powerset(range(n)):
tpr, fpr = subset_to_metrics(subset, clusters, target)
all_tpr.append(tpr)
all_fpr.append(fpr)
# evaluate only the upper bound, using knapsack greedy solution
ratios = [target[clusters==i].mean() for i in range(n)]
order = np.argsort(ratios)[::-1]
new_tpr = []
new_fpr = []
for i in range(n):
subset = order[0:(i+1)]
tpr, fpr = subset_to_metrics(subset, clusters, target)
new_tpr.append(tpr)
new_fpr.append(fpr)
plt.figure(figsize=(5,5))
plt.scatter(all_tpr, all_fpr, s=3)
plt.plot(new_tpr, new_fpr, c='red', lw=1)
plt.xlabel('TPR')
plt.ylabel('FPR')
plt.title('All and Pareto-optimal subsets')
plt.show();
Dieser Code wird ein schönes Bild für Sie zeichnen:
Die blauen Punkte sind (FPR, TPR) Tupel für alle Teilmengen, und die rote Linie verbindet (FPR, TPR) für die paretooptimalen Teilmengen.210
Und jetzt das bisschen Salz: Sie mussten sich überhaupt nicht um Teilmengen kümmern ! Was ich getan habe, ist das Sortieren der Baumblätter nach dem Anteil der positiven Proben in jeder. Was ich aber bekommen habe, ist genau die ROC-Kurve für die probabilistische Vorhersage des Baumes. Dies bedeutet, dass Sie den Baum nicht übertreffen können, indem Sie seine Blätter anhand der Zielhäufigkeiten im Trainingssatz von Hand auswählen.
Sie können sich entspannen und die normale Wahrscheinlichkeitsvorhersage verwenden :)