mirror of
https://github.com/cupcakearmy/mnist.git
synced 2024-12-22 16:16:32 +00:00
initial push
This commit is contained in:
parent
ae60abd9fb
commit
727f750aec
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
yarn.lock
|
||||||
|
.cache
|
||||||
|
dist
|
||||||
|
node_modules
|
10
docker-compose.yml
Normal file
10
docker-compose.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
version: '3.7'
|
||||||
|
|
||||||
|
services:
|
||||||
|
server:
|
||||||
|
image: cupcakearmy/static
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- 80:80
|
||||||
|
volumes:
|
||||||
|
- ./dist:/srv:ro
|
16
package.json
Normal file
16
package.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"start": "parcel src/index.html",
|
||||||
|
"build": "parcel build src/index.html"
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"last 1 Chrome versions"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"@tensorflow/tfjs": "^1.5.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"parcel-bundler": "^1.12.4",
|
||||||
|
"parcel-plugin-static-files-copy": "^2.2.1"
|
||||||
|
}
|
||||||
|
}
|
81
src/canvas.js
Normal file
81
src/canvas.js
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/* jslint esversion: 6, asi: true */
|
||||||
|
|
||||||
|
var canvas, ctx, flag = false,
|
||||||
|
prevX = 0,
|
||||||
|
currX = 0,
|
||||||
|
prevY = 0,
|
||||||
|
currY = 0,
|
||||||
|
dot_flag = false;
|
||||||
|
|
||||||
|
var x = "black",
|
||||||
|
y = 2;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
canvas = document.getElementById('can');
|
||||||
|
ctx = canvas.getContext("2d");
|
||||||
|
w = canvas.width;
|
||||||
|
h = canvas.height;
|
||||||
|
|
||||||
|
canvas.addEventListener("mousemove", function (e) {
|
||||||
|
findxy('move', e)
|
||||||
|
}, false);
|
||||||
|
canvas.addEventListener("mousedown", function (e) {
|
||||||
|
findxy('down', e)
|
||||||
|
}, false);
|
||||||
|
canvas.addEventListener("mouseup", function (e) {
|
||||||
|
findxy('up', e)
|
||||||
|
}, false);
|
||||||
|
canvas.addEventListener("mouseout", function (e) {
|
||||||
|
findxy('out', e)
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
|
||||||
|
window.document.getElementById('clear').addEventListener('click', erase)
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(prevX, prevY);
|
||||||
|
ctx.lineTo(currX, currY);
|
||||||
|
ctx.strokeStyle = x;
|
||||||
|
ctx.lineWidth = y;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.closePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
function erase() {
|
||||||
|
ctx.clearRect(0, 0, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findxy(res, e) {
|
||||||
|
if (res == 'down') {
|
||||||
|
prevX = currX;
|
||||||
|
prevY = currY;
|
||||||
|
currX = e.clientX - canvas.offsetLeft;
|
||||||
|
currY = e.clientY - canvas.offsetTop;
|
||||||
|
|
||||||
|
flag = true;
|
||||||
|
dot_flag = true;
|
||||||
|
if (dot_flag) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillStyle = x;
|
||||||
|
ctx.fillRect(currX, currY, 2, 2);
|
||||||
|
ctx.closePath();
|
||||||
|
dot_flag = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (res == 'up' || res == "out") {
|
||||||
|
flag = false;
|
||||||
|
}
|
||||||
|
if (res == 'move') {
|
||||||
|
if (flag) {
|
||||||
|
prevX = currX;
|
||||||
|
prevY = currY;
|
||||||
|
currX = e.clientX - canvas.offsetLeft;
|
||||||
|
currY = e.clientY - canvas.offsetTop;
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init()
|
61
src/index.html
Normal file
61
src/index.html
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
body>div {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div canvas {
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
div input {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: .5em;
|
||||||
|
padding: .5em 2em;
|
||||||
|
background: white;
|
||||||
|
outline: none;
|
||||||
|
border: 1px solid;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<h1>MNIST (Pretrained)</h1>
|
||||||
|
<canvas id="can" width="28" height="28"></canvas>
|
||||||
|
<br />
|
||||||
|
<input id="clear" type="button" value="clear">
|
||||||
|
<br />
|
||||||
|
<input id="test" type="button" value="test">
|
||||||
|
<br />
|
||||||
|
<h2 id="result"></h2>
|
||||||
|
<a href="https://github.com/cupcakearmy/mnist">
|
||||||
|
<h3>source code</h3>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="./tf.js"></script>
|
||||||
|
<script src="./canvas.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
22
src/tf.js
Normal file
22
src/tf.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* jslint esversion: 8, asi: true */
|
||||||
|
|
||||||
|
import * as tf from '@tensorflow/tfjs';
|
||||||
|
|
||||||
|
let model
|
||||||
|
|
||||||
|
tf.loadLayersModel('/model.json').then(m => {
|
||||||
|
model = m
|
||||||
|
})
|
||||||
|
|
||||||
|
window.document.getElementById('test').addEventListener('click', async () => {
|
||||||
|
const canvas = window.document.querySelector('canvas')
|
||||||
|
|
||||||
|
const { data, width, height } = canvas.getContext('2d').getImageData(0, 0, 28, 28)
|
||||||
|
|
||||||
|
const tensor = tf.tensor(new Uint8Array(data.filter((_, i) => i % 4 === 3)), [1, 28, 28, 1])
|
||||||
|
const prediction = model.predict(tensor)
|
||||||
|
const result = await prediction.data()
|
||||||
|
const guessed = result.indexOf(1)
|
||||||
|
console.log(guessed)
|
||||||
|
window.document.querySelector('#result').innerText = guessed
|
||||||
|
})
|
BIN
static/group1-shard1of1.bin
Normal file
BIN
static/group1-shard1of1.bin
Normal file
Binary file not shown.
310
static/model.json
Normal file
310
static/model.json
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
{
|
||||||
|
"format": "layers-model",
|
||||||
|
"generatedBy": "keras v2.2.4-tf",
|
||||||
|
"convertedBy": "TensorFlow.js Converter v1.4.0",
|
||||||
|
"modelTopology": {
|
||||||
|
"keras_version": "2.2.4-tf",
|
||||||
|
"backend": "tensorflow",
|
||||||
|
"model_config": {
|
||||||
|
"class_name": "Sequential",
|
||||||
|
"config": {
|
||||||
|
"name": "sequential",
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"class_name": "Conv2D",
|
||||||
|
"config": {
|
||||||
|
"name": "conv2d",
|
||||||
|
"trainable": true,
|
||||||
|
"batch_input_shape": [
|
||||||
|
null,
|
||||||
|
28,
|
||||||
|
28,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"dtype": "float32",
|
||||||
|
"filters": 64,
|
||||||
|
"kernel_size": [
|
||||||
|
3,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"strides": [
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"padding": "valid",
|
||||||
|
"data_format": "channels_last",
|
||||||
|
"dilation_rate": [
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"activation": "relu",
|
||||||
|
"use_bias": true,
|
||||||
|
"kernel_initializer": {
|
||||||
|
"class_name": "GlorotUniform",
|
||||||
|
"config": {
|
||||||
|
"seed": 420,
|
||||||
|
"dtype": "float32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bias_initializer": {
|
||||||
|
"class_name": "Zeros",
|
||||||
|
"config": {
|
||||||
|
"dtype": "float32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"kernel_regularizer": null,
|
||||||
|
"bias_regularizer": null,
|
||||||
|
"activity_regularizer": null,
|
||||||
|
"kernel_constraint": null,
|
||||||
|
"bias_constraint": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_name": "Conv2D",
|
||||||
|
"config": {
|
||||||
|
"name": "conv2d_1",
|
||||||
|
"trainable": true,
|
||||||
|
"dtype": "float32",
|
||||||
|
"filters": 32,
|
||||||
|
"kernel_size": [
|
||||||
|
3,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"strides": [
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"padding": "valid",
|
||||||
|
"data_format": "channels_last",
|
||||||
|
"dilation_rate": [
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"activation": "relu",
|
||||||
|
"use_bias": true,
|
||||||
|
"kernel_initializer": {
|
||||||
|
"class_name": "GlorotUniform",
|
||||||
|
"config": {
|
||||||
|
"seed": 420,
|
||||||
|
"dtype": "float32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bias_initializer": {
|
||||||
|
"class_name": "Zeros",
|
||||||
|
"config": {
|
||||||
|
"dtype": "float32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"kernel_regularizer": null,
|
||||||
|
"bias_regularizer": null,
|
||||||
|
"activity_regularizer": null,
|
||||||
|
"kernel_constraint": null,
|
||||||
|
"bias_constraint": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_name": "MaxPooling2D",
|
||||||
|
"config": {
|
||||||
|
"name": "max_pooling2d",
|
||||||
|
"trainable": true,
|
||||||
|
"dtype": "float32",
|
||||||
|
"pool_size": [
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"padding": "valid",
|
||||||
|
"strides": [
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"data_format": "channels_last"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_name": "Dropout",
|
||||||
|
"config": {
|
||||||
|
"name": "dropout",
|
||||||
|
"trainable": true,
|
||||||
|
"dtype": "float32",
|
||||||
|
"rate": 0.25,
|
||||||
|
"noise_shape": null,
|
||||||
|
"seed": 420
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_name": "Flatten",
|
||||||
|
"config": {
|
||||||
|
"name": "flatten",
|
||||||
|
"trainable": true,
|
||||||
|
"dtype": "float32",
|
||||||
|
"data_format": "channels_last"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_name": "Dense",
|
||||||
|
"config": {
|
||||||
|
"name": "dense",
|
||||||
|
"trainable": true,
|
||||||
|
"dtype": "float32",
|
||||||
|
"units": 128,
|
||||||
|
"activation": "relu",
|
||||||
|
"use_bias": true,
|
||||||
|
"kernel_initializer": {
|
||||||
|
"class_name": "GlorotUniform",
|
||||||
|
"config": {
|
||||||
|
"seed": 420,
|
||||||
|
"dtype": "float32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bias_initializer": {
|
||||||
|
"class_name": "Zeros",
|
||||||
|
"config": {
|
||||||
|
"dtype": "float32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"kernel_regularizer": null,
|
||||||
|
"bias_regularizer": null,
|
||||||
|
"activity_regularizer": null,
|
||||||
|
"kernel_constraint": null,
|
||||||
|
"bias_constraint": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_name": "Dropout",
|
||||||
|
"config": {
|
||||||
|
"name": "dropout_1",
|
||||||
|
"trainable": true,
|
||||||
|
"dtype": "float32",
|
||||||
|
"rate": 0.5,
|
||||||
|
"noise_shape": null,
|
||||||
|
"seed": 420
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_name": "Dense",
|
||||||
|
"config": {
|
||||||
|
"name": "dense_1",
|
||||||
|
"trainable": true,
|
||||||
|
"dtype": "float32",
|
||||||
|
"units": 10,
|
||||||
|
"activation": "softmax",
|
||||||
|
"use_bias": true,
|
||||||
|
"kernel_initializer": {
|
||||||
|
"class_name": "GlorotUniform",
|
||||||
|
"config": {
|
||||||
|
"seed": 420,
|
||||||
|
"dtype": "float32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bias_initializer": {
|
||||||
|
"class_name": "Zeros",
|
||||||
|
"config": {
|
||||||
|
"dtype": "float32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"kernel_regularizer": null,
|
||||||
|
"bias_regularizer": null,
|
||||||
|
"activity_regularizer": null,
|
||||||
|
"kernel_constraint": null,
|
||||||
|
"bias_constraint": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"training_config": {
|
||||||
|
"loss": "categorical_crossentropy",
|
||||||
|
"metrics": [
|
||||||
|
"accuracy"
|
||||||
|
],
|
||||||
|
"weighted_metrics": null,
|
||||||
|
"sample_weight_mode": null,
|
||||||
|
"loss_weights": null,
|
||||||
|
"optimizer_config": {
|
||||||
|
"class_name": "Adam",
|
||||||
|
"config": {
|
||||||
|
"name": "Adam",
|
||||||
|
"learning_rate": 0.0010000000474974513,
|
||||||
|
"decay": 0.0,
|
||||||
|
"beta_1": 0.8999999761581421,
|
||||||
|
"beta_2": 0.9990000128746033,
|
||||||
|
"epsilon": 1e-07,
|
||||||
|
"amsgrad": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"weightsManifest": [
|
||||||
|
{
|
||||||
|
"paths": [
|
||||||
|
"group1-shard1of1.bin"
|
||||||
|
],
|
||||||
|
"weights": [
|
||||||
|
{
|
||||||
|
"name": "conv2d/kernel",
|
||||||
|
"shape": [
|
||||||
|
3,
|
||||||
|
3,
|
||||||
|
1,
|
||||||
|
64
|
||||||
|
],
|
||||||
|
"dtype": "float32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "conv2d/bias",
|
||||||
|
"shape": [
|
||||||
|
64
|
||||||
|
],
|
||||||
|
"dtype": "float32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "conv2d_1/kernel",
|
||||||
|
"shape": [
|
||||||
|
3,
|
||||||
|
3,
|
||||||
|
64,
|
||||||
|
32
|
||||||
|
],
|
||||||
|
"dtype": "float32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "conv2d_1/bias",
|
||||||
|
"shape": [
|
||||||
|
32
|
||||||
|
],
|
||||||
|
"dtype": "float32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dense/kernel",
|
||||||
|
"shape": [
|
||||||
|
4608,
|
||||||
|
128
|
||||||
|
],
|
||||||
|
"dtype": "float32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dense/bias",
|
||||||
|
"shape": [
|
||||||
|
128
|
||||||
|
],
|
||||||
|
"dtype": "float32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dense_1/kernel",
|
||||||
|
"shape": [
|
||||||
|
128,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"dtype": "float32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dense_1/bias",
|
||||||
|
"shape": [
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"dtype": "float32"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user