TIF_E41253385/web_slearn/src/components/TrainingDetails.jsx

138 lines
3.9 KiB
JavaScript

const rate = (v) => `${(v * 100).toFixed(2).replace(".", ",")}%`;
export function SkippedRows({ audit, legacy = false, status = "completed" }) {
if (!audit) {
return legacy
? <p>Rincian baris yang dilewati belum dicatat untuk versi lama ini.</p>
: null;
}
return (
<div className="models-audit">
<p>
<b>
{audit.uploaded_rows} diunggah → {audit.accepted_rows} diterima →{" "}
{audit.skipped_rows.length} dilewati.
</b>
</p>
{audit.selected_column && (
<p>
Kolom yang digunakan: <b>{audit.selected_column}</b>
</p>
)}
<p>
{status === "completed" && audit.accepted_rows > 0
? `Data latih: ${audit.training_before} sebelum penambahan → ${audit.training_before + audit.accepted_rows} setelah training berhasil.`
: `Data latih tetap ${audit.training_before}.`}
</p>
{!!audit.skipped_rows.length && (
<details className="models-skipped-details">
<summary>
Lihat Data yang Dilewati ({audit.skipped_rows.length})
</summary>
<p className="models-skip-note">
Nomor baris adalah urutan record CSV, termasuk judul kolom
sebagai baris 1. Ulasan dengan baris baru di dalam tanda
kutip dihitung satu record.
</p>
<div className="models-table models-skipped-scroll">
<table className="models-skipped-table">
<thead>
<tr>
<th>Baris CSV</th>
<th>Ulasan</th>
<th>Alasan dilewati</th>
</tr>
</thead>
<tbody>
{audit.skipped_rows.map((r) => (
<tr key={r.source_row_number}>
<td>{r.source_row_number}</td>
<td className="models-skipped-text">
{r.text || "(kosong)"}
</td>
<td>
<span className="models-skip-reason">
{r.reason}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
</details>
)}
</div>
);
}
export function VersionComparison({ selected, original }) {
if (!original || selected.version === "v1") {
return (
<p>
Model penelitian awal: {selected.jumlah_data_training} data latih
dan {selected.jumlah_data_testing} data uji.
</p>
);
}
const metrics = [
["Akurasi", m => m.akurasi],
["Precision", m => m.classification_report["weighted avg"].precision],
["Recall", m => m.classification_report["weighted avg"].recall],
["F1-Score", m => m.classification_report["weighted avg"]["f1-score"]]
];
return (
<div>
<h3>Perbandingan dengan model awal v1</h3>
<p>
{selected.jumlah_data_training} data latih. Evaluasi pada{" "}
{selected.jumlah_data_testing} data uji tetap yang sama.
</p>
<div className="models-table">
<table>
<thead>
<tr>
<th>Metrik</th>
<th>v1</th>
<th>{selected.version}</th>
<th>Selisih (poin persentase)</th>
</tr>
</thead>
<tbody>
{metrics.map(([name, get]) => (
<tr key={name}>
<th>{name}</th>
<td>{rate(get(original))}</td>
<td>{rate(get(selected))}</td>
<td>
{((get(selected) - get(original)) * 100).toFixed(2)}
</td>
</tr>
))}
</tbody>
</table>
</div>
<p>
Precision, Recall, dan F1-Score menggunakan weighted average,
yaitu rata-rata yang memperhitungkan jumlah data pada setiap kelas.
</p>
</div>
);
}