def __init__(self, **kwargs): super(Boa, self).__init__(**kwargs) self.network = BayesNet(numVariables=self.config.space.dim, **self.config.__properties__) self.network = StructureProposal(**self.config.__properties__).search( self.network) self.trained = False
def update(self, history, fitness): super(Boa, self).update(history,fitness) if history.lastPopulation() is None: return population = [x for x,s in history.lastPopulation()] selected = int(self.config.truncate * len(population)) self.network = BayesNet(numVariables=self.config.space.dim, **self.config.__properties__) self.network.config.data = None self.network = StructureProposal(**self.network.config.__properties__).search(self.network) self.network.config.data = population self.network.structureSearch(population) self.network.update(self.history.updates, population)
def update(self, history, fitness): super(Boa, self).update(history, fitness) if history.lastPopulation() is None: return population = [x for x, s in history.lastPopulation()] selected = int(self.config.truncate * len(population)) self.network = BayesNet(numVariables=self.config.space.dim, **self.config.__properties__) self.network.config.data = None self.network = StructureProposal( **self.network.config.__properties__).search(self.network) self.network.config.data = population self.network.structureSearch(population) self.network.update(self.history.updates, population)
def parse(self, fname): f = open(fname) totalLine = "" done = False for line in f: totalLine += line lefts = len(totalLine.split("(")) rights = len(totalLine.split(")")) if lefts == rights: self.processLine(totalLine) totalLine = "" categories = [[]] * self.index for name, idx in self.indexMap.iteritems(): categories[idx] = self.variables[name]['vals'] cfg = Config() cfg.numVariables = len(self.variables) cfg.variableGenerator = MultinomialVariableGenerator(categories) cfg.randomizer = MultinomialRandomizer() cfg.sampler = DAGSampler() cfg.structureGenerator = StructureProposal(cfg) net = BayesNet(cfg) for variable in net.variables: variable.tables = self.variables[self.revIndexMap[ variable.index]]['cpt'] #print names[variable.index], self.variables[self.revIndexMap[variable.index]]['parents'] variable.known = [ self.indexMap[parent] for parent in self.variables[ self.revIndexMap[variable.index]]['parents'] ] variable.known = sorted(variable.known) variable.parents = dict([(i, net.variables[i]) for i in variable.known]) net.dirty = True net.computeEdgeStatistics() """ for variable in net.variables: print "(var ", self.revIndexMap[variable.index], " (", " ".join(variable.categories[variable.index]), "))" for variable in net.variables: print "(parents ", self.revIndexMap[variable.index], " (", " ".join([self.revIndexMap[i] for i in variable.known]), ") " for key, val in variable.tables.iteritems(): if key == "": expanded = "" else: cfg = array([int(num) for num in key.split(",")]) expanded = " ".join(self.variables[self.revIndexMap[variable.known[k]]]['vals'][c-1] for k,c in enumerate(cfg)) total = val.sum() vals = " ".join([str(i) for i in val]) print "((", expanded, ") ", vals, (1. - total), ")" print ")" """ return net
def __init__(self, space): self.space = space self.sampler = DAGSampler() if hasattr(space, 'dim'): self.numVariables = space.dim else: raise ValueError("Cannot determine the number of dimensions " "for BinaryBayesStructure space based on given " "space; expected space to have property dim " "indicating the number of required variables. ") super(BinaryBayesStructure, self).__init__(self.numVariables**2) self.config = Config(numVariables=self.numVariables, variableGenerator=self.variable, randomizer=self.randomize, sampler=self.sample) self.proposal = StructureProposal(**self.config.__properties__) self.config.structureGenerator = self.proposal
class Boa(PopulationDistribution): """The Bayesian Optimization Algorithm of Martin Pelikan. """ config = Config( variableGenerator=BinaryVariable, branchFactor=3, structureGenerator=GreedyStructureSearch( 3, BayesianInformationCriterion()), randomizer=lambda net: TernaryString(0L, -1L, net.numVariables), sampler=DAGSampler(), data=None, truncate=0.60, # percentage of the population to keep space=BinaryReal(realDim=5), history=SortedMarkovHistory) def __init__(self, **kwargs): super(Boa, self).__init__(**kwargs) self.network = BayesNet(numVariables=self.config.space.dim, **self.config.__properties__) self.network = StructureProposal(**self.config.__properties__).search( self.network) self.trained = False def compatible(self, history): return hasattr(history, "lastPopulation") and history.sorted def sample(self): x = self.network.__call__() cnt = 0 while not self.config.space.in_bounds(x): if cnt > 10000: raise ValueError( "Rejection sampling failed after 10,000 attempts in BOA") x = self.network.__call__() cnt += 1 return x def batch(self, num): return [self.sample() for i in xrange(num)] def update(self, history, fitness): super(Boa, self).update(history, fitness) if history.lastPopulation() is None: return population = [x for x, s in history.lastPopulation()] selected = int(self.config.truncate * len(population)) self.network = BayesNet(numVariables=self.config.space.dim, **self.config.__properties__) self.network.config.data = None self.network = StructureProposal( **self.network.config.__properties__).search(self.network) self.network.config.data = population self.network.structureSearch(population) self.network.update(self.history.updates, population)
class Boa(PopulationDistribution): """The Bayesian Optimization Algorithm of Martin Pelikan. """ config = Config(variableGenerator=BinaryVariable, branchFactor=3, structureGenerator=GreedyStructureSearch(3, BayesianInformationCriterion()), randomizer = lambda net: TernaryString(0L, -1L, net.numVariables), sampler = DAGSampler(), data = None, truncate = 0.60, # percentage of the population to keep space = BinaryReal(realDim=5), history=SortedMarkovHistory) def __init__(self, **kwargs): super(Boa, self).__init__(**kwargs) self.network = BayesNet(numVariables=self.config.space.dim, **self.config.__properties__) self.network = StructureProposal(**self.config.__properties__).search(self.network) self.trained = False def compatible(self, history): return hasattr(history, "lastPopulation") and history.sorted def sample(self): x = self.network.__call__() cnt = 0 while not self.config.space.in_bounds(x): if cnt > 10000: raise ValueError("Rejection sampling failed after 10,000 attempts in BOA") x = self.network.__call__() cnt += 1 return x def batch(self, num): return [self.sample() for i in xrange(num)] def update(self, history, fitness): super(Boa, self).update(history,fitness) if history.lastPopulation() is None: return population = [x for x,s in history.lastPopulation()] selected = int(self.config.truncate * len(population)) self.network = BayesNet(numVariables=self.config.space.dim, **self.config.__properties__) self.network.config.data = None self.network = StructureProposal(**self.network.config.__properties__).search(self.network) self.network.config.data = population self.network.structureSearch(population) self.network.update(self.history.updates, population)
class BayesNetStructure(Space, PreBayesSpace): """Space for Bayesian network structure search. Built on top of a variable space that determines the variables of the Bayes net. For example, a Euclidean space, say $\mathbb{R}^d$, would have $d$ :class:`GaussianVariable`s. Or, a Binary space would have :class:`BinaryVariable`s. The default choice of variable is controlled by the ``_mapping`` class variable based on the ``type`` field of the variable space. To have mixed networks, use a :class:`Product` space. :param space: The space of variables :type space: :class:`Space` """ _mappings = { # map space types to bayesian variables np.ndarray: GaussianVariable, TernaryString: BinaryVariable, } def __init__(self, space): super(BayesNetStructure, self).__init__(BayesNet) self.space = space self.sampler = DAGSampler() if hasattr(space, 'dim'): self.numVariables = space.dim else: raise ValueError("Cannot determine the number of dimensions " "for BayesNetStructure space based on given " "space; expected space to have property dim " "indicating the number of required variables. ") self.config = Config(numVariables=self.numVariables, variableGenerator=self.variable, randomizer=self.randomize, sampler=self.sample) self.proposal = StructureProposal(**self.config.__properties__) self.config.structureGenerator = self.proposal self.edges = [] self.nedges = [] def in_bounds(self, network, **kwargs): c = network.config return (isinstance(network, BayesNet) and len(network.variables) == self.numVariables and np.all([ v.__class__ == self.variable(v.index, c).__class__ for v in network.variables ])) def proportion(self, smaller, larger, index): return 2.0**((len(smaller.edges) + len(smaller.nedges)) - (len(larger.edges) + len(larger.nedges))) def area(self, **kwargs): return 1.0 def random(self): network = BayesNet(**self.config.__properties__) for i in xrange(5): self.proposal.search(network) return network def extent(self): return self.nedges, self.edges #raise NotImplementedError("Bayesian networks do not have a " # "well-defined notion of spatial extent; " # "If you have something in mind, please " # "subclass the space or submit a pull " # "request.") def hash(self, point): point.computeEdgeStatistics() return str(point.edges)
class BinaryBayesStructure(Binary, PreBayesSpace): """A binary genotype with a Bayesian network structure phenotype. Bits indicate the presence or absence of an edge. Built on top of a variable space that determines the variables of the Bayes net. For example, a Euclidean space, say $\mathbb{R}^d$, would have $d$ :class:`GaussianVariable`s. Or, a Binary space would have :class:`BinaryVariable`s. The default choice of variable is controlled by the ``_mapping`` class variable based on the ``type`` field of the variable space. To have mixed networks, use a :class:`Product` space. :param space: The space of variables :type space: :class:`Space` """ _mappings = { # map space types to bayesian variables np.ndarray: GaussianVariable, TernaryString: BinaryVariable, } def __init__(self, space): self.space = space self.sampler = DAGSampler() if hasattr(space, 'dim'): self.numVariables = space.dim else: raise ValueError("Cannot determine the number of dimensions " "for BinaryBayesStructure space based on given " "space; expected space to have property dim " "indicating the number of required variables. ") super(BinaryBayesStructure, self).__init__(self.numVariables**2) self.config = Config(numVariables=self.numVariables, variableGenerator=self.variable, randomizer=self.randomize, sampler=self.sample) self.proposal = StructureProposal(**self.config.__properties__) self.config.structureGenerator = self.proposal def convert(self, x): if not isinstance(x, self.type): cname = self.__class__.__name__ raise ValueError("Type mismatch in {0}.convert".format(cname)) try: net = BayesNet(**self.config.__properties__) edges = [] indexMap = {} for var in net.variables: indexMap[var.index] = var self.proposal.network = net for i in xrange(x.length): if x[i]: frm, to = i % self.numVariables, i // self.numVariables child = indexMap[frm] parent = indexMap[to] try: self.proposal.addEdge(child, parent, self.config.data) except CyclicException: pass self.proposal.network = None return net except Exception: traceback.print_exc() raise ValueError("Unable to convert point due to exception")
class BayesNetStructure(Space, PreBayesSpace): """Space for Bayesian network structure search. Built on top of a variable space that determines the variables of the Bayes net. For example, a Euclidean space, say $\mathbb{R}^d$, would have $d$ :class:`GaussianVariable`s. Or, a Binary space would have :class:`BinaryVariable`s. The default choice of variable is controlled by the ``_mapping`` class variable based on the ``type`` field of the variable space. To have mixed networks, use a :class:`Product` space. :param space: The space of variables :type space: :class:`Space` """ _mappings = { # map space types to bayesian variables np.ndarray: GaussianVariable, TernaryString: BinaryVariable, } def __init__(self, space): super(BayesNetStructure, self).__init__(BayesNet) self.space = space self.sampler = DAGSampler() if hasattr(space, 'dim'): self.numVariables = space.dim else: raise ValueError("Cannot determine the number of dimensions " "for BayesNetStructure space based on given " "space; expected space to have property dim " "indicating the number of required variables. ") self.config = Config(numVariables=self.numVariables, variableGenerator=self.variable, randomizer=self.randomize, sampler=self.sample) self.proposal = StructureProposal(**self.config.__properties__) self.config.structureGenerator = self.proposal self.edges = [] self.nedges = [] def in_bounds(self, network, **kwargs): c = network.config return (isinstance(network, BayesNet) and len(network.variables) == self.numVariables and np.all([v.__class__ == self.variable(v.index,c).__class__ for v in network.variables])) def proportion(self, smaller, larger, index): return 2.0 ** ((len(smaller.edges) + len(smaller.nedges)) - (len(larger.edges) + len(larger.nedges))) def area(self, **kwargs): return 1.0 def random(self): network = BayesNet(**self.config.__properties__) for i in xrange(5): self.proposal.search(network) return network def extent(self): return self.nedges, self.edges #raise NotImplementedError("Bayesian networks do not have a " # "well-defined notion of spatial extent; " # "If you have something in mind, please " # "subclass the space or submit a pull " # "request.") def hash(self, point): point.computeEdgeStatistics() return str(point.edges)
def __init__(self, **kwargs): super(Boa, self).__init__(**kwargs) self.network = BayesNet(numVariables=self.config.space.dim, **self.config.__properties__) self.network = StructureProposal(**self.config.__properties__).search(self.network) self.trained = False