# -rw-r--r-- 1.9 KiB View raw
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import random
import math

from tinygrad.nn import Linear
from tinygrad.tensor import Tensor
from tinygrad.nn.optim import Adam

HIDDEN_LAYERS = 10
HIDDEN_WIDTH = 10 # Measure accuracy as a function of this.
BIAS = True

class TwoDimensionalClassifier:
    def __init__(self):
        self.layers = [Linear(HIDDEN_WIDTH, HIDDEN_WIDTH, bias=BIAS) for _ in range(0, HIDDEN_LAYERS)]
        self.layers = [Linear(2, HIDDEN_WIDTH, bias=BIAS)] + self.layers + [Linear(HIDDEN_WIDTH, 2, bias=BIAS)]

    def transform(self, x):
        for layer in self.layers[:-1]:
            x = layer(x)
            x = x.relu()
        return self.layers[-1](x)

    def transformLayerByLayer(self, x):
        for layer in self.layers[:-1]:
            x = layer(x).relu()
            yield x
        yield self.layers[-1](x).softmax()

    def __call__(self, x):
        return self.transform(x).softmax()

def trained(distribution, training_steps=3000):
    Tensor.training = True
    net = TwoDimensionalClassifier()
    opt = Adam([layer.weight for layer in net.layers])
    for _ in range(training_steps):
        point, classification = distribution.sample()
        guess = net(point)
        error = guess.sparse_categorical_crossentropy(classification)
        opt.zero_grad()
        error.backward()
        opt.step()

    Tensor.training = False
    return net

# A circle at the origin. Points inside the circle are class 1, points
# outside the circle are class 0.
class CircleAtOrigin:
    def __init__(self, radius=1):
        self.radius = 1

    # Gets a random point in a 3x3 square centered on the origin and its
    # classification ([0] or [1] for inside the circle).
    def sample(self):
        x = random.random() * self.radius*3 - self.radius*1.5
        y = random.random() * self.radius*3 - self.radius*1.5
        point = Tensor([x, y])
        classification = Tensor([1]) if x*x + y*y <= self.radius*self.radius else Tensor([0])
        return point, classification