Skip to content

Instantly share code, notes, and snippets.

@jonahwilliams
Last active April 13, 2017 07:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jonahwilliams/810d8d84278539952369 to your computer and use it in GitHub Desktop.
Save jonahwilliams/810d8d84278539952369 to your computer and use it in GitHub Desktop.
Under-fitting versus Over-fitting
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<style>
.axis {
font: 10px sans-serif;
}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<form>
<label id="label">0 Degree Polynomial</label>
<input type="range" id="points" min="0" max="25" value="0">
</form>
<script src="LinearRegression.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var data = [];
for (var i = 0; i < 20; i++){
var a = 6 * Math.random();
data.push({'x': a,'y': 0.9 * Math.sin(a) + (0.25 * Math.random()) - 0.125});
}
var degree = document.getElementById("points").value;
var newdata = BasisExpand(data, degree);
var params = LinearRegression(newdata);
var smoothed = [];
for (var i = 1; i < 600; i++){
var val = BasisExpand([{'x':(6/600) * i, 'y':0}], degree);
var y = 0.0;
for (var j = 0; j < params.length; j++){
y += params[j][0] * val[0].x[j];
}
smoothed.push({'x':(6/600) * i, 'y': y});
}
var margin = {top: 80, right: 180, bottom: 80, left: 180},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var y = d3.scale.linear()
.domain([-1, 1])
.range([height, 0]);
var x = d3.scale.linear()
.domain([0, 6])
.range([0, width])
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function(d){
return x(d.x);
})
.attr("cy", function(d){
return y(d.y)
})
.style("fill", "black");
svg.append("path")
.datum(smoothed)
.attr("class", "line")
.attr("d", line);
d3.select("#points")
.on("change", function(d){
var degree = document.getElementById("points").value;
d3.select("label")
.text(degree + " Degree Polynomial");
var newdata = BasisExpand(data, degree);
var params = LinearRegression(newdata);
var smoothed = [];
for (var i = 1; i < 100; i++){
var val = BasisExpand([{'x':(6/100) * i, 'y':0}], degree);
var y = 0.0;
for (var j = 0; j < params.length; j++){
y += params[j][0] * val[0].x[j];
}
smoothed.push({'x':(6/100) * i, 'y': y});
}
svg.selectAll(".line")
.datum(smoothed)
.transition()
.attr("class", "line")
.attr("d", line);
})
function BasisExpand(data, degree){
var BasisData = [];
for (var i = 0; i < data.length; i++){
var expanded = {'x':[], 'y': data[i].y};
for (var j = 0; j <= degree; j++){
expanded['x'].push(Math.pow(data[i].x - 3, j));
}
BasisData.push(expanded);
}
return BasisData;
}
</script>
</body>
function LinearRegression(data){
var X = [],
y = [];
for (var i = 0; i < data.length; i ++){
var tempX = [];
for(var j = 0; j < data[0]['x'].length; j++){
tempX.push(data[i]['x'][j]);
}
X.push(tempX);
y.push([data[i].y]);
}
var t = matrixTranspose(X);
var hat = matrixMultiply(matrixMultiply(matrixInvert(matrixMultiply(t, X)), t), y);
return hat;
}
function matrixTranspose(a){
//http://stackoverflow.com/questions/4492678/to-swap-rows-with-columns-of-matrix-in-javascript-or-jquery
return Object.keys(a[0]).map(
function (c) { return a.map(function (r) { return r[c]; }); }
);
}
function matrixMultiply(m1, m2) {
// http://tech.pro/tutorial/1527/matrix-multiplication-in-functional-javascript
//
var result = [];
for (var i = 0; i < m1.length; i++) {
result[i] = [];
for (var j = 0; j < m2[0].length; j++) {
var sum = 0;
for (var k = 0; k < m1[0].length; k++) {
sum += m1[i][k] * m2[k][j];
}
result[i][j] = sum;
}
}
return result;
}
function matrixInvert(M){
// source - http://blog.acipo.com/matrix-inversion-in-javascript/
//
if(M.length !== M[0].length){return;}
var i=0, ii=0, j=0, dim=M.length, e=0, t=0;
var I = [], C = [];
for(i=0; i<dim; i+=1){
I[I.length]=[];
C[C.length]=[];
for(j=0; j<dim; j+=1){
if(i==j){ I[i][j] = 1; }
else{ I[i][j] = 0; }
C[i][j] = M[i][j];
}
}
for(i=0; i<dim; i+=1){
e = C[i][i];
if(e==0){
for(ii=i+1; ii<dim; ii+=1){
if(C[ii][i] != 0){
for(j=0; j<dim; j++){
e = C[i][j];
C[i][j] = C[ii][j];
C[ii][j] = e;
e = I[i][j];
I[i][j] = I[ii][j];
I[ii][j] = e;
}
break;
}
}
e = C[i][i];
if(e==0){return}
}
for(j=0; j<dim; j++){
C[i][j] = C[i][j]/e;
I[i][j] = I[i][j]/e;
}
for(ii=0; ii<dim; ii++){
if(ii==i){continue;}
e = C[ii][i];
for(j=0; j<dim; j++){
C[ii][j] -= e*C[i][j];
I[ii][j] -= e*I[i][j];
}
}
}
return I;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment