File size: 1,943 Bytes
3304d77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Un petit réseau de neurones en numpy (perceptron multicouche).

Tous les bots qui apprennent utilisent ce format pour jouer, ce qui permet de lancer
l'arène sans PyTorch. Les poids de départ sont tirés au hasard : le bot ne sait rien.
"""
from __future__ import annotations

import numpy as np


class MLP:
    def __init__(self, sizes, out_act="tanh", rng=None, flat=None):
        self.sizes = list(sizes)
        self.out_act = out_act
        self.shapes = [(a, b) for a, b in zip(self.sizes[:-1], self.sizes[1:])]
        self.n_params = sum(a * b + b for a, b in self.shapes)
        if flat is None:
            rng = rng or np.random.default_rng()
            flat = np.concatenate([
                np.concatenate([rng.normal(0, 1 / np.sqrt(a), a * b), np.zeros(b)]) for a, b in self.shapes
            ])
        self.set_flat(flat)

    def set_flat(self, flat):
        flat = np.asarray(flat, dtype=np.float32)
        assert flat.size == self.n_params, (flat.size, self.n_params)
        self.flat = flat
        self.layers, i = [], 0
        for a, b in self.shapes:
            W = flat[i:i + a * b].reshape(a, b); i += a * b
            bias = flat[i:i + b]; i += b
            self.layers.append((W, bias))

    def __call__(self, x):
        h = np.asarray(x, dtype=np.float32)
        for k, (W, b) in enumerate(self.layers):
            h = h @ W + b
            if k < len(self.layers) - 1:
                h = np.tanh(h)
        if self.out_act == "tanh":
            h = np.tanh(h)
        return h

    # ------------------------------------------------------------- sauvegarde
    def to_dict(self, prefix=""):
        return {prefix + "sizes": np.array(self.sizes), prefix + "flat": self.flat,
                prefix + "out_act": np.array(self.out_act)}

    @staticmethod
    def from_dict(d, prefix=""):
        return MLP(d[prefix + "sizes"].tolist(), str(d[prefix + "out_act"]), flat=d[prefix + "flat"])