xxxxxxxxxx
263
let dataPoints = [];
let slider_c, slider_m;
let checkbox_line, checkbox_error, checkbox_costFunction;
let hypothesisCanvas, costFunctionCanvas;
let m_range = [-5, 5];
let minX, minY, maxX, maxY;
let maxVal;
let actual_c = 100;
let actual_m = 0.2;
let estimated_c = actual_c;
let estimated_m = 5;
const randomRange = 20;
const numberOfPoints = 100;
function setup() {
createCanvas(windowWidth, windowHeight);
costFunctionCanvas = createGraphics(width / 2 - 100, height / 2 - 100);
actual_c = random(100);
actual_m = random(2);
generatePoints();
[minX, minY] = costFunction(m_range[0], actual_c);
[maxX, maxY] = costFunction(m_range[1], actual_c);
maxVal = max(minY, maxY);
// slider_c = createSlider(-height / 2, height / 2, estimated_c, 0.1);
// slider_c.value();
// slider_c.position(10, 90);
// slider_c.size(height / 2);
// slider_m = createSlider(...m_range, estimated_m, 0.01);
// slider_m.position(10, 140);
// slider_m.size(height / 2);
checkbox_line = createCheckbox();
checkbox_line.position(150, 250);
checkbox_error = createCheckbox();
checkbox_error.position(150, 280);
checkbox_costFunction = createCheckbox();
checkbox_costFunction.position(250, 310);
frameRate(10);
}
function draw() {
background(29, 43, 83);
//
noStroke();
fill(200);
textSize(20);
text("Formula: hθ(x) = θ0 + (θ1 * x)", 10, 30);
//
text("θ0: " + round(estimated_c, 2), 10, 80);
//
text("θ1: " + round(estimated_m, 2), 10, 130);
//
text(
`Hypothesis: hθ(x) = (${round(estimated_m, 2)} * x) + ${round(
estimated_c,
2
)}`,
10,
200
);
//
text(
// `Error: J(θ0,θ1) = ${int(costFunction(slider_m.value(), slider_c.value())[1])}`,
// `Error: J(θ0,θ1) = ${int(costFunction(estimated_m, actual_c)[1])}`,
`Error: J(θ0,θ1) = ${int(costFunction(estimated_m, estimated_c)[1])}`,
10,
230
);
text("Hide Line", 10, 265);
text("Hide Error", 10, 295);
text("Hide Cost Function Graph", 10, 325);
translate(width / 2, height / 2);
stroke(200);
strokeWeight(1);
line(-width / 2, 0, width / 2, 0);
line(0, -height / 2, 0, height / 2);
for (let pt of dataPoints) {
showError(pt);
// showErrorSquare(...pt);
showPoints(pt);
}
trainModel();
showPredictiveLine(400);
showCostFunctionGraph();
}
function showError(x, y) {
if (checkbox_error.checked()) {
return;
}
let [px, py] = linearFunc(x);
strokeWeight(2);
stroke(255, 0, 77);
line(x, y, px, py);
}
function showErrorSquare(x, y) {
if (checkbox_error.checked()) {
return;
}
// let [px, py] = linearFunc(x);
let [px, py] = costFunction(estimated_m, actual_c);
strokeWeight(2);
fill(255, 0, 77,100);
rect(x, y,px-x,py-y)
}
function showPredictiveLine(lineRange) {
if (checkbox_line.checked()) {
return;
}
let [px1, py1] = linearFunc(-lineRange);
let [px2, py2] = linearFunc(lineRange);
stroke(200);
strokeWeight(2);
line(px1, py1, px2, py2);
}
function generatePoints() {
const range = [-400, 400];
for (let i = 0; i < numberOfPoints; i++) {
dataPoints.push(mirror(linearRand(range)));
}
}
function showPoints(x, y) {
stroke(250, 239, 93);
strokeWeight(10);
point(x, y);
}
function linearRand(range) {
// y = mx + c
x = int(random(range));
y = actual_m * x + actual_c;
y = y + int(random(-randomRange, randomRange));
return [x, y];
}
function linearFunc(x) {
// y = mx + c
// estimated_m = slider_m.value();
// estimated_c = slider_c.value();
y = estimated_m * x + estimated_c;
return mirror(x, y);
}
function mirror(x, y) {
return [x, -y];
}
let noiseSeed = 22;
let n = 0;
let numStripes = 6;
function showCostFunctionGraph() {
if (checkbox_costFunction.checked()) {
return;
}
image(costFunctionCanvas, 50, 50);
c = costFunctionCanvas;
c.background(10);
c.push();
c.translate(c.width / 2, c.height / 2);
c.stroke(100, 100, 240);
c.strokeWeight(1);
c.line(-c.width / 2, 0, c.width / 2, 0);
c.line(0, -c.height / 2, 0, c.height / 2);
showCurve();
showCPoint();
c.pop();
}
function showCPoint() {
c = costFunctionCanvas;
let [cx, cy] = costFunction(estimated_m, actual_c);
// let [cx, cy] = costFunction(slider_m.value(), actual_c);
// let [cx, cy] = costFunction(slider_m.value(), slider_c.value());
cx = map(cx, m_range, -c.width / 2, c.width / 2);
cy = map(cy, -10000, -maxVal, 0, c.height / 2);
c.stroke(250, 239, 93);
c.strokeWeight(10);
c.point(cx, cy);
}
function showCurve() {
c = costFunctionCanvas;
let points = 100;
let d = m_range[1] - m_range[0];
let interval = d / points;
let m = m_range[0];
c.noFill(255, 1);
c.beginShape();
for (let i = 0; i < 100; i++) {
let [cx, cy] = costFunction(m, estimated_c);
// let [cx, cy] = costFunction(m, slider_c.value());
// let [cx, cy] = costFunction(m, actual_c);
cx = map(cx, m_range, -c.width / 2, c.width / 2);
cy = map(cy, -10000, -maxVal, 0, c.height / 2);
c.vertex(cx, cy);
m += interval;
}
c.endShape();
}
function costFunction(m, c) {
let totalError = 0;
for (let [x, y] of dataPoints) {
let [px, py] = linearFuncErr(x, m, c);
totalError += pow(py - y, 2);
}
return [m, (1 / (2 * dataPoints.length)) * totalError];
}
function linearFuncErr(x, m, c) {
y = m * x + c;
return mirror(x, y);
}
function trainModel() {
let learning_rate_c = 0.05;
let learning_rate_m = 0.000001;
let temp_c =
estimated_c +
learning_rate_c * change_in_error(estimated_m, estimated_c, false);
let temp_m =
estimated_m +
learning_rate_m * change_in_error(estimated_m, estimated_c, true);
estimated_c = temp_c
estimated_m = temp_m
}
function change_in_error(m, c, xi = false) {
let totalError = 0;
for (let [x, y] of dataPoints) {
let [px, py] = linearFuncErr(x, m, c);
totalError += (py - y) * (xi ? px : 1);
}
return (2 / dataPoints.length) * totalError;
}