Last active
November 9, 2017 13:19
-
-
Save WKBae/ced01318202ee860ec52ba5c4ae6dc36 to your computer and use it in GitHub Desktop.
MNIST tester using Flask
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head><title>MNIST Tester</title></head> | |
<style> | |
#number-pad { | |
padding: 0; | |
margin: 0; | |
border-collapse: collapse; | |
border: 1px solid #000; | |
} | |
#number-pad tr { | |
margin: 0; | |
padding: 0; | |
height: 10px; | |
} | |
#number-pad tr td { | |
margin: 0; | |
padding: 0; | |
width: 10px; | |
} | |
.selected { | |
background: #000; | |
} | |
</style> | |
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> | |
<script> | |
var rules = ""; | |
for(var i = 0; i <= 255; i++) { | |
var color = (255 - i).toString(16) | |
color = color + color + color | |
rules += 'td[data-amount="' + i + '"]{background:#' + color + '}' | |
} | |
var st = document.createElement('style') | |
st.innerText = rules | |
document.head.appendChild(st) | |
$(function() { | |
var mousedown = false | |
var changed = false | |
var $tds = $("#number-pad td") | |
var lastRow = -1, lastCol = -1 | |
function applyNear(row, col) { | |
if(row > 0) { | |
var $top = $tds.eq((row - 1) * 28 + col) | |
$top.attr('data-amount', Math.min((($top.attr('data-amount') || 0)|0) + 5, 255)) | |
} | |
if(col > 0) { | |
var $left = $tds.eq(row * 28 + (col - 1)) | |
$left.attr('data-amount', Math.min((($left.attr('data-amount') || 0)|0) + 5, 255)) | |
} | |
if(row < 27) { | |
var $bottom = $tds.eq((row + 1) * 28 + col) | |
$bottom.attr('data-amount', Math.min((($bottom.attr('data-amount') || 0)|0) + 5, 255)) | |
} | |
if(col < 27) { | |
var $right = $tds.eq(row * 28 + (col + 1)) | |
$right.attr('data-amount', Math.min((($right.attr('data-amount') || 0)|0) + 5, 255)) | |
} | |
} | |
darkerTimer = 0 | |
$tds.mouseenter(function() { | |
if(!mousedown) { | |
$(this).css('background', '#aaa'); | |
} else { | |
var idx = $tds.index(this) | |
var row = idx / 28 |0, col = idx % 28 | |
var $toSet = $(this) | |
var updated = [[row, col]] | |
if(lastRow >= 0 && lastCol >= 0) { | |
var dr = row - lastRow, dc = col - lastCol | |
var set = {} | |
for(var r = lastRow; r < row; r++) { | |
var c = Math.round(lastCol + dc * (r - lastRow) / dr) | |
set[r * 28 + c] = true | |
} | |
for(var c = lastCol; c < col; c++) { | |
var r = Math.round(lastRow + dr * (c - lastCol) / dc) | |
set[r * 28 + c] = true | |
} | |
for(var key in set) { | |
if(set.hasOwnProperty(key)) { | |
$toSet = $toSet.add($tds.eq(key|0)) | |
updated.push([key / 28 | 0, key % 28]) | |
} | |
} | |
} | |
$toSet.attr('data-amount', 255) | |
console.log(JSON.stringify(updated), $toSet) | |
applyNear(row, col) | |
darkerTimer = setInterval(function() {applyNear(row, col)}, 50) | |
changed = true | |
lastRow = row | |
lastCol = col | |
} | |
}).mouseleave(function() { | |
$(this).css('background', ''); | |
clearInterval(darkerTimer) | |
darkerTimer = 0 | |
}) | |
$tds.add("#number-pad").mousedown(function() { | |
mousedown = true | |
lastRow = -1 | |
lastCol = -1 | |
$("#result").text("Result: ...") | |
$(this).mouseenter() | |
return false | |
}) | |
$('body').mouseup(function() { | |
mousedown = false | |
}) | |
$("#reset").click(function() { | |
$("[data-amount]").attr('data-amount', '') | |
$("#result").text("") | |
}) | |
setInterval(function() { | |
if(!mousedown && changed) { | |
var amounts = Array.prototype.join.call($tds.map(function() { | |
return (($(this).attr('data-amount') || 0)|0).toString(16) | |
}), ',') | |
//console.log(amounts) | |
$.post('./determine', {'amounts': amounts}, function(data) { | |
$("#result").text("Result: " + data); | |
}) | |
changed = false | |
} | |
}, 1000) | |
}) | |
</script> | |
<body> | |
<table id="number-pad"> | |
<!-- 28 * 28 matrix, ouch --> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> | |
</table> | |
<button id="reset">Reset</button> | |
<div id="result"></div> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from flask import Flask, Response, request | |
import tensorflow as tf | |
app = Flask(__name__) | |
@app.route('/') | |
def page(): | |
with open('mnist-tester.html', 'r', encoding='utf8') as f: | |
return f.read() | |
sess = tf.InteractiveSession() | |
def setup_nn(): | |
# Same network configuration as the checkpoint to load | |
x = tf.placeholder(tf.float32, [None, 784]) | |
x_image = tf.reshape(x, [-1, 28, 28, 1]) | |
W_conv1 = tf.get_variable('W_conv1', shape=[5, 5, 1, 32], initializer=tf.truncated_normal_initializer(stddev=0.01)) | |
b_conv1 = tf.get_variable('b_conv1', shape=[32], initializer=tf.zeros_initializer) | |
h_conv1 = tf.nn.relu(tf.nn.conv2d(x_image, W_conv1, strides=[1, 1, 1, 1], padding='SAME') + b_conv1) | |
h_pool1 = tf.nn.max_pool(h_conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') | |
W_conv2 = tf.get_variable('W_conv2', shape=[5, 5, 32, 64], initializer=tf.truncated_normal_initializer(stddev=0.01)) | |
b_conv2 = tf.get_variable('b_conv2', shape=[64], initializer=tf.zeros_initializer) | |
h_conv2 = tf.nn.relu(tf.nn.conv2d(h_pool1, W_conv2, strides=[1, 1, 1, 1], padding='SAME') + b_conv2) | |
h_pool2 = tf.nn.max_pool(h_conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') | |
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64]) | |
W_fc1 = tf.get_variable('W_fc1', shape=[7*7*64, 1024], initializer=tf.truncated_normal_initializer(stddev=0.01)) | |
b_fc1 = tf.get_variable('b_fc1', [1024], initializer=tf.zeros_initializer) | |
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) | |
W_fc2 = tf.get_variable('W_fc2', shape=[1024, 256], initializer=tf.truncated_normal_initializer(stddev=0.01)) | |
b_fc2 = tf.get_variable('b_fc2', [256], initializer=tf.zeros_initializer) | |
h_fc2 = tf.nn.relu(tf.matmul(h_fc1, W_fc2) + b_fc2) | |
W_endpoint = tf.get_variable('W_endpoint', shape=[256, 10], initializer=tf.truncated_normal_initializer(stddev=0.01)) | |
b_endpoint = tf.get_variable('b_endpoint', [10], initializer=tf.zeros_initializer) | |
logits = tf.matmul(h_fc2, W_endpoint) + b_endpoint | |
result = tf.argmax(logits, 1) | |
sess.run(tf.global_variables_initializer()) | |
saver = tf.train.Saver([W_conv1, b_conv1, W_conv2, b_conv2, W_fc1, b_fc1, W_fc2, b_fc2, W_endpoint, b_endpoint]) | |
# Load the trained checkpoint weights | |
saver.restore(sess, './mnist.ckpt-12000') | |
return x, result | |
x, result = setup_nn() | |
@app.route('/determine', methods=['POST']) | |
def determine(): | |
amts = [int(x, 16) / 255 for x in request.form['amounts'].split(',')] | |
res = sess.run(result, feed_dict={x: [amts]}) | |
return str(res[0]) | |
if __name__ == '__main__': | |
app.run(host='0.0.0.0') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment