AI Engineering Academy · Pelajaran

Metrik Pengambilan: Hit Rate, MRR, dan NDCG

Buat set data acuan berisi kueri dan dokumen yang relevan, lalu hitung hit rate, peringkat timbal balik rata-rata, dan NDCG untuk mengukur seberapa sering sistem pengambil menemukan bagian yang tepat.

Pelajaran 2 dari 413 langkah

Metrik Pengambilan: Hit Rate, MRR, dan NDCG adalah pelajaran AI Engineering Academy gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Engineering Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Engineering Academy mencakup 4 pelajaran total.

Mengapa Metrik Pengambilan Berbeda?

Hit rate memberi tahu Anda apakah bagian yang relevan muncul di posisi mana pun dalam K hasil teratas, tetapi tidak memberi tahu di mana bagian itu muncul dalam peringkat. Sistem yang selalu menempatkan bagian terbaik di peringkat 5 lebih buruk daripada sistem yang secara konsisten menempatkannya di peringkat 1, meskipun keduanya memiliki hit rate yang sama. Metrik yang lebih mendalam seperti MRR dan NDCG menangkap kualitas peringkat, serta memberi penghargaan kepada sistem yang menempatkan bagian paling relevan di posisi teratas, tempat LLM dan pengguna paling mungkin memakainya.

Hit Rate @K: Tinjauan dan Penerapan

Hit rate@K adalah metrik paling sederhana: pada berapa proporsi kueri setidaknya satu bagian yang relevan muncul dalam K hasil teratas? Metrik ini memberikan sinyal biner untuk setiap kueri dan mudah ditafsirkan. Hitung dengan memeriksa irisan himpunan antara ID yang diambil dan ID relevan yang diketahui. Gunakan K=5 sebagai nilai bawaan karena sebagian besar sistem RAG mengambil 5 bagian. Bandingkan hit rate@1, @3, dan @5 untuk memahami bagaimana sensitivitas berubah ketika jendela pengambilan diperluas.

def hit_rate_at_k(golden_dataset, retriever, k=5):
    hits = 0
    for item in golden_dataset:
        retrieved = retriever.retrieve(item['question'], top_k=k)
        retrieved_ids = [r['id'] for r in retrieved[:k]]
        relevant_ids = set(item['relevant_chunk_ids'])
        if any(rid in relevant_ids for rid in retrieved_ids):
            hits += 1
    return hits / len(golden_dataset)

for k in [1, 3, 5, 10]:
    hr = hit_rate_at_k(golden_dataset, retriever, k=k)
    print(f'Hit rate@{k}: {hr:.1%}')

Mean Reciprocal Rank (MRR)

MRR (Mean Reciprocal Rank) mengukur rata-rata kebalikan dari peringkat tempat bagian relevan pertama muncul. Jika bagian relevan berada di peringkat 1, nilai kebalikan peringkatnya adalah 1/1 = 1.0. Pada peringkat 2 nilainya 0.5, sedangkan pada peringkat 5 nilainya 0.2. MRR dirata-ratakan untuk semua kueri. MRR yang lebih tinggi berarti pengambil secara konsisten menempatkan bagian relevan di dekat posisi teratas, yang penting karena LLM lebih memperhatikan konteks yang ditempatkan di bagian awal perintah.

def mean_reciprocal_rank(golden_dataset, retriever, top_k=10):
    reciprocal_ranks = []
    for item in golden_dataset:
        retrieved = retriever.retrieve(item['question'], top_k=top_k)
        retrieved_ids = [r['id'] for r in retrieved]
        relevant_ids = set(item['relevant_chunk_ids'])

        rr = 0.0
        for rank, rid in enumerate(retrieved_ids, start=1):
            if rid in relevant_ids:
                rr = 1.0 / rank
                break  # only the first relevant result counts
        reciprocal_ranks.append(rr)

    mrr = sum(reciprocal_ranks) / len(reciprocal_ranks)
    print(f'MRR@{top_k}: {mrr:.3f}')
    return mrr

Menafsirkan Skor MRR

