mirror of
https://github.com/cupcakearmy/mnist.git
synced 2024-12-22 08:06:28 +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