Beispiel #1
0
    def backward_pass(self, var, normalize=False):
        w = self.weights[var]
        if self.get_child_factors(var):
            phi = factor_product(*self.get_child_factors(var))
        else:
            phi = 1.0
        if self.children[var]:
            phi = factor_product(
                *[phi],
                *[self.messages[(child, var)] for child in self.children[var]])
        if self.parents[var]:
            phi = factor_product(*[phi],
                                 *[self.messages[(self.parents[var], var)]])

        phi.abs()
        for child in self.children[var]:
            wc = self.weights[child]
            m = self.messages[(child, var)].copy()
            self.messages[(var, child)] = factor_product(
                m.power(-1.0, inplace=False), phi.power(wc / w, inplace=False))
            self.messages[(var, child)].weightedsum(
                list(set(phi.variables) - set(m.variables)), wc)
            self.messages[(var,
                           child)].name = "M_" + str(var) + "->" + str(child)
            if normalize:
                self.messages[(var, child)].normalize()
Beispiel #2
0
    def update_reparam(self, ovar, method="projected_gradient"):
        if method == "projected_gradient":
            step_size = self.reparam_step_size
            b = {
                var: self.get_q(var).marginalize_except([ovar], inplace=False)
                for var in self.nvardict[ovar]
            }
            b_avg = np.sum(
                np.array([b[var].values for var in self.nvardict[ovar]]),
                0) / len(self.nvardict[ovar])
            for var in self.nvardict[ovar]:
                temp = b[var].copy()
                temp.values = np.exp(-step_size * (temp.values - b_avg))
                factor = self.model.get_factor(self.adj_factor_names[var][0])
                factor.product(temp)

        elif method == "fixedpoint":
            b = {
                var: self.get_q(var).marginalize_except([ovar], inplace=False)
                for var in self.nvardict[ovar]
            }
            b_avg = factor_product(*[
                b[var].power(self.weights[var], inplace=False)
                for var in self.nvardict[ovar]
            ])
            for var in self.nvardict[ovar]:
                temp = b[var].copy()
                temp.values = b_avg.values / b[var].values
                temp.power(self.weights[var])
                factor = self.model.get_factor(self.adj_factor_names[var][0])
                factor.product(temp)
Beispiel #3
0
 def forward_pass(self, var, normalize=False):
     if self.parents[var]:
         w = self.weights[var]
         self.messages[(var, self.parents[var])] = factor_product(
             *self.get_child_factors(var),
             *[self.messages[(child, var)] for child in self.children[var]])
         self.messages[(var, self.parents[var])].weightedsum(
             [self.ovardict[var]], w)
         if normalize:
             self.messages[(var, self.parents[var])].normalize()
Beispiel #4
0
    def get_q(self, var):
        w = self.weights[var]
        if self.get_child_factors(var):
            phi = factor_product(*self.get_child_factors(var))
        else:
            phi = 1.0

        if self.children[var]:
            phi = factor_product(
                *[phi],
                *[self.messages[(child, var)] for child in self.children[var]])
        if self.parents[var]:
            phi = factor_product(*[phi],
                                 *[self.messages[(self.parents[var], var)]])

        phi.abs()
        phi.power(1 / w)
        phi.normalize()
        phi.name = "q_" + str(var)
        return phi.copy()
Beispiel #5
0
    def compute_Z(self, add_time=False):
        if add_time:
            t = time()
        for ovar in self.model.variables:
            for var in self.nvardict[ovar]:
                self.forward_pass(var, normalize=False)

        Z = 1.0
        for var in self.variables:
            w = self.weights[var]
            if not self.parents[var]:
                phi = factor_product(
                    *self.get_child_factors(var), *[
                        self.messages[(child, var)]
                        for child in self.children[var]
                    ])
                Z *= phi.weightedsum([self.ovardict[var]], w,
                                     inplace=False).values

        self.Z = Z * np.exp(self.baselogZ)
        self.logZ = np.log(Z) + self.baselogZ
        if add_time:
            self.elapsed_time += time() - t
