Uday's picture
Added model training artifact dashboard and saving artifacts
00d1de8
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CTM Training Dashboard</title>
<style>
:root {
--bg-color: #f4f4f9;
--card-bg: #ffffff;
--text-color: #333;
--accent-color: #4a90e2;
--success-color: #2ecc71;
--font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
body {
font-family: var(--font-family);
background-color: var(--bg-color);
color: var(--text-color);
margin: 0;
padding: 20px;
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
text-align: center;
margin-bottom: 40px;
}
h1 {
color: var(--accent-color);
margin-bottom: 10px;
}
.status-card {
background: var(--card-bg);
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
text-align: center;
}
.metric {
display: flex;
flex-direction: column;
}
.metric-label {
font-size: 0.9em;
color: #666;
}
.metric-value {
font-size: 1.5em;
font-weight: bold;
color: var(--text-color);
}
.plots-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.plot-card {
background: var(--card-bg);
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.plot-card img {
width: 100%;
height: auto;
border-radius: 4px;
}
.artifacts-section {
background: var(--card-bg);
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
text-align: center;
margin-bottom: 30px;
}
.btn {
display: inline-block;
padding: 10px 20px;
background-color: var(--accent-color);
color: white;
text-decoration: none;
border-radius: 5px;
margin: 0 10px;
transition: background-color 0.3s;
}
.btn:hover {
background-color: #357abd;
}
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
margin-top: 20px;
}
.gallery img {
width: 100%;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
footer {
text-align: center;
margin-top: 50px;
color: #888;
font-size: 0.9em;
}
#last-updated {
font-size: 0.8em;
color: #999;
margin-top: 5px;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>CTM Training Dashboard</h1>
<p>Real-time monitoring of Energy-Based Halting Experiment</p>
<div id="last-updated">Waiting for data...</div>
</header>
<div class="status-card" id="metrics-container">
<div class="metric">
<span class="metric-label">Iteration</span>
<span class="metric-value" id="iter">--</span>
</div>
<div class="metric">
<span class="metric-label">Epoch</span>
<span class="metric-value" id="epoch">--</span>
</div>
<div class="metric">
<span class="metric-label">Train Loss</span>
<span class="metric-value" id="train-loss">--</span>
</div>
<div class="metric">
<span class="metric-label">Test Loss</span>
<span class="metric-value" id="test-loss">--</span>
</div>
<div class="metric">
<span class="metric-label">Train Acc</span>
<span class="metric-value" id="train-acc">--</span>
</div>
<div class="metric">
<span class="metric-label">Test Acc</span>
<span class="metric-value" id="test-acc">--</span>
</div>
</div>
<div class="plots-grid">
<div class="plot-card">
<h3>Loss History</h3>
<img
id="loss-plot"
src="logs/scratch/losses.png"
alt="Loss Plot"
onerror="this.src='https://via.placeholder.com/600x400?text=Waiting+for+Plots'"
/>
</div>
<div class="plot-card">
<h3>Accuracy History</h3>
<img
id="acc-plot"
src="logs/scratch/accuracies.png"
alt="Accuracy Plot"
onerror="this.src='https://via.placeholder.com/600x400?text=Waiting+for+Plots'"
/>
</div>
</div>
<div class="artifacts-section">
<h2>Artifacts & Downloads</h2>
<p>Download the latest model checkpoints and full logs.</p>
<a href="logs/scratch/artifacts.zip" class="btn"
>Download All Artifacts (.zip)</a
>
<a href="logs/scratch/checkpoint.pt" class="btn"
>Download Checkpoint (.pt)</a
>
</div>
<div class="artifacts-section">
<h2>Attention Visualization</h2>
<p>Latest generated attention maps from the model.</p>
<div class="gallery" id="gif-gallery">
<!-- GIFs will be injected here -->
<img
src="logs/scratch/0_attention.gif"
onerror="this.style.display='none'"
alt="Attention Map"
/>
</div>
</div>
</div>
<footer>
<p>Continuous Thought Machine Experiment</p>
</footer>
<script>
const LOG_DIR = "logs/scratch";
async function updateDashboard() {
try {
// Fetch status.json
const response = await fetch(
`${LOG_DIR}/status.json?t=${new Date().getTime()}`
);
if (!response.ok) throw new Error("Status file not found");
const data = await response.json();
// Update Metrics
document.getElementById(
"iter"
).textContent = `${data.iteration} / ${data.total_iterations}`;
document.getElementById("epoch").textContent = data.epoch;
document.getElementById("train-loss").textContent = parseFloat(
data.train_loss
).toFixed(4);
document.getElementById("test-loss").textContent = parseFloat(
data.test_loss
).toFixed(4);
// Handle Accuracy (could be array or float)
const formatAcc = (acc) => {
if (Array.isArray(acc)) {
return (acc[acc.length - 1] * 100).toFixed(2) + "%";
}
return (acc * 100).toFixed(2) + "%";
};
document.getElementById("train-acc").textContent = formatAcc(
data.train_accuracy
);
document.getElementById("test-acc").textContent = formatAcc(
data.test_accuracy
);
// Update Timestamp
document.getElementById(
"last-updated"
).textContent = `Last updated: ${new Date().toLocaleTimeString()}`;
// Refresh Images
const timestamp = new Date().getTime();
document.getElementById(
"loss-plot"
).src = `${LOG_DIR}/losses.png?t=${timestamp}`;
document.getElementById(
"acc-plot"
).src = `${LOG_DIR}/accuracies.png?t=${timestamp}`;
// Refresh Gallery (simple approach: try to reload the known gif)
const gallery = document.getElementById("gif-gallery");
gallery.innerHTML = `<img src="${LOG_DIR}/0_attention.gif?t=${timestamp}" onerror="this.style.display='none'" alt="Attention Map">`;
} catch (error) {
console.log("Waiting for training to start...", error);
document.getElementById("last-updated").textContent =
"Waiting for training to start...";
}
}
// Update every 30 seconds
setInterval(updateDashboard, 30000);
// Initial call
updateDashboard();
</script>
</body>
</html>