←Back to Science Coding Hub/Part J/J3
J3Medium★ Core Essential · Industrial BedrockPart J · RecSys & Search Metrics

NDCG@K (Normalized Discounted Cumulative Gain)

Industrial-grade implementation and mathematical foundations of NDCG@K (Normalized Discounted Cumulative Gain).

⏱️ Time Complexity: O(K log K) 理想排序开销
💾 Space Complexity: O(K)
💡

Core Mental Anchor / Mnemonic

Master NDCG@K (Normalized Discounted Cumulative Gain): enforce numerical stability, check tensor shapes, and eliminate redundant memory allocations.

📐 Mathematical Derivation & Core Formula

DCG@K=∑i=1K2reli−1log⁡2(i+1),NDCG@K=DCG@KIDCG@K\mathrm{DCG}@K = \sum_{i=1}^K \frac{2^{rel_i} - 1}{\log_2(i + 1)}, \quad \mathrm{NDCG}@K = \frac{\mathrm{DCG}@K}{\mathrm{IDCG}@K}
### Mathematical Derivation & Theoretical Principles
Detailed first-principles formulation and architectural mechanics for NDCG@K (Normalized Discounted Cumulative Gain).

Refer to the LaTeX equation above for the core operator definition. The operator is designed to ensure strict numerical bounds, avoiding floating-point overflows and gradient anomalies.

🔄 Tensor Dimensions & Shape Flow

相关度列表 -> 截取前 K -> (2^rel - 1)/log2(i+2) sum 得 DCG -> 降序理想排列算 IDCG -> DCG/IDCG

🛡️ Industrial Numerical Stability & Pitfalls

  • Ensure proper multi-dimensional tensor broadcasting and keepdims retention.
  • Enforce numerical guards (eps clamping and overflow thresholds) during exponentiation and division.
  • Verify train versus eval mode behavioral distinctions (e.g. frozen running statistics and dropout bypass).

💻 Industrial Code Implementation

import numpy as np

def compute_ndcg_at_k(relevance_scores: list, k: int = 10) -> float:
    """
    参数:
        relevance_scores: 按推荐/搜索排序给出的真实相关度得分列表 (如 [3, 2, 0, 1])
        k: 截断位置
    """
    rel = np.asarray(relevance_scores)[:k]
    if len(rel) == 0:
        return 0.0
        
    # 1. 计算实际预测顺序的 DCG@K
    discounts = np.log2(np.arange(len(rel)) + 2) # i=0 时 log2(2)=1.0
    gains = 2.0 ** rel - 1.0
    dcg = np.sum(gains / discounts)
    
    # 2. 计算理想完美顺序下的 IDCG@K
    ideal_rel = np.sort(np.asarray(relevance_scores))[::-1][:k]
    ideal_gains = 2.0 ** ideal_rel - 1.0
    ideal_discounts = np.log2(np.arange(len(ideal_rel)) + 2)
    idcg = np.sum(ideal_gains / ideal_discounts)
    
    if idcg == 0.0:
        return 0.0
    return float(dcg / idcg)

🧪 Runnable Assertions & Validation

Copy and run directly in Python / Jupyter to verify correctness:

import numpy as np
# 完美排序
assert compute_ndcg_at_k([3, 2, 1, 0], k=3) == 1.0
# 最差逆序
ndcg_bad = compute_ndcg_at_k([0, 1, 2, 3], k=4)
assert 0.0 < ndcg_bad < 1.0
print("✓ NDCG@K 排名增益评估自测通过")

🎯 Core Architecture Follow-up Q&A

Q1:What are the key trade-offs and memory bottlenecks when deploying NDCG@K (Normalized Discounted Cumulative Gain) in high-throughput inference?
Memory bandwidth (HBM to SRAM I/O) is the primary latency factor. Fusing element-wise operations and avoiding intermediate tensor materialization significantly outperforms naive implementations.
Q2:How does NDCG@K (Normalized Discounted Cumulative Gain) handle extreme numerical boundaries or precision reduction (FP16/BF16/INT8)?
Under low precision, operations must be upcasted to FP32 during accumulation to prevent underflow/overflow, followed by proper scaling and clamping before converting back to the target format.
←Prev: AUC-ROC Calculation with Rank Ties HandlingAll 69 KernelsNext: Confusion Matrix, Precision, Recall & Macro/Micro F1→