Beispiel #6
0
    def __init__(self, model, ibound):
        self.model = model.copy()
        self.logZ = 0.0
        self.Z = 0.0
        self.baselogZ = 0.0
        self.messages = {}
        self.reparam = {
            var: np.zeros(model.get_nstate(var))
            for var in model.variables
        }
        self.gauges = {
            var: Factor(
                "G" + str(var),
                [var + "_", var],
                [model.get_nstate(var),
                 model.get_nstate(var)],
                np.eye(model.get_nstate(var)),
            )
            for var in model.variables
        }
        self.build_cover_graph(ibound)

        for var in self.variables:
            if self.parents[var]:
                self.messages[(var, self.parents[var])] = factor_product(
                    *self.get_child_factors(var), *[
                        self.messages[(child, var)]
                        for child in self.children[var]
                    ])
                self.messages[(var, self.parents[var])].marginalize(
                    [self.ovardict[var]])
                self.messages[(var, self.parents[var])].values = np.full_like(
                    self.messages[(var, self.parents[var])].values, 1.0)
                self.messages[(var, self.parents[var])].name = (
                    "M_" + str(var) + str(self.parents[var]))

        for var in reversed(self.variables):
            if self.get_child_factors(var):
                phi = factor_product(*self.get_child_factors(var))
            else:
                phi = 1.0
            if self.children[var]:
                phi = factor_product(
                    *[phi], *[
                        self.messages[(child, var)]
                        for child in self.children[var]
                    ])
            if self.parents[var]:
                phi = factor_product(
                    *[phi], *[self.messages[(self.parents[var], var)]])

            for child in self.children[var]:
                m = self.messages[(child, var)].copy()
                self.messages[(var, child)] = factor_product(phi, m)
                self.messages[(var, child)].marginalize(
                    list(set(phi.variables) - set(m.variables)))
                self.messages[(var, child)].values = np.full_like(
                    self.messages[(var, child)].values, 1.0)
                self.messages[(
                    var, child)].name = "M_" + str(var) + "->" + str(child)

        self.reparam_step_size = 0.1
        self.weight_step_size = 0.1
        self.gauge_step_size = 0.005

        self.elapsed_time = 0.0
Beispiel #7
0
    def get_gauges_der_factor(self, ovariable, factor):
        factor_der = {
            gauge_idx: np.full_like(factor.values, 0.0)
            for gauge_idx, gauge_val in np.ndenumerate(
                self.gauges[ovariable].values)
        }
        temp = {
            gauge_idx: np.full_like(factor.values, 0.0)
            for gauge_idx, gauge_val in np.ndenumerate(
                self.gauges[ovariable].values)
        }
        gauge_list = {}
        if factor == self.model.get_adj_factors(ovariable)[0]:
            top_factor = factor.copy()
            factor_order = copy(factor.variables)
            for ovar in factor.variables:
                if ovar != ovariable:
                    if self.model.get_adj_factors(ovar).index(factor) == 0:
                        gauge = self.gauges[ovar].copy()
                    elif self.model.get_adj_factors(ovar).index(factor) == 1:
                        gauge = self.gauges[ovar].invT(inplace=False)

                    top_factor = factor_product(top_factor, gauge)
                    top_factor.marginalize([ovar])
                    top_factor.variables[top_factor.variables.index(
                        ovar + "_")] = ovar

            top_factor.values = top_factor.values.transpose(
                [top_factor.variables.index(ovar) for ovar in factor_order])
            top_factor.variables = copy(factor_order)

            for gauge_idx, gauge_val in np.ndenumerate(
                    self.gauges[ovar].values):
                for factor_idx, factor_val in np.ndenumerate(factor.values):
                    if gauge_idx[0] == factor_idx[factor.variables.index(
                            ovariable)]:
                        top_idx = list(copy(factor_idx))
                        top_idx[top_factor.variables.index(
                            ovariable)] = gauge_idx[1]
                        factor_der[gauge_idx][factor_idx] = top_factor.values[
                            tuple(top_idx)]

            return factor_der

        elif factor == self.model.get_adj_factors(ovariable)[1]:
            top_factor = factor.copy()
            factor_order = copy(factor.variables)

            for ovar in factor.variables:
                if ovar != ovariable:
                    if self.model.get_adj_factors(ovar).index(factor) == 0:
                        gauge = self.gauges[ovar].copy()
                    elif self.model.get_adj_factors(ovar).index(factor) == 1:
                        gauge = self.gauges[ovar].invT(inplace=False)

                    top_factor = factor_product(top_factor, gauge)
                    top_factor.marginalize([ovar])
                    top_factor.variables[top_factor.variables.index(
                        ovar + "_")] = ovar

            top_factor.values = top_factor.values.transpose(
                [top_factor.variables.index(ovar) for ovar in factor_order])
            top_factor.variables = copy(factor_order)

            for gauge_idx, gauge_val in np.ndenumerate(
                    self.gauges[ovar].values):
                for factor_idx, factor_val in np.ndenumerate(factor.values):
                    if gauge_idx[1] == factor_idx[factor.variables.index(
                            ovariable)]:
                        top_idx = list(copy(factor_idx))
                        top_idx[top_factor.variables.index(
                            ovariable)] = gauge_idx[0]
                        factor_der[gauge_idx][factor_idx] -= top_factor.values[
                            tuple(top_idx)]

            return factor_der
        else:
            print("Something wrong")
            return False