abril4416
Add Gradio hub with linear and logistic regression interfaces
c745dff
Raw
History Blame Contribute Delete
4.84 kB
const canvas = document.getElementById("simplePlot");
const ctx = canvas.getContext("2d");
const zSlider = document.getElementById("z");
const zValue = document.getElementById("zValue");
const showHalf = document.getElementById("showHalf");
const showFormula = document.getElementById("showFormula");
const resetBtn = document.getElementById("resetSimple");
const animateBtn = document.getElementById("animateSimple");
const stats = document.getElementById("simpleStats");
const MARGIN = { left: 72, right: 24, top: 24, bottom: 58 };
const Z_MIN = -10;
const Z_MAX = 10;
let timer = null;
let direction = 1;
function sigmoid(z) {
return 1 / (1 + Math.exp(-z));
}
function zToX(z) {
const width = canvas.width - MARGIN.left - MARGIN.right;
return MARGIN.left + ((z - Z_MIN) / (Z_MAX - Z_MIN)) * width;
}
function yToCanvas(y) {
const height = canvas.height - MARGIN.top - MARGIN.bottom;
return canvas.height - MARGIN.bottom - y * height;
}
function drawAxes() {
const left = MARGIN.left;
const right = canvas.width - MARGIN.right;
const top = MARGIN.top;
const bottom = canvas.height - MARGIN.bottom;
ctx.strokeStyle = "#c9d9df";
ctx.lineWidth = 1;
for (let z = -10; z <= 10; z += 2) {
const x = zToX(z);
ctx.beginPath();
ctx.moveTo(x, top);
ctx.lineTo(x, bottom);
ctx.stroke();
}
for (let y = 0; y <= 1.001; y += 0.1) {
const py = yToCanvas(y);
ctx.beginPath();
ctx.moveTo(left, py);
ctx.lineTo(right, py);
ctx.stroke();
}
ctx.strokeStyle = "#14343f";
ctx.lineWidth = 1.4;
ctx.beginPath();
ctx.moveTo(left, yToCanvas(0));
ctx.lineTo(right, yToCanvas(0));
ctx.stroke();
ctx.beginPath();
ctx.moveTo(zToX(0), top);
ctx.lineTo(zToX(0), bottom);
ctx.stroke();
ctx.fillStyle = "#14343f";
ctx.font = "13px 'Avenir Next', sans-serif";
for (let z = -10; z <= 10; z += 2) {
ctx.fillText(String(z), zToX(z) - 8, yToCanvas(0) + 19);
}
for (let y = 0; y <= 1.001; y += 0.2) {
ctx.fillText(y.toFixed(1), left - 40, yToCanvas(y) + 4);
}
ctx.fillText("z", right - 12, yToCanvas(0) + 38);
ctx.fillText("y", zToX(0) + 12, top + 12);
}
function drawSigmoid() {
ctx.strokeStyle = "#0a8f7b";
ctx.lineWidth = 3;
ctx.beginPath();
const steps = 600;
for (let i = 0; i <= steps; i += 1) {
const z = Z_MIN + (i / steps) * (Z_MAX - Z_MIN);
const y = sigmoid(z);
const x = zToX(z);
const py = yToCanvas(y);
if (i === 0) ctx.moveTo(x, py);
else ctx.lineTo(x, py);
}
ctx.stroke();
}
function drawHalfLine() {
ctx.strokeStyle = "#d8534f";
ctx.lineWidth = 1.3;
ctx.setLineDash([7, 5]);
ctx.beginPath();
ctx.moveTo(MARGIN.left, yToCanvas(0.5));
ctx.lineTo(canvas.width - MARGIN.right, yToCanvas(0.5));
ctx.stroke();
ctx.setLineDash([]);
}
function drawProbe(z) {
const y = sigmoid(z);
const px = zToX(z);
const py = yToCanvas(y);
ctx.strokeStyle = "#14343f";
ctx.setLineDash([4, 4]);
ctx.beginPath();
ctx.moveTo(px, yToCanvas(0));
ctx.lineTo(px, py);
ctx.stroke();
ctx.setLineDash([]);
ctx.fillStyle = "#14343f";
ctx.beginPath();
ctx.arc(px, py, 6, 0, Math.PI * 2);
ctx.fill();
if (showFormula.checked) {
ctx.font = "13px 'Avenir Next', sans-serif";
ctx.fillText(`z=${z.toFixed(2)}, y=${y.toFixed(4)}`, px + 8, py - 8);
}
}
function renderStats(z) {
const y = sigmoid(z);
const inverse = Math.log(y / (1 - y));
stats.innerHTML = `
<span>Function: y = 1 / (1 + np.exp(-z))</span>
<span>Current z: ${z.toFixed(2)}</span>
<span>Output y: ${y.toFixed(4)}</span>
<span>Cross-check logit(y): ${inverse.toFixed(4)}</span>
`;
}
function render() {
const z = Number(zSlider.value);
zValue.textContent = z.toFixed(2);
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawAxes();
drawSigmoid();
if (showHalf.checked) drawHalfLine();
drawProbe(z);
renderStats(z);
}
function stopAnimation() {
if (timer) {
clearInterval(timer);
timer = null;
}
animateBtn.textContent = "Animate z";
}
function startAnimation() {
if (timer) return;
animateBtn.textContent = "Stop Animation";
timer = setInterval(() => {
let next = Number(zSlider.value) + direction * 0.18;
if (next >= Z_MAX) {
next = Z_MAX;
direction = -1;
} else if (next <= Z_MIN) {
next = Z_MIN;
direction = 1;
}
zSlider.value = next;
render();
}, 30);
}
function reset() {
zSlider.value = 0;
showHalf.checked = true;
showFormula.checked = true;
stopAnimation();
render();
}
zSlider.addEventListener("input", render);
showHalf.addEventListener("input", render);
showFormula.addEventListener("input", render);
resetBtn.addEventListener("click", reset);
animateBtn.addEventListener("click", () => {
if (timer) stopAnimation();
else startAnimation();
});
reset();