def stepwise_e_step(self, data, varNames): '''collect sufficient statistics for each variable data: 2d numpy array varNames: list of string ''' ctp = NaturalCliqueTreePropagation(self._model) tree = ctp.cliqueTree() cliques = tree.cliques # set up evidence datacase = ContinuousDatacase.create(varNames) datacase.synchronize(self._model) for i in range(len(data)): datacase.putValues(data[i]) evidence = datacase.getEvidence() ctp.use(evidence) ctp.propagate() for j in range(len(cliques)): self.batchSufficientStatistics[j].add(cliques[j].potential) # construct variable to statisticMap variableStatisticMap = dict() for node in self._model.nodes: clique = tree.getClique(node.variable) index = cliques.index(clique) variableStatisticMap[node.variable] = ( self.sufficientStatistics[index], self.batchSufficientStatistics[index]) return variableStatisticMap
def initializeSufficientStatistics(self, batch_size): ctp = NaturalCliqueTreePropagation(self._model) ctp.initializePotentials() tree = ctp.cliqueTree() cliques = tree.cliques sufficientStatistics = [None] * len(cliques) batchSufficientStatistics = [None] * len(cliques) for i in range(len(cliques)): if isinstance(cliques[i], DiscreteClique): sufficientStatistics[i] = DiscreteCliqueSufficientStatistics( cliques[i], batch_size) batchSufficientStatistics[ i] = DiscreteCliqueSufficientStatistics( cliques[i], batch_size) elif isinstance(cliques[i], MixedClique): sufficientStatistics[i] = MixedCliqueSufficientStatistics( cliques[i], batch_size) batchSufficientStatistics[i] = MixedCliqueSufficientStatistics( cliques[i], batch_size) else: raise Exception("unknown type of clique") return sufficientStatistics, batchSufficientStatistics
def grad(self, x): datacase = ContinuousDatacase.create(self.varNames) datacase.synchronize(self._model) ctp = NaturalCliqueTreePropagation(self._model) num, dim = x.shape out = np.zeros((num, dim), dtype=np.float32) datacase.putValues(x) evidence = datacase.getEvidence() ctp.use(evidence) ctp.propagate() tree = ctp.cliqueTree() gradient = np.zeros((num, dim)) for node in self._model.getLeafNodes(): clique = tree.getClique(node.variable) cliquePotential = clique.potential.clone() cliquePotential.normalize() moGpotential = node.potential.clone() vars = moGpotential.continuousVariables value = evidence.getValues(vars) b = np.zeros(len(vars)) subgradient = np.zeros((num, len(vars))) for j in range(moGpotential.size): sol = np.linalg.solve(moGpotential.get(j).covar, (np.expand_dims(moGpotential.get(j).mu, axis=0) - value).T).T # subgradient += sol * np.expand_dims(cliquePotential.p[:, j], axis=1) subgradient += sol * np.expand_dims(np.exp(cliquePotential.logp[:, j]), axis=1) for j in range(len(vars)): index = datacase.variables.index(vars[j]) gradient[:, index] = subgradient[:, j] return gradient