Skor MRR memiliki tafsiran yang intuitif: MRR = 1.0 berarti bagian relevan pertama selalu berada di peringkat 1 (sempurna). MRR = 0.5 berarti bagian tersebut biasanya berada di peringkat 2. MRR = 0.25 berarti biasanya berada di peringkat 4—informasi relevan muncul cukup jauh di bawah sehingga mungkin terpotong dari konteks. Untuk RAG, targetkan MRR > 0.7 guna memastikan bagian paling relevan secara konsisten berada di antara dua posisi pertama.

# MRR interpretation table
mrr_interpretations = {
    1.0:  'Perfect — relevant chunk always at rank 1',
    0.5:  'Good — typically at rank 2',
    0.33: 'Acceptable — typically at rank 3',
    0.25: 'Weak — typically at rank 4',
    0.1:  'Poor — relevant chunk rarely near the top'
}

for score, description in mrr_interpretations.items():
    print(f'MRR {score:.2f}: {description}')

Precision @K

Precision@K mengukur proporsi dari K bagian yang diambil yang benar-benar relevan. Berbeda dari hit rate (yang bersifat biner), precision@K mengukur rasio sinyal terhadap derau dalam hasil pengambilan Anda. Precision yang rendah berarti LLM menerima konteks yang tidak relevan bersamaan dengan bagian yang relevan, sehingga meningkatkan risiko kebingungan atau injeksi perintah. Untuk RAG, precision@5 > 0.6 merupakan sasaran yang sehat.

def precision_at_k(golden_dataset, retriever, k=5):
    precisions = []
    for item in golden_dataset:
        retrieved = retriever.retrieve(item['question'], top_k=k)
        retrieved_ids = [r['id'] for r in retrieved[:k]]
        relevant_ids = set(item['relevant_chunk_ids'])

        relevant_retrieved = sum(
            1 for rid in retrieved_ids if rid in relevant_ids
        )
        precision = relevant_retrieved / k
        precisions.append(precision)

    mean_precision = sum(precisions) / len(precisions)
    print(f'Precision@{k}: {mean_precision:.3f}')
    return mean_precision

Discounted Cumulative Gain (DCG)

DCG adalah metrik evaluasi daftar berperingkat yang memberikan penghargaan jika bagian yang lebih relevan ditempatkan lebih tinggi. Metrik ini menjumlahkan skor relevansi bagian yang diambil, tetapi mendiskonnya secara logaritmik berdasarkan posisi: peringkat 1 mendapat kredit penuh, peringkat 2 mendapat diskon log(2), dan seterusnya. Bagian yang lebih relevan di posisi teratas menghasilkan DCG yang lebih tinggi. Versi ternormalisasi (NDCG) membagi nilai tersebut dengan DCG ideal (peringkat terbaik yang mungkin) untuk menghasilkan skor antara 0 dan 1.

import math

def dcg_at_k(relevances, k):
    '''relevances[i] = 1 if chunk at rank i+1 is relevant, else 0'''
    dcg = 0.0
    for i, rel in enumerate(relevances[:k]):
        # rank is i+1, discount is log2(rank + 1)
        dcg += rel / math.log2(i + 2)
    return dcg

def ndcg_at_k(retrieved_ids, relevant_ids, k):
    relevances = [1 if rid in relevant_ids else 0
                  for rid in retrieved_ids[:k]]
    actual_dcg = dcg_at_k(relevances, k)
    ideal_dcg = dcg_at_k([1] * min(len(relevant_ids), k), k)
    return actual_dcg / ideal_dcg if ideal_dcg > 0 else 0.0

Menghitung NDCG di Seluruh Dataset

NDCG@K adalah metrik pengambilan standar emas untuk sistem pencarian. Metrik ini menangkap relevansi dan posisi peringkat secara bersamaan. NDCG@5 sebesar 0.85 berarti pengambil Anda secara rata-rata mencapai 85% dari peringkat terbaik secara teoretis. NDCG menangani kasus ketika terdapat beberapa bagian relevan untuk setiap kueri (masing-masing mendapat skor relevansi) dan memberikan penalti kepada sistem yang menemukan bagian relevan tetapi menempatkannya terlalu rendah.

