Foxgrad's picture
Add game engine and bots
3304d77 verified
Raw History Blame Contribute Delete
1.94 kB
"""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"])