forge/trinity/pantheon.py (90 lines of code) (raw):
from pdb import set_trace as T
import numpy as np
import torch
import time
from collections import defaultdict
from torch.nn.parameter import Parameter
from forge.ethyr.torch import save
from forge.ethyr.torch.optim import ManualAdam, ManualSGD
from forge.ethyr.torch.param import getParameters
from forge.blade.lib.log import Quill
from forge import trinity
class Model:
def __init__(self, config, args):
self.saver = save.Saver(config.NPOP, config.MODELDIR,
'models', 'bests', resetTol=256)
self.config, self.args = config, args
self.init()
if self.config.LOAD or self.config.BEST:
self.load(self.config.BEST)
def init(self):
print('Initializing new model...')
if self.config.SHAREINIT:
self.shared(self.config.NPOP)
else:
self.unshared(self.config.NPOP)
self.params = Parameter(torch.Tensor(np.array(self.models)))
self.opt = None
if not self.config.TEST:
self.opt = ManualAdam([self.params], lr=0.001, weight_decay=0.00001)
#Initialize a new network
def initModel(self):
return getParameters(trinity.ANN(self.config))
def shared(self, n):
model = self.initModel()
self.models = [model for _ in range(n)]
def unshared(self, n):
self.models = [self.initModel() for _ in range(n)]
#Grads and clip
def stepOpt(self, gradDicts):
grads = defaultdict(list)
keysets = [grads.keys() for grads in gradDicts]
for gradDict in gradDicts:
for worker, grad in gradDict.items():
grads[worker].append(grad)
for worker, gradList in grads.items():
grad = np.array(gradList)
grad = np.mean(grad, 0)
grad = np.clip(grad, -5, 5)
grads[worker] = grad
gradAry = torch.zeros_like(self.params)
for worker, grad in grads.items():
gradAry[worker] = torch.Tensor(grad)
self.opt.step(gradAry)
def checkpoint(self, reward):
if self.config.TEST:
return
self.saver.checkpoint(self.params, self.opt, reward)
def load(self, best=False):
print('Loading model...')
epoch = self.saver.load(
self.opt, self.params, best)
@property
def nParams(self):
nParams = sum([len(e) for e in self.model])
print('#Params: ', str(nParams/1000), 'K')
@property
def model(self):
return self.params.detach().numpy()
class Pantheon:
def __init__(self, config, args):
self.start, self.tick, self.nANN = time.time(), 0, config.NPOP
self.config, self.args = config, args
self.net = Model(config, args)
self.quill = Quill(config.MODELDIR)
self.log = defaultdict(list)
self.net.nParams
self.period = 1
@property
def model(self):
return self.net.model
def step(self, recvs):
recvs, logs = list(zip(*recvs))
#Write logs
self.quill.scrawl(logs)
self.tick += 1
if not self.config.TEST:
lifetime = self.quill.latest()
self.net.stepOpt(recvs)
self.net.checkpoint(lifetime)
self.net.saver.print()
else:
self.quill.print()
return self.model