def mean_ndcg_at_k(golden_dataset, retriever, k=5):
    ndcg_scores = []
    for item in golden_dataset:
        retrieved = retriever.retrieve(item['question'], top_k=k)
        retrieved_ids = [r['id'] for r in retrieved[:k]]
        relevant_ids = set(item['relevant_chunk_ids'])
        score = ndcg_at_k(retrieved_ids, relevant_ids, k)
        ndcg_scores.append(score)
    mean = sum(ndcg_scores) / len(ndcg_scores)
    print(f'NDCG@{k}: {mean:.4f}')
    return mean

# Compute all retrieval metrics together
hit_rate = hit_rate_at_k(golden_dataset, retriever, k=5)
mrr = mean_reciprocal_rank(golden_dataset, retriever, top_k=5)
ndcg = mean_ndcg_at_k(golden_dataset, retriever, k=5)

Menggunakan RAGAS untuk Metrik Otomatis

Pustaka RAGAS menyediakan kerangka evaluasi siap produksi untuk sistem RAG. Pustaka ini menerapkan metrik precision konteks, recall konteks, kesetiaan, dan relevansi jawaban dengan pendekatan LLM sebagai penilai. Berikan pertanyaan, jawaban, konteks yang diambil, dan jawaban acuan Anda kepada RAGAS untuk memperoleh laporan evaluasi lengkap dengan skor untuk setiap metrik. Ini adalah cara tercepat untuk menyiapkan pipeline evaluasi RAG yang menyeluruh.

from ragas import evaluate
from ragas.metrics import (
    context_precision,
    context_recall,
    faithfulness,
    answer_relevancy
)
from datasets import Dataset

eval_data = Dataset.from_list([
    {
        'question': item['question'],
        'answer': item['generated_answer'],
        'contexts': item['retrieved_texts'],
        'ground_truth': item['expected_answer']
    }
    for item in golden_dataset_with_answers
])

results = evaluate(
    eval_data,
    metrics=[context_precision, context_recall, faithfulness, answer_relevancy]
)
print(results)

Membagi Metrik Berdasarkan Kategori Kueri

Rata-rata metrik secara keseluruhan dapat menyembunyikan pola penting. Bagi dataset emas Anda ke dalam beberapa kategori—pencarian fakta, perbandingan, pertanyaan prosedural tentang cara melakukan sesuatu, dan pertanyaan di luar cakupan—lalu hitung metrik secara terpisah untuk masing-masing kategori. Anda mungkin menemukan bahwa hit rate mencapai 95% untuk pencarian fakta, tetapi hanya 60% untuk perbandingan multi-langkah. Metrik tingkat kategori mengungkap mode kegagalan tertentu yang tersembunyi di balik skor agregat.

from collections import defaultdict

def evaluate_by_category(golden_dataset, retriever):
    by_category = defaultdict(list)
    for item in golden_dataset:
        category = item.get('category', 'unknown')
        retrieved = retriever.retrieve(item['question'], top_k=5)
        retrieved_ids = {r['id'] for r in retrieved}
        hit = bool(retrieved_ids & set(item['relevant_chunk_ids']))
        by_category[category].append(hit)

    print('Hit rate by category:')
    for cat, hits in sorted(by_category.items()):
        hr = sum(hits) / len(hits)
        print(f'  {cat}: {hr:.1%} ({sum(hits)}/{len(hits)})')

Saat Metrik Tidak Selaras

Terkadang metrik memberikan sinyal yang bertentangan. Anda mungkin meningkatkan NDCG (peringkat yang lebih baik), sementara hit rate tetap datar (jumlah kegagalan yang sama). Hal ini terjadi ketika pengoptimalan memindahkan bagian relevan dari peringkat 6 ke peringkat 2 tanpa membawa kueri yang sebelumnya gagal ke dalam 5 hasil teratas. Dalam kasus seperti ini, periksa apakah pengoptimalan Anda membantu kueri yang sebelumnya sudah berhasil, tetapi mengabaikan kueri yang gagal. Selalu periksa contoh kegagalan individual bersama metrik agregat.

def analyze_failures(golden_dataset, retriever, top_k=5):
    failures = []
    for item in golden_dataset:
        retrieved = retriever.retrieve(item['question'], top_k=top_k)
        retrieved_ids = {r['id'] for r in retrieved}
        relevant_ids = set(item['relevant_chunk_ids'])
        if not (retrieved_ids & relevant_ids):
            failures.append({
                'question': item['question'],
                'expected_chunks': list(relevant_ids),
                'retrieved_chunks': [r['id'] for r in retrieved],
                'top_score': retrieved[0]['score'] if retrieved else None
            })
    print(f'Failures: {len(failures)}/{len(golden_dataset)}')
    return failures

Recall @K: Kelengkapan Pengambilan

Recall@K mengukur proporsi semua bagian relevan yang diambil dalam K hasil teratas. Jika sebuah pertanyaan memiliki 3 bagian relevan dalam indeks dan pengambil Anda mengembalikan 2 di antaranya dalam 5 hasil teratas, recall@5 adalah 2/3 = 0.67. Recall yang tinggi penting ketika LLM memerlukan beberapa bukti untuk menyusun jawaban yang lengkap—bahkan kehilangan satu bagian penting dapat membuat jawaban tidak lengkap. Seimbangkan precision dan recall dengan menyesuaikan K: K yang lebih besar meningkatkan recall, tetapi menurunkan precision.

def recall_at_k(golden_dataset, retriever, k=5):
    recalls = []
    for item in golden_dataset:
        retrieved = retriever.retrieve(item['question'], top_k=k)
        retrieved_ids = set(r['id'] for r in retrieved[:k])
        relevant_ids = set(item['relevant_chunk_ids'])
        if not relevant_ids:
            continue  # skip items with no annotated relevant chunks
        retrieved_relevant = retrieved_ids & relevant_ids
        recall = len(retrieved_relevant) / len(relevant_ids)
        recalls.append(recall)
    mean_recall = sum(recalls) / len(recalls)
    print(f'Recall@{k}: {mean_recall:.3f}')
    return mean_recall

Pemeriksaan Singkat

Uji pemahaman Anda tentang konsep Rekayasa AI dari pelajaran ini.

Rangkuman Pelajaran

Dalam pelajaran ini, Anda mempelajari: hit rate@K sebagai metrik keberadaan biner, MRR untuk mengukur posisi rata-rata bagian relevan pertama, precision@K untuk rasio sinyal terhadap derau dalam pengambilan, NDCG@K sebagai metrik peringkat standar emas, dan pustaka RAGAS untuk mengotomatiskan evaluasi RAG dengan precision konteks, recall, kesetiaan, dan relevansi jawaban. Selanjutnya, kita akan membahas metrik pembuatan dan pengukuran kesetiaan secara lebih mendalam.

Gratis untuk memulai

Belajar Python dengan tutor AI — gratis

Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.

Kursus
30
Pelajaran
120

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Metrik Pengambilan: Hit Rate, MRR, dan NDCG” gratis?

Ya — teks lengkap “Metrik Pengambilan: Hit Rate, MRR, dan NDCG” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Engineering Academy, upgrade ke CoddyKit PRO. Kursus AI Engineering Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Metrik Pengambilan: Hit Rate, MRR, dan NDCG”?

Buat set data acuan berisi kueri dan dokumen yang relevan, lalu hitung hit rate, peringkat timbal balik rata-rata, dan NDCG untuk mengukur seberapa sering sistem pengambil menemukan bagian yang tepat. Kamu berlatih AI Engineering Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai AI Engineering Academy?

Tidak diperlukan pengalaman sebelumnya. AI Engineering Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Metrik Pengambilan: Hit Rate, MRR, dan NDCG” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Engineering Academy ini?

Ya. Setiap pelajaran AI Engineering Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Mengapa Evaluasi Penting dalam RAG
  2. Metrik Pengambilan: Hit Rate, MRR, dan NDCG
  3. Metrik Pembuatan: Kesetiaan dan Relevansi Jawaban
  4. Membangun Sistem Evaluasi Otomatis
← Kembali ke AI Engineering Academy