Nếu tôi hiểu chính xác câu hỏi, bạn đã đào tạo một thuật toán phân chia dữ liệu của bạn thành cụm rời rạc. Bây giờ bạn muốn gán dự đoán cho một số tập hợp con của cụm và cho phần còn lại của chúng. Và không phải là các tập hợp con đó, bạn muốn tìm các tập hợp tối ưu pareto, tức là những tập hợp tối đa hóa tỷ lệ dương thực sự với số lượng dự đoán dương cố định (điều này tương đương với việc sửa PPV). Nó có đúng không?1 0N10
Điều này nghe có vẻ rất giống như vấn đề ba lô ! Kích thước cụm là "trọng số" và số lượng mẫu dương trong một cụm là "giá trị" và bạn muốn lấp đầy chiếc ba lô có công suất cố định với càng nhiều giá trị càng tốt.
Vấn đề về chiếc ba lô có một số thuật toán để tìm giải pháp chính xác (ví dụ: bằng lập trình động). Nhưng một giải pháp tham lam hữu ích là sắp xếp các cụm của bạn theo thứ tự giảm dần (nghĩa là chia sẻ các mẫu dương tính) và lấy đầu tiên . Nếu bạn lấy từ đến , bạn có thể phác họa đường cong ROC của mình rất rẻ. kk0Nv a l u ew e i gh tkk0N
Và nếu bạn chỉ định cho các cụm đầu tiên và cho phân số ngẫu nhiên của các mẫu trong cụm thứ , bạn sẽ có được giới hạn trên cho vấn đề về chiếc ba lô. Với điều này, bạn có thể vẽ giới hạn trên cho đường cong ROC của mình.k - 1 p ∈ [ 0 , 1 ] k1k - 1p ∈ [ 0 , 1 ]k
Dưới đây là một ví dụ về con trăn:
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();
Mã này sẽ vẽ một bức tranh đẹp cho bạn:
Các dấu chấm màu xanh là các bộ dữ liệu (FPR, TPR) cho tất cả các tập con và đường màu đỏ kết nối (FPR, TPR) cho các tập hợp con tối ưu pareto.210
Và bây giờ là một chút muối: bạn hoàn toàn không phải bận tâm về các tập con ! Những gì tôi đã làm là sắp xếp lá cây theo tỷ lệ mẫu dương tính trong mỗi mẫu. Nhưng những gì tôi nhận được chính xác là đường cong ROC cho dự đoán xác suất của cây. Điều này có nghĩa là, bạn không thể vượt trội hơn cây bằng cách tự tay hái lá dựa trên tần số mục tiêu trong tập huấn luyện.
Bạn có thể thư giãn và tiếp tục sử dụng dự đoán xác suất thông thường :)