Show dataset YOLO training curves

This commit is contained in:
2026-06-30 15:35:25 +08:00
parent b60fcc5112
commit 90dccbea0e
5 changed files with 61 additions and 4 deletions

View File

@@ -55,7 +55,7 @@ for the `yolo.train_custom` task. The selected upload dataset also exposes
direct YOLO custom train, predict, and heatmap actions; custom outputs are
written under `var/custom_yolo_runs` and are scanned by the results dashboard.
When a dataset is selected, the dataset panel shows its custom YOLO `best.pt`,
prediction previews, heatmap previews, and detected training curves.
prediction previews, heatmap previews, and inline training curve previews.
Segmentation previews, YOLO heatmaps, and loss/metric artifacts are grouped on
the results dashboard, and YOLO-style `results.csv` files are parsed into
lightweight training curves.

View File

@@ -44,7 +44,11 @@ def evaluate_project() -> dict:
"upload_ui": "uploadDatasetFiles" in frontend_text and "labels" in frontend_text and "masks" in frontend_text,
"dataset_quality_ui": "DatasetQuality" in frontend_text and "generateSelectedYoloYaml" in frontend_text,
"uploaded_yolo_workflow_ui": "startSelectedYoloTrain" in frontend_text and "startSelectedYoloPredict" in frontend_text and "startSelectedYoloHeatmap" in frontend_text,
"dataset_yolo_outputs_ui": "DatasetYoloOutputs" in frontend_text and "selectedYoloOutputs" in frontend_text and "BEST.PT READY" in frontend_text,
"dataset_yolo_outputs_ui": "DatasetYoloOutputs" in frontend_text
and "selectedYoloOutputs" in frontend_text
and "BEST.PT READY" in frontend_text
and "datasetOutputCurve" in frontend_text
and "MiniCurvePlot" in frontend_text,
"loss_result_ui": "loss" in frontend_text.lower() and "heatmap" in frontend_text.lower() and "CurvePanel" in frontend_text,
"job_progress_ui": "JobProgressBar" in frontend_text and "progressTrack" in frontend_text,
"runtime_readiness_ui": "runtimeReadiness" in frontend_text and "环境就绪" in frontend_text,

View File

@@ -216,8 +216,8 @@ def api_results() -> list[dict]:
@app.get("/api/results/curves")
def api_result_curves() -> list[dict]:
return scan_training_curves()
def api_result_curves(limit: int = 100) -> list[dict]:
return scan_training_curves(limit=limit)
@app.get("/api/artifacts/{artifact_path:path}")

View File

@@ -1289,6 +1289,8 @@ function DatasetQuality({ validation }: { validation: DatasetValidation }) {
function DatasetYoloOutputs({ dataset, outputs }: { dataset: UploadedDataset; outputs: DatasetYoloOutputsPayload }) {
const previewItems = [...outputs.heatmaps.slice(0, 3), ...outputs.predictions.slice(0, 3)].slice(0, 6);
const primaryCurve = outputs.curves[0];
const curveSeries = primaryCurve?.series.slice(0, 4) ?? [];
return (
<div className="datasetOutputBox">
<div className="qualityHead">
@@ -1315,6 +1317,15 @@ function DatasetYoloOutputs({ dataset, outputs }: { dataset: UploadedDataset; ou
</a>
))}
</div>
{primaryCurve && !!curveSeries.length && (
<div className="datasetOutputCurve">
<div>
<strong>{primaryCurve.name}</strong>
<span>{primaryCurve.row_count} epochs · {primaryCurve.family}</span>
</div>
<MiniCurvePlot series={curveSeries} />
</div>
)}
{!!previewItems.length && (
<div className="datasetOutputPreview">
{previewItems.map((item) => (

View File

@@ -853,6 +853,48 @@ textarea {
white-space: nowrap;
}
.datasetOutputCurve {
display: grid;
gap: 8px;
padding: 8px;
border-radius: 6px;
border: 1px solid var(--line);
background: #101310;
}
.datasetOutputCurve > div {
min-width: 0;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.datasetOutputCurve strong,
.datasetOutputCurve span {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.datasetOutputCurve strong {
flex: 1 1 auto;
}
.datasetOutputCurve span {
flex: 0 1 auto;
color: var(--muted);
font-size: 11px;
}
.datasetOutputCurve .curveSvg,
.datasetOutputCurve .curveEmpty {
min-height: 96px;
aspect-ratio: 2.6 / 1;
border-radius: 6px;
}
.datasetOutputPreview {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));