jsuarez/ES.py (106 lines of code) (raw):

from pdb import set_trace as T import ray import numpy as np from sim.lib import Utils from collections import defaultdict from itertools import chain from sim.lib.PriorityQueue import PriorityQueue from scipy.stats import rankdata class ES: def __init__(self, foo, hyperparams, test=False): #self.nPop = 2048 self.nPop = 512 self.nRollouts = 1 self.minRollouts = 1 self.nDims = 25248 + 16 + 96 + 6 self.nNoise = 10000 self.sigma = hyperparams['sigma'] self.alpha = hyperparams['alpha'] self.topP = hyperparams['topP'] self.tstep = hyperparams['step'] #0.0020*51.2 self.tick = 0 self.test = test self.desciples= {} self.elite = defaultdict(list) #self.topk = PriorityQueue(20) self.priorities = [] self.bench = Utils.BenchmarkTimer() #if not test: self.meanVec = self.sigma*np.random.randn(self.nDims) self.resetNoise() self.data = (self.meanVec, self.noise) def collectRollout(self, iden, ent): if self.test: return f, mut = (ent.timeAlive, ent.packet) mut = mut[0] self.elite[mut].append(f) def stepES(self): if self.tick % self.tstep != 0: return meanOff, n = 0, 0 noise = self.noise #Mean over rollouts elite = [(np.min(v), k) for k, v in self.elite.items() if len(v) >= self.minRollouts] if len(elite) == 0: return elite = sorted(elite, reverse=True) self.elite = defaultdict(list) Fs, mutations = list(zip(*elite)) topP = int(self.topP * len(Fs)) Fs, mutations = Fs[:topP], mutations[:topP] Fs = rankdata(Fs, method='dense') Fs = np.asarray(Fs)[:, np.newaxis] mutations = noise[mutations, :] if len(Fs) == 0: return #Weighted mean vec update meanOff = np.mean(Fs*mutations, 0) meanVec = self.meanVec self.meanVec = meanVec + self.alpha * meanOff self.data = self.meanVec, self.noise def getParams(self): return self.meanVec, self.priorities def setParams(self, meanVec, hyperparams): self.meanVec = meanVec self.data = (self.meanVec, self.shared[1]) def print(self): print(sorted(self.priorities, reverse=True)[:20]) @property def n(self): return len(self.desciples) def step(self): self.tick += 1 self.cullDead() #self.priorities = self.topk.priorities() #self.priorities = self.priorities[:len(self.priorities)] elite = [np.min(v) for v in self.elite.values() if len(v) >= self.minRollouts] elite = sorted(elite, reverse=True) priorities = int(self.topP * len(elite)) self.priorities = elite[:priorities] self.stepES() pass @property def shared(self): ret = self.data self.data = (None, None) return ret def cullDead(self): for k in list(self.desciples.keys()): if not self.desciples[k].alive: del self.desciples[k] def resetNoise(self): self.noiseInd = 0 self.noiseIncInd = 0 if self.test: self.noise = np.zeros((self.nNoise, self.nDims)) else: self.noise = 0.1*np.random.randn(self.nNoise, self.nDims) def save(self): return self.meanVec def load(self, meanVec): self.meanVec = meanVec #Returns a seed to use for spawning def spawn(self): iden = Utils.uniqueKey(self.desciples) self.noiseIncInd += 1 if self.noiseIncInd == self.nRollouts: self.noiseIncInd = 0 self.noiseInd += 1 if self.noiseInd == self.nNoise: self.noiseInd = 0 self.noiseIncInd = 0 packet = self.noiseInd return iden, [packet]