我正在运行一个多标签预测模型。作为一个性能度量,我正在检查我的模型中最高的N
预测是否包含y=1
的真实的情况。
例如,如果我的模型对一个数据点的最高预测是黄色(90%)、绿色(80%)、红色(75%),而现实是绿色和红色,我将其视为“正确”预测,而诸如(精确)准确度之类的度量将其视为不正确。
下面是我的实现,它有一个比较实际的大X和y矩阵(有很多列)的例子。我需要找到一个运行速度更快的实现(或完全不同的解决方案)。
以下可重现示例(运行速度太慢,约2分钟):
from scipy.sparse import random
import numpy as np
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
import time
np.random.seed(14)
## Generate sparse X, and y
X = random(100_000, 1000, density=0.01, format='csr')
y = pd.DataFrame(np.random.choice([0, 1], size=(100_000, 10)))
# Define no change as 0 in all rows
y['no_change'] = np.where(y.sum(axis=1) == 0, 1, 0)
dt = DecisionTreeClassifier(max_depth=15)
dt.fit(X, y)
# Print precise accuracy -- truth must precisely match prediction
print(f"Accuracy score (precise): {accuracy_score(y_true=y, y_pred=dt.predict(X=X)):.1%}")
# Get top n predictions based on probability (in case of equality keep all)
def top_n_preds(row, n_top):
topcols = row[row > 0].nlargest(n=n_top, keep='all')
top_colnames = topcols.index.tolist()
return top_colnames
start = time.time()
# Retrieve probabilities of predictions
pred_probs = np.asarray(dt.predict_proba(X=X))
pred_probs = pd.DataFrame(pred_probs[:, :, 1].T, columns=y.columns)
# Find top 5 predictions
pred_probs['top_preds'] = pred_probs.apply(top_n_preds, axis=1, n_top=5)
# List all real changes in y
pred_probs['real_changes'] = y.apply(lambda row: row[row == 1].index.tolist(), axis=1)
# Check if real changes are contained in top 5 predictions
pred_probs['preds_cover_reality'] = pred_probs.apply(lambda row: set(row['real_changes']).issubset(set(row['top_preds'])), axis=1)
print(f"Accuracy present in top n_top predictions: {pred_probs['preds_cover_reality'].sum() / y.shape[0]:.1%}")
print(f"Time elapsed: {(time.time()-start)/60:.1f} minutes")
1条答案
按热度按时间ruyhziif1#
在您的案例中,3个连续的
.apply
调用会产生显著的开销和延迟。为了提高性能,我建议在成对的数据集上进行一次遍历:
pred_probs
和y.values == 1
(一次性获得 *real_changes
* 列的过滤数据集)。另一个开销最大、时间延迟最大的部分是在
pred_probs
行上调用pandas.Series.nlargest
。尽管有人可能认为它可以被
numpy.argpartition
取代,但这并不完全正确。在某些情况下,某些pred_probs
行的过滤值数量可能小于top_N
,这会中断np.argpartition()
调用。更值得注意的是一个特殊的情况
Series.nlargest(n=top_N, keep='all')
,您使用的那个,允许保留副本,以便得到的样本量将大于top_N
。为了以某种方式模仿这种行为,我使用
np.sort
+np.in1d
+np.where
的组合。我的新版本在大约2.5秒内聚合准确性选择/标记以获得最终准确性分数。
样品输出: