Panduan
Tutorial: classifier dan regressor
Panduan yang dapat dijalankan untuk tiga model prediktif yang dievaluasi dari baris perintah: classifier churn biner, router tiket tiga kelas yang dievaluasi satu kelas sekaligus, dan regressor waktu pengiriman yang dinilai dengan galat absolut dalam rentang yang dideklarasikan. Masing-masing berjalan secara lokal tanpa penyedia, tanpa kunci, dan tanpa jaringan, dan masing-masing diakhiri dengan perubahan kandidat yang diukur terhadap baseline.
Halaman ini adalah pendamping praktik untuk Classifier dan regressor, yang menjelaskan setiap field; baca halaman itu sebagai referensi dan halaman ini untuk melakukannya sekali dari awal sampai akhir. Istilah seperti interval, status keputusan, dan tindakan rilis didefinisikan dalam Konsep.
Apa yang diukur Oloproof untuk model prediktif, dan apa yang tidak
| Model | Apa yang Anda dapatkan | Apa yang tidak Anda dapatkan |
|---|---|---|
| Classifier biner | akurasi, recall, presisi, skor Brier, log loss, ROC-AUC, dan average precision, ditambah hitungan konfusi, tabel kalibrasi, dan sapuan ambang batas | ambang batas yang direkomendasikan |
| Classifier multikelas | satu recall dan satu presisi per kelas, masing-masing metrik biner yang kelas positifnya adalah kelas itu (satu melawan sisanya) | metrik rata-rata makro atau mikro |
| Regressor | rata-rata galat absolut, dibatasi oleh target_range yang Anda deklarasikan | galat kuadrat, R kuadrat, atau galat apa pun tanpa rentang yang dideklarasikan |
Modelnya sendiri tetap milik Anda. Oloproof memanggil fungsi Python yang Anda tunjuk, membaca prediksi yang dikembalikannya, dan tidak pernah melihat fitur, bobot, atau internalnya.
Prasyarat
- Python 3.11 atau yang lebih baru dan pip install oloproof di lingkungan virtual, seperti di mulai cepat.
- File-file contoh, yang disertakan dalam paket. Salin ke direktori baru agar store eksekusi berada di sana:
oloproof init --example predictive ~/oloproof-predictive
cd ~/oloproof-predictiveSetiap perintah di bawah dijalankan dari salah satu dari tiga subdirektorinya. Setiap eksekusi menulis buktinya ke direktori .oloproof/ di samping oloproof.yaml yang dibacanya.
predictive/
binary/ app.py oloproof.yaml candidate.yaml release.yaml comparison.yaml data/accounts.jsonl
multiclass/ app.py oloproof.yaml candidate.yaml release.yaml data/tickets.jsonl
regression/ app.py oloproof.yaml candidate.yaml release.yaml data/orders.jsonlBagian 1: classifier biner
Adapternya
binary/app.py memuat model dan adapter dalam satu file. Modelnya adalah model churn deterministik yang sama dengan contoh churn_model (oloproof init --example churn_model); adapternya adalah fungsi terdekorasi yang dipanggil Oloproof:
from oloproof import system
@system(name="churn-model", version="baseline")
def run(account):
score = churn_score(account)
return {"label": score >= 0.5, "score": round(score, 4)}
@system(name="churn-model", version="candidate-cutoff-0.4")
def run_candidate(account):
score = churn_score(account)
return {"label": score >= 0.4, "score": round(score, 4)}Untuk mengevaluasi model Anda sendiri, pertahankan bentuknya dan ganti churn_score dengan panggilan ke model itu, misalnya model.predict_proba([features(account)])[0][1] untuk model scikit-learn yang Anda muat sekali saat impor. Ubah version setiap kali model atau ambang potongnya berubah: versi adalah bagian dari kunci cache, sehingga model yang dilatih ulang di bawah versi yang sama akan memakai ulang prediksi lama.
Bentuk input dan keluaran
Satu baris data/accounts.jsonl adalah satu kasus:
{"expected": {"label": false}, "id": "account_000", "input": {"recent_upgrade": true, "support_contacts": 0, "tenure_months": 0}, "metadata": {"plan": "enterprise"}}| Bagian | Bentuk | Siapa yang membacanya |
|---|---|---|
| input | objek yang diterima fungsi Anda | adapter Anda |
| expected.label | true atau false, kebenarannya | evaluator |
| metadata.plan | JSON apa pun | hanya irisan |
| label yang dikembalikan | true atau false, prediksinya | evaluator |
| score yang dikembalikan | angka dalam [0, 1], probabilitas kelas positif | Brier, log loss, peringkat, kalibrasi, sapuan |
Evaluatornya, dan mengapa yang ini
binary/oloproof.yaml:
version: 1
project: churn-tutorial
dataset: data/accounts.jsonl
system:
name: churn-model
version: baseline
callable: app:run
evaluators:
- {type: predictive_correct, criterion: accuracy}
- {type: predictive_recall, criterion: recall}
- {type: predictive_precision, criterion: precision}
- {type: predictive_brier, criterion: brier}
- {type: predictive_log_loss, criterion: log_loss, clip: 0.02}
- {type: predictive_ranking, criterion: rank}
metrics:
- {id: roc_auc, type: ranking, criterion: rank, statistic: roc_auc}
- {id: pr_auc, type: ranking, criterion: rank, statistic: average_precision}
predictive:
label_field: label
score_field: score
expected_field: label
positive: true
calibration_bins: 10
thresholds: [0.3, 0.4, 0.5, 0.6, 0.7]
slices: [metadata.plan, "confidence:0.5"]
min_slice_support: 20- Akurasi, recall, dan presisi adalah tiga tingkat atas tiga kumpulan baris yang berbeda: setiap akun, akun yang churn, dan akun yang ditandai model. Model churn memerlukan ketiganya karena sekitar sepertiga akun churn, sehingga model yang memprediksi tidak ada yang churn akurat 68% dan tidak menemukan siapa pun.
- Brier dan log loss menilai probabilitas di balik label. Log loss memerlukan clip, karena satu kesalahan yang yakin jika tidak akan bernilai tak hingga.
- predictive_ranking ditambah dua entri metrics: memberi ROC-AUC dan average precision. Keduanya menjawab seberapa baik model mengurutkan akun, terpisah dari di mana ambang potongnya berada.
- Blok predictive: menyatakan di mana label, skor, dan kebenaran berada, dan menghasilkan hitungan konfusi, tabel kalibrasi, dan sapuan ambang batas di samping metrik.
Kebijakannya
binary/release.yaml menetapkan batas bawah untuk setiap tingkat:
version: 1
confidence_level: 0.95
block_on: [FAIL, INSUFFICIENT_EVIDENCE, MANUAL_REVIEW]
rules:
- {id: accuracy-floor, metric: accuracy, min: 0.75}
- {id: recall-floor, metric: recall, min: 0.60}
- {id: precision-floor, metric: precision, min: 0.60}Aturan lolos ketika batas bawah interval melampaui batas itu, gagal ketika batas atasnya di bawahnya, dan selain itu berstatus INSUFFICIENT_EVIDENCE.
Jalankan
cd binary
oloproof runDipangkas:
Run run_... [DECIDED/COMPLETE]
Gate: ALLOW (exit 0)
│ accuracy-floor │ accuracy │ PASS │ lower_bound_meets_minimum │
│ recall-floor │ recall │ PASS │ lower_bound_meets_minimum │
│ precision-floor │ precision │ PASS │ lower_bound_meets_minimum │
│ accuracy │ 88.5% │ [83.2%, 92.6%] │ 177 / 200 observed · 0 missing · 0 excluded │
│ recall │ 81.2% │ [69.5%, 90.0%] │ 52 / 64 observed · 0 missing · 136 excluded │
│ precision │ 82.5% │ [70.9%, 91.0%] │ 52 / 63 observed · 0 missing · 137 excluded │
│ brier │ 0.120 │ [0.094, 0.154] │ mean of 200 observed · 0 missing · 0 excluded │
│ log_loss │ 0.389 │ [0.323, 0.499] │ mean of 200 observed · 0 missing · 0 excluded │
│ roc_auc │ 92.3% │ [69.3%, 100.0%] │ roc_auc over 64 positive · 136 negative · 0 missing · 0 excluded │
│ pr_auc │ 86.5% │ │ average_precision over 64 positive · 136 negative · 0 missing · 0 excluded │Cara membacanya:
- Gate: ALLOW (exit 0) berarti tidak ada aturan yang mencapai status yang diblokir kebijakan. Itu bukan klaim bahwa model baik di luar tiga batas bawah yang Anda tulis.
- Hitungan excluded adalah penyebut yang sedang bekerja: recall diukur atas 64 akun yang churn, sehingga 136 yang tidak churn dikecualikan darinya, bukan dihitung sebagai kegagalan.
- pr_auc tidak memiliki interval. Pada 200 baris mesin menahan batas yang tidak dapat didukungnya; aturan atasnya akan berstatus INSUFFICIENT_EVIDENCE dengan interval_unavailable.
Di bawah metrik, keluaran yang sama mencetak hitungan konfusi, tabel kalibrasi, dan sapuan ambang batas:
│ actually positive │ 52 │ 12 │
│ actually negative │ 11 │ 125 │
│ 0.2-0.3 │ 26.7% │ 0.0% │ 34 rows │
│ 0.5-0.6 │ 53.4% │ 81.0% │ 21 rows │
│ 0.3 │ 57.4% │ 96.9% │ 62/108 predicted positive · 62/64 actual positive │
│ 0.4 │ 62.6% │ 89.1% │ 57/91 predicted positive · 57/64 actual positive │
│ 0.5 │ 82.5% │ 81.2% │ 52/63 predicted positive · 52/64 actual positive │
│ 0.6 │ 83.3% │ 54.7% │ 35/42 predicted positive · 35/64 actual positive │
│ 0.7 │ 100.0% │ 37.5% │ 24/24 predicted positive · 24/64 actual positive │Hitungan bukan tingkat dan tidak ada aturan yang boleh menyebutnya. Baris kalibrasi menyatakan bahwa probabilitas model meleset: pada pita 0.2 sampai 0.3 model mengklaim sekitar satu dari empat akan churn dan tidak satu pun dari 34 yang churn. Sapuannya berjudul Thresholds (exploratory; recommends nothing): sapuan itu menunjukkan apa yang akan diukur setiap ambang potong dan menyerahkan pilihannya kepada Anda, karena hanya Anda yang tahu berapa biaya satu pelanggan churn yang terlewat dibandingkan satu panggilan retensi yang sia-sia.
Periksa kegagalannya
oloproof inspect RUN_ID --failures --limit 523 of 200 cases failed, errored or did not finish
account_032
output: {"label": false, "score": 0.07}
accuracy: failed
recall: failed
account_037
output: {"label": false, "score": 0.37}
accuracy: failed
recall: failed
...RUN_ID adalah id pada baris pertama keluaran eksekusi. oloproof inspect RUN_ID --case account_037 menampilkan input, nilai yang diharapkan, keluaran, dan setiap penilaian satu kasus. Beberapa pelanggan churn yang terlewat berada tepat di bawah ambang potong 0.5 (0.37, 0.43), yang sudah diisyaratkan baris 0.4 pada sapuan.
Tindakan berikutnya yang bermakna mengikuti apa yang Anda lihat, bukan gerbang: di sini kesalahan berkumpul di bawah ambang potong, sehingga kandidat mencoba ambang yang lebih rendah. Seandainya itu kesalahan yang yakin (0.07), tindakan berikutnya ada pada fitur model, dan tidak ada ambang potong yang akan membantu.
Perubahan kandidat, dan perbandingannya
binary/candidate.yaml adalah oloproof.yaml dengan dua baris diubah:
system:
name: churn-model
version: candidate-cutoff-0.4
callable: app:run_candidateoloproof run --config candidate.yamlGate: BLOCK (exit 3)
│ accuracy-floor │ accuracy │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold │
│ recall-floor │ recall │ PASS │ lower_bound_meets_minimum │
│ precision-floor │ precision │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold │
│ accuracy │ 79.5% │ [73.2%, 84.9%] │ 159 / 200 observed · 0 missing · 0 excluded │
│ recall │ 89.1% │ [78.7%, 95.5%] │ 57 / 64 observed · 0 missing · 136 excluded │
│ precision │ 62.6% │ [51.8%, 72.6%] │ 57 / 91 observed · 0 missing · 109 excluded │Persis baris 0.4 pada sapuan: recall naik, presisi turun. Keluar 3 adalah INSUFFICIENT_EVIDENCE, bukan FAIL: batas-batas bawah berada di dalam interval, sehingga 200 akun tidak dapat menyatakan di sisi mana kandidat berada. Skornya tidak berubah, sehingga Brier, log loss, dan ROC-AUC identik.
Sekarang bandingkan kedua eksekusi kasus demi kasus. binary/comparison.yaml memuat aturan perbandingan:
version: 1
confidence_level: 0.95
block_on: [FAIL, INSUFFICIENT_EVIDENCE, MANUAL_REVIEW]
rules:
- {id: recall-no-worse, kind: non_inferiority, metric: recall, margin: 0.05}
- {id: accuracy-no-worse, kind: non_inferiority, metric: accuracy, margin: 0.05}oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy comparison.yamlComparison sha256:... of run_... against run_... · 200 paired cases
accuracy: -9.0 points [-17.9, -1.4] · 200 paired · 0 missing · 0 excluded
recall: +7.8 points [-2.8, +21.9] · 64 paired · 0 missing · 136 excluded
excluded 136: not_a_positive_case
precision: +0.0 points [-8.3, +8.3] · 63 paired · 0 missing · 137 excluded
excluded 137: not_predicted_positive
...
Decisions
recall-no-worse recall non-inferiority, margin 5.0 points PASS lower_bound_above_margin
accuracy-no-worse accuracy non-inferiority, margin 5.0 points INSUFFICIENT_EVIDENCE interval_overlaps_margin
no sample size would make this PASS: the difference itself (-9.0 points) is outside the margin, so more cases would move it toward FAIL
Gate: BLOCK (exit 3)Baca baris presisi dengan cermat. Presisi kandidat sendiri turun dari 82.5% menjadi 62.6%, tetapi selisih berpasangannya +0.0 atas 63 pasangan. Perbandingan memasangkan baris: selisih presisi hanya diukur atas akun yang ditandai oleh kedua model, dan pada 63 akun itu keduanya benar. Ke-28 akun tambahan yang ditandai kandidat, 23 di antaranya alarm palsu, berada di luar kumpulan itu. Itulah sebabnya comparison.yaml menjaga akurasi alih-alih presisi untuk perubahan ambang potong; Aturan perbandingan memuat jenis-jenis aturannya.
Keputusannya adalah bagian yang berguna: recall terbukti tidak lebih buruk, dan akurasi tidak dapat dibuktikan berada dalam lima poin; baris saran menyatakan bahwa lebih banyak data akan mendorongnya ke arah FAIL. Apakah menukar sembilan poin akurasi dengan delapan poin recall sepadan adalah keputusan bisnis yang telah dibuat terlihat oleh gerbang.
Bagian 2: classifier multikelas, satu kelas sekaligus
multiclass/app.py merutekan tiket dukungan ke salah satu dari tiga antrean, dan memiliki satu cacat yang disengaja: setiap tiket yang dikirim dari aplikasi seluler masuk ke technical.
@system(name="ticket-router", version="baseline")
def route(ticket):
if ticket["channel"] == "app":
return {"queue": "technical"}
return {"queue": classify(str(ticket["subject"]))}Sebuah kasus:
{"expected": {"queue": "billing"}, "id": "ticket_000", "input": {"channel": "email", "subject": "update the card on file"}, "metadata": {"channel": "email"}}Tidak ada metrik multikelas yang dapat diaktifkan. Setiap kelas mendapat blok binernya sendiri: recall untuk billing adalah recall biner yang kelas positifnya billing. multiclass/oloproof.yaml:
evaluators:
- {type: predictive_correct, criterion: accuracy, field: queue, expected_field: queue}
- {type: predictive_recall, criterion: recall_billing, field: queue, expected_field: queue, positive: billing}
- {type: predictive_precision, criterion: precision_billing, field: queue, expected_field: queue, positive: billing}
- {type: predictive_recall, criterion: recall_technical, field: queue, expected_field: queue, positive: technical}
- {type: predictive_precision, criterion: precision_technical, field: queue, expected_field: queue, positive: technical}
- {type: predictive_recall, criterion: recall_account, field: queue, expected_field: queue, positive: account}
- {type: predictive_precision, criterion: precision_account, field: queue, expected_field: queue, positive: account}
slices: [metadata.channel]Oloproof tidak menghitung rata-rata makro atau mikro atas semua ini. Jika Anda memerlukannya, itu angka yang Anda turunkan sendiri dari hitungan per kelas, dan tidak ada aturan yang dapat menjadi gerbang atasnya. Kebijakan menetapkan batas bawah pada kelas-kelas yang penting, karena router bisa akurat secara keseluruhan namun kehilangan satu antrean:
rules:
- {id: billing-recall-floor, metric: recall_billing, min: 0.80}
- {id: account-recall-floor, metric: recall_account, min: 0.80}
- {id: technical-precision-floor, metric: precision_technical, min: 0.80}cd ../multiclass
oloproof runGate: BLOCK (exit 1)
│ billing-recall-floor │ recall_billing │ FAIL │ upper_bound_below_minimum │
│ account-recall-floor │ recall_account │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold │
│ technical-precision-floor │ precision_technical │ FAIL │ upper_bound_below_minimum │
│ accuracy │ 81.3% │ [74.1%, 87.3%] │ 122 / 150 observed · 0 missing · 0 excluded │
│ recall_billing │ 66.0% │ [51.2%, 78.8%] │ 33 / 50 observed · 0 missing · 100 excluded │
│ precision_billing │ 100.0% │ [89.4%, 100.0%] │ 33 / 33 observed · 0 missing · 117 excluded │
│ recall_technical │ 100.0% │ [92.8%, 100.0%] │ 50 / 50 observed · 0 missing · 100 excluded │
│ precision_technical │ 64.1% │ [52.4%, 74.7%] │ 50 / 78 observed · 0 missing · 72 excluded │
│ recall_account │ 78.0% │ [64.0%, 88.5%] │ 39 / 50 observed · 0 missing · 100 excluded │
│ precision_account │ 100.0% │ [90.9%, 100.0%] │ 39 / 39 observed · 0 missing · 111 excluded │Keluar 1 berarti setidaknya satu aturan FAIL. Setiap kelas memiliki penyebutnya sendiri: 78 tiket disebut technical, sehingga itulah penyebut presisi untuk technical. Tabel irisan menunjuk ke penyebabnya; irisan bersifat eksploratif dan tidak pernah menjadi gerbang, tetapi irisan yang ditandai adalah petunjuk yang layak dibaca:
│ metadata.channel=app │ accuracy │ 42.9% │ [28.8%, 57.8%] │ 21 / 49 observed · ... │ marked (p 0.0001) │oloproof inspect RUN_ID --failures --limit 228 of 150 cases failed, errored or did not finish
ticket_011
output: {"queue": "technical"}
accuracy: failed
precision_technical: failed
recall_account: failed
...Kandidat (route_candidate, dijalankan dengan oloproof run --config candidate.yaml) menghapus jalan pintas kanal itu. Pada data sintetis ini kandidat merutekan setiap tiket dengan benar dan gerbang mengizinkan:
Gate: ALLOW (exit 0)
│ billing-recall-floor │ recall_billing │ PASS │ lower_bound_meets_minimum │
│ account-recall-floor │ recall_account │ PASS │ lower_bound_meets_minimum │
│ technical-precision-floor │ precision_technical │ PASS │ lower_bound_meets_minimum │oloproof compare bekerja di sini persis seperti di Bagian 1, satu selisih per metrik kelas.
Bagian 3: regressor, dinilai dengan galat absolut
regression/app.py memperkirakan hari pengiriman dan mengabaikan apakah barangnya tersedia:
@system(name="delivery-estimator", version="baseline")
def estimate(order):
return {"days": round(base_days(order), 1)}Sebuah kasus, dengan kebenaran berupa angka:
{"expected": {"days": 11}, "id": "order_000", "input": {"distance_km": 468, "express": false, "in_stock": false}, "metadata": {"in_stock": false}}Satu-satunya evaluator regresi adalah galat absolut, dan evaluator ini memerlukan rentang tempat setiap target berada. Galat absolut adalah rata-rata terbatas yang intervalnya hanya berlaku di dalam rentang itu, sehingga rentang itu dideklarasikan, tidak pernah diberi nilai bawaan. Pengiriman di sini memakan waktu 0 sampai 20 hari:
evaluators:
- type: predictive_absolute_error
criterion: days_error
field: days
expected_field: days
target_range: [0, 20]
slices: [metadata.in_stock]Kebijakannya adalah anggaran, aturan max:: lolos ketika batas atas interval berada pada atau di bawahnya.
rules:
- {id: error-budget, metric: days_error, max: 2.0}cd ../regression
oloproof runGate: BLOCK (exit 1)
│ error-budget │ days_error │ FAIL │ lower_bound_above_maximum │
│ days_error │ 2.66 │ [2.01, 3.57] │ mean of 120 observed · 0 missing · 0 excluded │
│ metadata.in_stock=false │ days_error │ 5.18 │ [4.60, 6.65] │ mean of 53 observed · ... │
│ metadata.in_stock=true │ days_error │ 0.67 │ [0.51, 2.19] │ mean of 67 observed · ... │FAIL karena bahkan batas bawah interval berada di atas anggaran dua hari. Evaluator skor tidak memiliki lolos atau gagal per kasus, sehingga oloproof inspect RUN_ID --failures tidak mencantumkan apa pun; bacalah sebuah kasus:
oloproof inspect RUN_ID --case order_000output: {
"days": 6.1
}
judgments:
days_error: score 4.9Irisan menunjukkan ke mana harus melihat: pesanan yang stoknya habis meleset lima hari. Kandidat (estimate_candidate) menambahkan lima hari untuk barang yang stoknya habis:
oloproof run --config candidate.yamlGate: ALLOW (exit 0)
│ error-budget │ days_error │ PASS │ upper_bound_meets_maximum │
│ days_error │ 0.70 │ [0.56, 1.57] │ mean of 120 observed · 0 missing · 0 excluded │Pemecahan masalah
| Gejala | Penyebab dan perbaikan |
|---|---|
| Configuration error: evaluator 'recall' counts 'churned' as the positive class, and no case's 'label' is 'churned' | positive: menyebut nilai yang tidak dimiliki kasus mana pun. Gunakan nilai persis seperti yang muncul di bawah expected, termasuk true dibandingkan "true". |
| release rule ... refers to unknown metric 'false_positives' | Hitungan konfusi bukan metrik. Jadikan recall atau presisi sebagai gerbang. |
| Evaluator regresi ditolak sebelum eksekusi | target_range tidak ada atau kosong. Deklarasikan rentang yang benar-benar dapat diambil target; rentang yang lebih lebar memberi interval yang lebih lebar. |
| Aturan peringkat berstatus INSUFFICIENT_EVIDENCE (interval_unavailable) | Suite terlalu kecil untuk interval statistik itu, biasanya pr_auc. Jadikan roc_auc sebagai gerbang, atau tambahkan kasus. |
| Kandidat melaporkan angka baseline | Kedua eksekusi berbagi version, sehingga prediksi yang di-cache dipakai ulang. Beri setiap perubahan versinya sendiri. |
| Sebuah kasus missing alih-alih salah | Fungsi Anda memunculkan exception, atau field yang dibaca evaluator tidak ada atau bukan angka. oloproof inspect RUN_ID --case ID menampilkan error-nya. |
Keterbatasan
- Tidak ada ambang batas yang direkomendasikan. Sapuan melaporkan apa yang akan diukur oleh setiap ambang potong yang dideklarasikan.
- Tidak ada metrik rata-rata makro atau mikro untuk multikelas, dan tidak ada dukungan multi-label selain satu blok per label.
- Regresi hanya berupa galat absolut dalam target_range yang dideklarasikan: tidak ada galat kuadrat, R kuadrat, atau galat tanpa batas.
- Kalibrasi ditampilkan sebagai tabel, tidak menjadi gerbang dan tidak dikoreksi.
- Selisih presisi berpasangan hanya mencakup baris yang ditandai oleh kedua model, seperti yang ditunjukkan Bagian 1.
- Contoh-contohnya deterministik dan sintetis. Keputusannya menunjukkan mekanismenya, bukan perilaku model sungguhan pada data sungguhan.
Langkah selanjutnya
- Classifier dan regressor adalah referensi field demi field.
- Membandingkan kandidat dengan baseline dan Aturan perbandingan membahas alur kerja perbandingan.
- Irisan membahas pita confidence: dan dukungan irisan.
- Gerbang CI mencantumkan kode keluar.