sklearn ndcg_score 返回了错误的结果

问题描述 投票:0回答:2

我正在从事一个涉及使用NDCG(归一化分布累积增益)的项目,并且我了解该方法的基础计算。

因此,我从

ndcg_score
导入了
sklearn.metrics
,然后将一个真实值数组和另一个数组传递给
ndcg_score
函数来计算它们的 NDCG 分数。地面真值数组的值为
[5, 4, 3, 2, 1]
,而另一个数组的值为
[5, 4, 3, 2, 0]
,因此这两个数组中只有最后一个元素不同。

from sklearn.metrics import ndcg_score

user_ndcg = ndcg_score(array([[5, 4, 3, 2, 1]]), array([[5, 4, 3, 2, 0]]))

我预计结果约为 0.96233 (9.88507/10.27192)。然而,

user_ndcg
居然返回了
1.0
,这让我很惊讶。最初我以为这是由于舍入造成的,但事实并非如此,因为当我对另一组数组进行实验时:
ndcg_score(array([[5, 4, 3, 2, 1]]), array([[5, 4, 0, 2, 0]]))
,它正确返回了0.98898。

有谁知道这是否可能是 sklearn

ndcg_score
函数的错误,或者我的代码是否做错了什么?

scikit-learn ranking recommendation-engine
2个回答
2
投票

我假设您正在尝试预测此问题的六个不同类别(0、1、2、3、4 和 5)。如果要评估五个不同观测值的 ndcg,则必须向函数传递两个形状为

(5, 6)
的数组。

也就是说,您已将基本事实和预测转换为每行五行六列的数组。

# Current form of ground truth and predictions
y_true = [5, 4, 3, 2, 1]
y_pred = [5, 4, 3, 2, 0]
# Transform ground truth to ndarray
y_true_nd = np.zeros(shape=(5, 6))
y_true_nd[np.arange(5), y_true] = 1
# Transform predictions to ndarray
y_pred_nd = np.zeros(shape=(5, 6))
y_pred_nd[np.arange(5), y_pred] = 1
# Calculate ndcg score
ndcg_score(y_true_nd, y_pred_nd)
> 0.8921866522394966

这是

y_true_nd
y_pred_nd
的样子:

y_true_nd

array([[0., 0., 0., 0., 0., 1.],
       [0., 0., 0., 0., 1., 0.],
       [0., 0., 0., 1., 0., 0.],
       [0., 0., 1., 0., 0., 0.],
       [0., 1., 0., 0., 0., 0.]])

y_pred_nd

array([[0., 0., 0., 0., 0., 1.],
       [0., 0., 0., 0., 1., 0.],
       [0., 0., 0., 1., 0., 0.],
       [0., 0., 1., 0., 0., 0.],
       [1., 0., 0., 0., 0., 0.]])

0
投票

在手动计算 NDCG 分子(即 DCG)时,您使用的是“array([[5, 4, 3, 2, 0]])”。 DCG 计算中应该包含的是ground true相关性分数,根据“array([[5, 4, 3, 2, 0]])”的顺序重新排列。由于分数的顺序是严格降序的,因此 DCG 应直接从 array([[5, 4, 3, 2, 1]]) 计算。换句话说,您的“array([[5, 4, 3, 2, 0]])”分数表示 IDCG 场景。这就是为什么你从 sklearn 得到 1 的原因。 即使您将分数更改为“array([[.5, .4, .3, .2, 0]])”,您最终也会得到相同的 NDCG = 1,因为只有顺序与您的分数有关。以下所有命令都会产生相同的值,即“10.27192”

print("DCG score =: ", dcg_score(np.array([[5, 4, 3, 2, 1]]), np.array([[5, 4, 3, 2, 0]])))
print("DCG score =: ", dcg_score(np.array([[5, 4, 3, 2, 1]]), np.array([[.5, .4, .3, .2, .0]])))
print("IDCG score =: ", dcg_score(np.array([[5, 4, 3, 2, 1]]), np.array([[5, 4, 3, 2, 1]])))
© www.soinside.com 2019 - 2024. All rights reserved.