ffcm commited on
Commit
de6bc20
β€’
1 Parent(s): e3ce5a0

Initial commit

Browse files
Files changed (7) hide show
  1. .vscode/settings.json +6 -0
  2. README.md +6 -2
  3. app.py +32 -0
  4. dataset.py +63 -0
  5. model_91_7248.bin +0 -0
  6. network.py +73 -0
  7. requirements.txt +1 -0
.vscode/settings.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "[python]": {
3
+ "editor.defaultFormatter": "ms-python.autopep8"
4
+ },
5
+ "python.formatting.provider": "none"
6
+ }
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Nn Scratch Mnist
3
  emoji: πŸƒ
4
  colorFrom: indigo
5
  colorTo: pink
@@ -10,4 +10,8 @@ pinned: false
10
  license: mit
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
1
  ---
2
+ title: Simple MNIST Classifier
3
  emoji: πŸƒ
4
  colorFrom: indigo
5
  colorTo: pink
 
10
  license: mit
11
  ---
12
 
13
+ The model used is a Neural Network made with Python and Numpy only.
14
+ Architecture is 784 input units, two hidden layers of 72 and 24 units and a 10 unit output.
15
+ Training was done on the MNIST training dataset of 60000 images.
16
+
17
+ Video (Portuguese-Brazil): https://www.youtube.com/watch?v=NhG8NsHW6fI
app.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pickle
3
+
4
+ with open('model_91_7248.bin', 'rb') as f:
5
+ nn = pickle.load(f)
6
+
7
+
8
+ def predict(input):
9
+ x = input.reshape((784, 1))
10
+ p = nn.feed_forward(x).reshape((10,))
11
+
12
+ return dict(enumerate(p))
13
+
14
+
15
+ demo = gr.Interface(
16
+ fn=predict,
17
+ inputs=[
18
+ gr.Sketchpad(
19
+ shape=(28, 28),
20
+ brush_radius=1.2,
21
+ )
22
+ ],
23
+ outputs=[
24
+ gr.Label(
25
+ num_top_classes=3,
26
+ scale=2,
27
+ )
28
+ ],
29
+ live=True,
30
+ allow_flagging=False,
31
+
32
+ ).launch()
dataset.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+
4
+ def load_training():
5
+ images_file = open('./train-images-idx3-ubyte', 'rb')
6
+ labels_file = open('./train-labels-idx1-ubyte', 'rb')
7
+
8
+ images = load_images(images_file)
9
+ labels = load_labels(labels_file)
10
+
11
+ return images, labels
12
+
13
+
14
+ def bytes_to_int(bytes):
15
+ return int.from_bytes(bytes, byteorder='big')
16
+
17
+
18
+ def load_images(file, num=60000):
19
+ magic = bytes_to_int(file.read(4))
20
+ if (magic != 2051):
21
+ raise RuntimeError('Wrong file for images')
22
+
23
+ num_images = bytes_to_int(file.read(4))
24
+ num_rows = bytes_to_int(file.read(4))
25
+ num_cols = bytes_to_int(file.read(4))
26
+
27
+ images = []
28
+
29
+ for i in range(min(num_images, num)):
30
+ images.append([
31
+ bytes_to_int(file.read(1)) for p in range(num_rows * num_cols)
32
+ ])
33
+
34
+ return images
35
+
36
+
37
+ def load_labels(file, num=60000):
38
+ magic = bytes_to_int(file.read(4))
39
+ if (magic != 2049):
40
+ raise RuntimeError('Wrong file for labels')
41
+
42
+ num_labels = bytes_to_int(file.read(4))
43
+
44
+ labels = [
45
+ bytes_to_int(file.read(1)) for l in range(min(num_labels, num))
46
+ ]
47
+
48
+ return labels
49
+
50
+
51
+ def convert_label_to_output(label: int):
52
+ output = np.zeros((10, 1))
53
+ output[label][0] = 1.0
54
+
55
+ return output
56
+
57
+
58
+ def convert_image_to_input(image: list):
59
+ return np.reshape(image, (784, 1))
60
+
61
+
62
+ def convert_output_to_label(output: np.ndarray[np.float64]):
63
+ return np.argmax(output)
model_91_7248.bin ADDED
Binary file (485 kB). View file
 
network.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ class NeuralNetwork():
4
+ def __init__(self, neurons_per_layer):
5
+ self.num_layers = len(neurons_per_layer)
6
+ self.neurons_per_layer = neurons_per_layer
7
+
8
+ a = neurons_per_layer[1:]
9
+ b = neurons_per_layer[:-1]
10
+
11
+ self.weights = [
12
+ np.random.randn(current, previous) for current, previous in
13
+ zip(a, b)
14
+ ]
15
+
16
+ self.bias = [np.random.randn(y, 1) for y in a]
17
+
18
+ def activation_fn(self, x):
19
+ return 1.0 / (1.0 + np.exp(-x))
20
+
21
+ def cost_derivative(self, output, expected):
22
+ return output - expected
23
+
24
+ def activation_derivative(self, x):
25
+ return self.activation_fn(x) * (1 - self.activation_fn(x))
26
+
27
+ def feed_forward(self, x):
28
+ for w, b in zip(self.weights, self.bias):
29
+ z = np.dot(w, x) + b
30
+ x = self.activation_fn(z)
31
+
32
+ return x
33
+
34
+ def backprop(self, x, expected):
35
+ weight_gradients = [np.zeros(w.shape) for w in self.weights]
36
+ bias_gradients = [np.zeros(b.shape) for b in self.bias]
37
+
38
+ zs = []
39
+ activation = np.array(x)
40
+ activations = [np.array(x)]
41
+
42
+ for w, b in zip(self.weights, self.bias):
43
+ z = np.dot(w, activation) + b
44
+ zs.append(z)
45
+ activation = self.activation_fn(z)
46
+ activations.append(activation)
47
+
48
+ delta = self.cost_derivative(
49
+ activation, expected) * self.activation_derivative(zs[-1])
50
+
51
+ weight_gradients[-1] = np.dot(delta, activations[-2].T)
52
+ bias_gradients[-1] = delta
53
+
54
+ for layer in range(2, self.num_layers):
55
+ z = zs[-layer]
56
+ d = self.activation_derivative(z)
57
+ delta = np.dot(self.weights[-layer + 1].T, delta) * d
58
+
59
+ weight_gradients[-layer] = np.dot(delta, activations[-layer - 1].T)
60
+ bias_gradients[-layer] = delta
61
+
62
+ return (weight_gradients, bias_gradients)
63
+
64
+ def adjust(self, lr, weight_gradients, bias_gradients):
65
+ self.weights = [
66
+ w - lr * nw for w, nw in
67
+ zip(self.weights, weight_gradients)
68
+ ]
69
+
70
+ self.bias = [
71
+ b - lr * nb for b, nb in
72
+ zip(self.bias, bias_gradients)
73
+ ]
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ numpy==1.26.0