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