my-homelab-configs/apps/demos-static/public/model-drift/model-drift.js

53 lines
1.8 KiB
JavaScript

const canvas = document.getElementById('drift-canvas');
const ctx = canvas.getContext('2d');
let accuracy = Array.from({ length: 44 }, (_, index) => 92 - Math.sin(index / 3) * 2);
let status = 'Model is healthy.';
function draw() {
const width = canvas.width;
const height = canvas.height;
const pad = 28;
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = '#f8fafc';
ctx.fillRect(0, 0, width, height);
ctx.strokeStyle = '#d9e2ec';
for (let i = 0; i < 5; i += 1) {
const y = pad + ((height - pad * 2) / 4) * i;
ctx.beginPath();
ctx.moveTo(pad, y);
ctx.lineTo(width - pad, y);
ctx.stroke();
}
ctx.strokeStyle = '#805ad5';
ctx.lineWidth = 3;
ctx.beginPath();
accuracy.forEach((value, index) => {
const x = pad + (index / Math.max(1, accuracy.length - 1)) * (width - pad * 2);
const y = height - pad - ((value - 40) / 60) * (height - pad * 2);
if (index === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
});
ctx.stroke();
document.getElementById('drift-status').textContent = status;
}
document.getElementById('drift-spike').addEventListener('click', () => {
accuracy = accuracy.map((value, index) => index > 20 ? Math.max(55, value - (index - 18) * 0.9) : value);
status = 'Black Friday traffic spike: feature distribution shifted, accuracy is sliding.';
draw();
});
document.getElementById('drift-corrupt').addEventListener('click', () => {
accuracy = accuracy.map((value, index) => index % 4 === 0 ? Math.max(45, value - 18) : value);
status = 'Corrupted input data: model confidence is having a very bad afternoon.';
draw();
});
document.getElementById('drift-retrain').addEventListener('click', () => {
accuracy = accuracy.map((_, index) => 91 + Math.sin(index / 4) * 3);
status = 'Retrained model: accuracy recovered and everyone pretends this was planned.';
draw();
});
draw();