Skip to content

Commit fc124fe

Browse files
committed
initial make dots app
1 parent 155ff7c commit fc124fe

File tree

6 files changed

+318
-2
lines changed

6 files changed

+318
-2
lines changed

README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,17 @@
1-
# data-space
2-
Machine learning in data space web demo
1+
# Data Space
2+
3+
**Machine learning in data space web demo.**
4+
5+
In the tradition of Tkinter SVM GUI, the purpose of this app is to demonstrate how machine learning model forms are affected by the shape of the underlying dataset. By selecting a dataset or by creating one of your own, you can fit a model to the data and see how the model would make decisions based on the data it has been trained on. Although this is a toy example, hopefully it helps give you the intuition that the machine learning process is a model selection search for the best combination of features, algorithm, and hyperparameter that generalize well in a bounded feature space.
6+
7+
## Getting Started
8+
9+
To run this app locally, first clone the repository and install the requirements:
10+
11+
$ pip install -r requirements.txt
12+
13+
You can then run the Flask app as follows:
14+
15+
$ python3 app.py
16+
17+
This will start a webserver for the app, you can open a browser window at [http://127.0.0.1:5000/](http://127.0.0.1:5000/) to view the application.

app.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env python3
2+
# app
3+
# A quick Flask app to demonstrate Machine Learning decision space.
4+
#
5+
# Author: Benjamin Bengfort <benjamin@bengfort.com>
6+
# Created: Sun Jul 21 06:22:47 2019 -0400
7+
#
8+
# Copyright (C) 2019 Georgetown Data Analytics (CCPE)
9+
# For license information, see LICENSE.txt
10+
#
11+
# ID: app.py [] benjamin@bengfort.com $
12+
13+
"""
14+
A quick Flask app to demonstrate Machine Learning decision space.
15+
"""
16+
17+
##########################################################################
18+
## Imports
19+
##########################################################################
20+
21+
from flask import Flask
22+
from flask import render_template
23+
24+
25+
##########################################################################
26+
## Flask Application Definition
27+
##########################################################################
28+
29+
app = Flask(__name__)
30+
31+
32+
##########################################################################
33+
## Routes
34+
##########################################################################
35+
36+
@app.route('/')
37+
@app.route('/index')
38+
def index():
39+
return render_template('index.html', title='Home')
40+
41+
42+
##########################################################################
43+
## Run the Web App
44+
##########################################################################
45+
46+
if __name__ == "__main__":
47+
app.run()

requirements.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
## Package Dependencies
2+
Flask==1.1.1
3+
gunicorn==19.9.0
4+
numpy==1.16.4
5+
scikit-learn==0.21.2
6+
scipy==1.3.0
7+
8+
## Subdependencies
9+
# Click==7.0
10+
# itsdangerous==1.1.0
11+
# Jinja2==2.10.1
12+
# joblib==0.13.2
13+
# MarkupSafe==1.1.1
14+
# python-dateutil==2.8.0
15+
# six==1.12.0
16+
# sklearn==0.0
17+
# Werkzeug==0.15.5
18+
19+
## Python Dependencies
20+
# pip==19.1.1
21+
# setuptools==41.0.1
22+
# wheel==0.33.4

static/css/dataspace.css

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* Sticky footer styles */
2+
html {
3+
position: relative;
4+
min-height: 100%;
5+
}
6+
body {
7+
/* Margin bottom by footer height */
8+
margin-bottom: 60px;
9+
}
10+
.footer {
11+
position: absolute;
12+
bottom: 0;
13+
width: 100%;
14+
/* Set the fixed height of the footer here */
15+
height: 60px;
16+
/* Vertically center the text there */
17+
line-height: 60px;
18+
}
19+
20+
body > .container {
21+
padding: 40px 15px 0;
22+
}
23+
24+
svg {
25+
width: 100%;
26+
height: 520px;
27+
}

static/js/dataspace.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
const radius = 3.5;
2+
const margin = {top: 10, right: 10, bottom: 10, left: 10};
3+
4+
var app = null;
5+
var currentClass = 0;
6+
7+
8+
class Dataspace {
9+
constructor(selector) {
10+
this.svg = d3.select(selector);
11+
this.$svg = $(selector);
12+
this.dataset = [];
13+
14+
// drawing properties are hardcoded for now
15+
this.width = this.$svg.width();
16+
this.height = this.$svg.height();
17+
this.color = d3.scale.category10();
18+
19+
this.xScale = d3.scale.linear()
20+
.domain([0, 1])
21+
.range([margin.left, this.width - margin.right]);
22+
23+
this.yScale = d3.scale.linear()
24+
.domain([0, 1])
25+
.range([margin.top, this.height - margin.bottom])
26+
}
27+
28+
draw() {
29+
var self = this;
30+
this.svg.selectAll("circle")
31+
.data(this.dataset)
32+
.enter()
33+
.append("circle")
34+
.attr({
35+
cx: function (d) { return self.xScale(d.x); },
36+
cy: function (d) { return self.yScale(d.y); },
37+
fill: function (d) { return self.color(d.c); },
38+
r: radius
39+
});
40+
}
41+
42+
// Add raw data point (e.g. where x and y are between 0 and 1)
43+
addPoint(point) {
44+
this.dataset.push(point);
45+
this.draw();
46+
}
47+
48+
// Add coordinates data point (e.g. where x and y are in the svg)
49+
addCoords(coords) {
50+
var point = {
51+
x: this.xScale.invert(coords[0]),
52+
y: this.yScale.invert(coords[1]),
53+
c: currentClass
54+
};
55+
this.addPoint(point);
56+
}
57+
58+
}
59+
60+
$(document).ready(function() {
61+
// Create the dataspace app
62+
app = new Dataspace("#dataspace");
63+
64+
// Add point to dataset when dataspace is clicked on
65+
app.svg.on("click", function() {
66+
var coords = d3.mouse(this);
67+
app.addCoords(coords);
68+
})
69+
70+
// Change the current class when the select is changed
71+
$("select#classSelect").change(function(e) {
72+
e.preventDefault();
73+
currentClass = parseInt($(e.target).val());
74+
return false;
75+
})
76+
77+
});

templates/index.html

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta http-equiv="X-UA-Compatible" content="chrome=1">
6+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
7+
8+
<title>Data Space</title>
9+
10+
<meta name="author" content="Georgetown Data Science">
11+
<meta name="keywords" content="machine learning, scikit-learn, data space">
12+
<meta name="description" content="Machine learning in data space web demo.">
13+
14+
<!-- shortcut icon -->
15+
16+
<!-- stylesheets -->
17+
<link href="https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/flatly/bootstrap.min.css" rel="stylesheet"
18+
integrity="sha384-T5jhQKMh96HMkXwqVMSjF3CmLcL1nT9//tCqu9By5XSdj7CwR0r+F3LTzUdfkkQf" crossorigin="anonymous">
19+
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"
20+
integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
21+
<link href="{{ url_for('static', filename='css/dataspace.css') }}" rel="stylesheet">
22+
</head>
23+
<body>
24+
<header>
25+
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
26+
<a class="navbar-brand" href="/">Data Space</a>
27+
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
28+
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
29+
<span class="navbar-toggler-icon"></span>
30+
</button>
31+
32+
<div class="collapse navbar-collapse" id="navbarSupportedContent">
33+
<ul class="navbar-nav mr-auto">
34+
<li class="nav-item active">
35+
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
36+
</li>
37+
<li class="nav-item">
38+
<a class="nav-link" href="#" data-toggle="modal" data-target="#aboutModal">
39+
About
40+
</a>
41+
</li>
42+
</ul>
43+
</div>
44+
</nav>
45+
</header>
46+
47+
<main role="main" class="container">
48+
<!-- dataspace -->
49+
<div class="row">
50+
<div class="col-md-12">
51+
<div class="border border-primary">
52+
<!-- the data visualization canvas -->
53+
<svg id="dataspace"></svg>
54+
</div>
55+
</div>
56+
</div><!-- dataspace ends -->
57+
58+
<!-- controls -->
59+
<div class="row mt-2">
60+
<div class="col-md-6">
61+
<form class="form-inline" id="dataEntryForm">
62+
<label class="my-1 mr-2" for="classSelect">Add Points to Class</label>
63+
<select class="custom-select my-1 mr-sm-2" id="classSelect">
64+
<option value="0" selected>0</option>
65+
<option value="1">1</option>
66+
<option value="2">2</option>
67+
<option value="3">3</option>
68+
</select>
69+
</form>
70+
</div>
71+
<div class="col-md-6">
72+
73+
</div>
74+
</div><!-- controls ends -->
75+
</main>
76+
77+
<footer class="footer bg-light">
78+
<div class="container">
79+
<span class="text-muted">
80+
Made with &spades; by <a href="https://github.com/bbengfort">@bbengfort</a>
81+
for the Georgetown Data Science Certificate
82+
</span>
83+
<span class="text-muted pull-right">For Demonstration Purposes Only.</span>
84+
</div>
85+
</footer>
86+
87+
<!-- modals -->
88+
<div class="modal fade" id="aboutModal" tabindex="-1" role="dialog"
89+
aria-labelledby="aboutModalLabel" aria-hidden="true">
90+
<div class="modal-dialog modal-dialog-centered" role="document">
91+
<div class="modal-content">
92+
<div class="modal-header">
93+
<h5 class="modal-title" id="aboutModalLabel">About Data Space</h5>
94+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
95+
<span aria-hidden="true">&times;</span>
96+
</button>
97+
</div>
98+
<div class="modal-body">
99+
<p>
100+
In the tradition of Tkinter SVM GUI, the purpose of this website is to demonstrate how
101+
machine learning model forms are affected by the shape of the underlying dataset. By
102+
selecting a dataset or by creating one of your own, you can fit a model to the data
103+
and see how the model would make decisions based on the data it has been trained on.
104+
Although this is a toy example, hopefully it helps give you the intuition that the
105+
machine learning process is a model selection search for the best combination of features,
106+
algorithm, and hyperparameter that generalize well in a bounded feature space.
107+
</p>
108+
</div>
109+
<div class="modal-footer">
110+
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
111+
</div>
112+
</div>
113+
</div>
114+
</div>
115+
116+
<!-- javascript at the bottom of the page for faster loading -->
117+
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
118+
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
119+
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"
120+
integrity="sha256-G7A4JrJjJlFqP0yamznwPjAApIKPkadeHfyIwiaa9e0=" crossorigin="anonymous"></script>
121+
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"
122+
integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
123+
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.12/d3.min.js" charset="utf-8"></script>
124+
<script src="{{ url_for('static', filename='js/dataspace.js') }}"></script>
125+
126+
<!-- google analytics -->
127+
</body>
128+
</html>

0 commit comments

Comments
 (0)