back to lab notes
aicompleted2024

Neural Network from Scratch

Multilayer Perceptron (MLP) projetado do zero em Python e exportado para inferência nativa em navegador (HTML/JS) para OCR. Baseado em Tariq Rashid, 2016.

PythonNumPyJavaScriptAIOCR

Specifications

Arquitetura

784 → 200 → 10

Ativação

Sigmóide

Dataset

MNIST CSV (1k + 3× aug)

Augmentation

Rotação ±10° (scipy)

Pesos Export

weights.js (3.4 MB)

Inferência

Browser (canvas 28×28)

Tech Stack

Python 3NumPySciPyHTML5 CanvasVanilla JS

Overview

Rede neural MLP com 784 entradas (pixels), 200 neurônios ocultos e 10 saídas (classes 0-9). Inicialização de pesos por distribuição normal. Aprendizado por descida de gradiente com backpropagation. Data augmentation real via matrizes de rotação scipy.ndimage (±10°), triplicando o dataset de 1.000 para 3.000 amostras. Exportação dos pesos pré-treinados para weights.js (3.4 MB) para contornar políticas CORS em execução file:///. Normalização visual no canvas: algoritmo de centro de massa com bounding box, interpolação bilinear 20×20px e centralização em frame 28×28 normalizado [0.01, 0.99].

Key Features

  • Forward propagation e backpropagation implementados do zero com NumPy
  • Data augmentation via matrizes de rotação scipy.ndimage (±10°, 3× dataset)
  • Export de pesos para JS standalone (weights.js, 3.4 MB) — bypass CORS
  • Algoritmo de centro de massa + bounding box para normalização MNIST-style no canvas
  • Interpolação bilinear para rescale 20×20px → frame 28×28 centralizado
  • Inferência 100% client-side no navegador sem backend

Backpropagation — Atualização de Pesos

python
def backward(self, X, y, learning_rate=0.01):
    m = X.shape[0]
    output = self.activations[-1]
    delta = (output - y) * self.sigmoid_derivative(
        self.z_values[-1]
    )
    for i in range(len(self.weights) - 1, -1, -1):
        dw = np.dot(self.activations[i].T, delta) / m
        db = np.sum(delta, axis=0, keepdims=True) / m
        if i > 0:
            delta = np.dot(
                delta, self.weights[i].T
            ) * self.sigmoid_derivative(self.z_values[i-1])
        self.weights[i] -= learning_rate * dw
        self.biases[i] -= learning_rate * db