Si entendí la pregunta correctamente, has entrenado un algoritmo que divide tus datos en grupos disjuntos. Ahora desea asignar la predicción a algún subconjunto de los clústeres y al resto de ellos. Y en esos subconjuntos, desea encontrar los pareto-óptimos, es decir, aquellos que maximizan la tasa positiva verdadera dado un número fijo de predicciones positivas (esto es equivalente a fijar PPV). ¿Es correcto?norte10 0
¡Esto suena muy parecido al problema de la mochila ! Los tamaños de los conglomerados son "pesos" y el número de muestras positivas en un conglomerado son "valores", y desea llenar su mochila de capacidad fija con el mayor valor posible.
El problema de la mochila tiene varios algoritmos para encontrar soluciones exactas (por ejemplo, mediante programación dinámica). Pero una solución codiciosa útil es ordenar los grupos en orden decreciente de (es decir, compartir muestras positivas) y tomar la primera . Si lleva de a , puede dibujar su curva ROC de forma muy económica.v a l u ew e i gh tkk0 0norte
Y si asigna a los primeros grupos de y a la fracción aleatoria de muestras en el grupo , obtendrá el límite superior del problema de la mochila. Con esto, puede dibujar el límite superior de su curva ROC.1k - 1p ∈ [ 0 , 1 ]k
Aquí va un ejemplo de python:
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();
Este código dibujará una buena imagen para ti:
210
Y ahora un poco de sal: ¡no tenía que preocuparse por los subconjuntos en absoluto ! Lo que hice fue ordenar las hojas de los árboles por la fracción de muestras positivas en cada una. Pero lo que obtuve es exactamente la curva ROC para la predicción probabilística del árbol. Esto significa que no puede superar el rendimiento del árbol seleccionando manualmente sus hojas en función de las frecuencias objetivo en el conjunto de entrenamiento.
Puedes relajarte y seguir usando predicciones probabilísticas ordinarias :)