Пример #1
0
    def init(self, graph):
        if self.known_cpds is None:
            self.known_cpds = []
        self.alpha = float(self.alpha)

        known = {cpd.scope[0] for cpd in self.known_cpds}
        self.unknown = set(self.scope) - known

        known_cpds = [CPD(cpd.scope, cpd.values) for cpd in self.known_cpds]
        unknown_cpds = []

        self.parents = find_parents(self.scope, graph)
        for v in self.unknown:
            pa_v = sorted(self.parents[v])
            f = Factor([v] + pa_v)

            val_pa_v = product(*(range(pa.k) for pa in pa_v))
            for assg in val_pa_v:
                dist = np.random.dirichlet([self.alpha / len(f.values)] * v.k)

                assg = list(assg)
                for i in range(v.k):
                    f.values[f.atoi([i] + assg)] = dist[i]

            unknown_cpds.append(CPD(f.scope, f.values))

        self.bn = BayesianNetwork(known_cpds + unknown_cpds)
Пример #2
0
    def optimal_decision_rule(self, scope):
        cf = self.id.chance_factors
        uf = Factor([], [0.0])
        for f in self.id.utility_factors:
            uf += f

        gd = GibbsDistribution(cf + [uf])
        ve = VariableElimination(gd)

        mu = ve.posterior(scope, normalize=False)
        assg_map = [scope.index(v) for v in mu.scope]
        ind = mu.scope.index(scope[0])

        rule = Factor(scope, np.zeros(np.prod([v.k for v in scope])))
        n = int(np.prod([v.k for v in scope[1:]]))

        for i in range(n):
            assg = rule.itoa(i)

            assg_mu = np.array(assg)[assg_map]
            assg_mu[ind] = -1

            assg_max = [mu.argmax(assg_mu)] + list(assg[1:])

            rule.values[rule.atoi(assg_max)] = 1.0

        return CPD(rule.scope, rule.values)
Пример #3
0
    def init(self, graph):
        if self.known_cpds is None:
            self.known_cpds = []
        self.alpha = float(self.alpha)

        known = {cpd.scope[0] for cpd in self.known_cpds}
        self.unknown = set(self.scope) - known

        known_cpds = [CPD(cpd.scope, cpd.values) for cpd in self.known_cpds]
        unknown_cpds = []

        self.parents = find_parents(self.scope, graph)
        for v in self.unknown:
            pa_v = sorted(self.parents[v])
            f = Factor([v] + pa_v)

            val_pa_v = product(*(range(pa.k) for pa in pa_v))
            for assg in val_pa_v:
                dist = np.random.dirichlet([self.alpha / len(f.values)] * v.k)

                assg = list(assg)
                for i in range(v.k):
                    f.values[f.atoi([i] + assg)] = dist[i]

            unknown_cpds.append(CPD(f.scope, f.values))

        self.bn = BayesianNetwork(known_cpds + unknown_cpds)
Пример #4
0
    def optimal_decision_rule(self, scope):
        cf = self.id.chance_factors
        uf = Factor([], [0.0])
        for f in self.id.utility_factors:
            uf += f

        gd = GibbsDistribution(cf + [uf])
        ve = VariableElimination(gd)

        mu = ve.posterior(scope, normalize=False)
        assg_map = [scope.index(v) for v in mu.scope]
        ind = mu.scope.index(scope[0])

        rule = Factor(scope, np.zeros(np.prod([v.k for v in scope])))
        n = int(np.prod([v.k for v in scope[1:]]))

        for i in range(n):
            assg = rule.itoa(i)

            assg_mu = np.array(assg)[assg_map]
            assg_mu[ind] = -1

            assg_max = [mu.argmax(assg_mu)] + list(assg[1:])

            rule.values[rule.atoi(assg_max)] = 1.0

        return CPD(rule.scope, rule.values)
Пример #5
0
    def maximum_a_posteriori(self, evidence=[]):
        gd = self.gd.reduce(evidence)

        elim_variables = set([v for f in gd.factors for v in f.scope])

        gm = MinFillElimination(gd.factors)
        elim_variables = gm.ordering(elim_variables)

        factors = gd.factors

        phis = []
        for v in elim_variables:
            factor = reduce(lambda x, y: x * y,
                            [f for f in factors if v in f.scope],
                            Factor([], np.array([1.0])))

            phis.append(factor)

            factor = factor.maximize(v)
            factors = [f for f in factors if v not in f.scope] + [factor]

        assgmap = dict()
        for (i, f) in reversed(list(enumerate(phis))):
            assg = [0] * len(f.scope)

            for j, v in enumerate(f.scope):
                if v == elim_variables[i]:
                    assg[j] = -1
                else:
                    assg[j] = assgmap[v]

            assgmap[elim_variables[i]] = f.argmax(assg)

        return [(v, assgmap[v]) for v in elim_variables]
Пример #6
0
    def refit(self, graph):
        parents = find_parents(self.scope, graph)

        new_scopes = set()
        for v in self.scope:
            scope = tuple([v] + sorted(parents[v]))
            new_scopes.add(scope)

        old_scopes = set(self.stats.keys())

        remove_c = len(old_scopes | new_scopes) - self.maxlen
        if remove_c > 0:
            for key in self.stats.keys():
                if key not in new_scopes:
                    del self.stats[key]
                    remove_c -= 1

                if remove_c <= 0:
                    break

        self.last_scopes = new_scopes

        new_scopes = new_scopes - old_scopes
        for scope in new_scopes:
            self.stats[scope] = Factor(scope)

        self.count_occurences(new_scopes)

        return self
Пример #7
0
def six_variables():
    M = RandomVar('Market', 3)
    S = RandomVar('Survey', 4)  # S = 3 means no survey

    T = RandomVar('Test', 2)
    F = RandomVar('Found', 2)

    uMF = Factor([M, F], [0, -7, 0, 5, 0, 20])
    uT = Factor([T], [0, -1])

    cM = CPD([M], [0.5, 0.3, 0.2])

    cST = CPD([S, M, T], [
        0.0, 0.6, 0.0, 0.3, 0.0, 0.1, 0.0, 0.3, 0.0, 0.4, 0.0, 0.4, 0.0, 0.1,
        0.0, 0.3, 0.0, 0.5, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0
    ])

    # Alternative decision rules for F given S
    dFS_1 = CPD([F, S], [0, 0, 0, 1, 1, 1, 1, 0])
    dFS_2 = CPD([F, S], [1, 0, 0, 0, 0, 1, 1, 1])  # Optimal

    # Alternative decision rules for T
    dT_1 = CPD([T], [1.0, 0.0])
    dT_2 = CPD([T], [0.0, 1.0])  # Optimal

    id = InfluenceDiagram([cM, cST], [uMF, uT])
    eu = ExpectedUtility(id)

    print(eu.expected_utility([dFS_1, dT_1]))
    print(eu.expected_utility([dFS_1, dT_2]))
    print(eu.expected_utility([dFS_2, dT_1]))
    print(eu.expected_utility([dFS_2, dT_2]))

    # New influence diagram with a single decision rule
    dT = dT_2

    id2 = InfluenceDiagram([cM, cST, dT], [uMF, uT])
    eu2 = ExpectedUtility(id2)

    dFS_optimal = eu2.optimal_decision_rule([F, S])
    print(eu.expected_utility([dFS_optimal, dT]))
Пример #8
0
    def getFactor(self, conditions):
        newTable = dict(self.table)
        for var in conditions:
            # We need to fix the entry for the var in this factors
            if var in self.factors:
                loc = self.factors.index(var)
                newTable = {
                    key: newTable[key]
                    for key in newTable if key[loc] == conditions[var]
                }

        return Factor(self.factors, newTable)
Пример #9
0
    def fit(self, X, graph):
        self.X = np.array(X)
        self.stats = OrderedDict()

        new_scopes = set()
        parents = find_parents(self.scope, graph)
        for v in self.scope:
            scope = tuple([v] + sorted(parents[v]))
            self.stats[scope] = Factor(scope)
            new_scopes.add(scope)

        self.last_scopes = new_scopes
        self.count_occurences(new_scopes)

        return self
Пример #10
0
    def posterior(self, hypothesis, evidence=[], normalize=True):
        gd = self.gd.reduce(evidence)
        elim_variables = set(
            [v for f in gd.factors for v in f.scope if v not in hypothesis])

        gm = MinFillElimination(gd.factors)
        elim_variables = gm.ordering(elim_variables)

        factors = gd.factors

        for v in elim_variables:
            factor = reduce(lambda x, y: x * y,
                            [f for f in factors if v in f.scope],
                            Factor([], np.array([1.0])))
            factor = factor.marginalize(v)
            factors = [f for f in factors if v not in f.scope] + [factor]

        return GibbsDistribution(factors).joint(normalize)
Пример #11
0
def three_variables():
    M = RandomVar('Market', 3)
    F = RandomVar('Found', 2)

    uMF = Factor([M, F], [0, -7, 0, 5, 0, 20])

    cM = CPD([M], [0.5, 0.3, 0.2])

    # Alternative decision rules for F
    dF_1 = CPD([F], [1.0, 0])
    dF_2 = CPD([F], [0, 1.0])  # Optimal

    id = InfluenceDiagram([cM], [uMF])
    eu = ExpectedUtility(id)

    print(eu.expected_utility([dF_1]))
    print(eu.expected_utility([dF_2]))

    print(eu.optimal_decision_rule([F]))
Пример #12
0
def die():
    # Parameters
    # d1_ = [0.2, 0.0, 0.5, 0.1, 0.1, 0.1]
    # d2_ = [0.2, 0.3, 0.1, 0.05, 0.05, 0.3]
    d1_ = [0.1, 0.9]
    d2_ = [0.6, 0.4]
    n_samples = 5000

    n_iterations = 10
    n_restarts = 2
    verbose = 2

    # Model creation
    if len(d1_) != len(d2_):
        raise Exception('The die should have the same cardinality')

    h = RandomVar('h', 2)
    o1 = RandomVar('o1', len(d1_))
    o2 = RandomVar('o2', len(d2_))

    f_h = CPD([h], [0.5, 0.5])
    f_o1_h = Factor([o1, h])
    f_o2_h = Factor([o2, h])

    for i in range(len(f_o1_h.values)):
        o_, h_ = f_o1_h.itoa(i)
        f_o1_h.values[i] = d1_[o_] if h_ == 0 else d2_[o_]
        f_o2_h.values[i] = d2_[o_] if h_ == 0 else d1_[o_]

    f_o1_h = CPD(f_o1_h.scope, f_o1_h.values)
    f_o2_h = CPD(f_o2_h.scope, f_o2_h.values)

    bn = BayesianNetwork([f_h, f_o1_h, f_o2_h])

    # Sampling from true model
    fs = ForwardSampler(bn)
    fs.sample(n_samples)
    scope, X = fs.samples_to_matrix()

    em = ExpectationMaximization(scope, known_cpds=[f_h],
                                 n_iterations=n_iterations,
                                 n_restarts=n_restarts, alpha=10.0,
                                 verbose=verbose)

    print('True log-likelihood (no missing variables):')
    print(em.log_likelihood(X, bn))

    print('Maximum log-likelihood (no missing variables):')
    ls = LikelihoodScore(scope)
    ls.fit(X, bn.graph())
    print(ls.score)

    # Hiding variable
    X[:, scope.index(h)] = -1

    print('True log-likelihood (missing variables):')
    print(em.log_likelihood(X, bn))

    bn_pred = em.fit_predict(X, bn.graph())
    print('Best log-likelihood (missing variables)')
    print(em.log_likelihood(X, bn_pred))

    # Estimation results
    print('Results:')
    f_o1_h = [f for f in bn_pred.factors if f.scope[0] == o1][0]
    f_o2_h = [f for f in bn_pred.factors if f.scope[0] == o2][0]

    d = np.zeros(o1.k)
    d1 = np.zeros(o1.k)
    d2 = np.zeros(o1.k)

    with printoptions(precision=3):
        print('d1: {0}'.format(d1_))

        for i in range(o1.k):
            d[i] = f_o1_h.values[f_o1_h.atoi([i, 0])]
        print('d1 according to o1: {0}'.format(d))
        d1 += d

        for i in range(o2.k):
            d[i] = f_o2_h.values[f_o2_h.atoi([i, 1])]
        print('d1 according to o2: {0}'.format(d))
        d1 += d

        print('d2: {0}'.format(d2_))
        for i in range(o1.k):
            d[i] = f_o1_h.values[f_o1_h.atoi([i, 1])]
        print('d2 according to o1: {0}'.format(d))
        d2 += d

        for i in range(o2.k):
            d[i] = f_o2_h.values[f_o2_h.atoi([i, 0])]
        print('d2 according to o2: {0}'.format(d))
        d2 += d

        print('Average estimate:')
        print('d1: {0}'.format(d1/2.))
        print('d2: {0}'.format(d2/2.))
Пример #13
0
    def joint(self, normalize=True):
        f = Factor([], [1.0])
        for fi in self.factors:
            f = f * fi

        return f.normalize() if normalize else f
Пример #14
0
    def joint(self, normalize=True):
        f = Factor([], [1.0])
        for fi in self.factors:
            f = f * fi

        return f.normalize() if normalize else f
Пример #15
0
    def fit(self, X, graph):
        """Find the parameters for a probabilistic graphical model, given a
        graph and a data set that possibly contains missing data.

        After fitting, the model is available as a BayesianNetwork `self.bn`.

        Parameters
        ----------
        X : two-dimensional np.array or python matrix of integers
            Matrix representing the observations. The value `X[i, j]` should
            correspond to the discrete random variable `self.scope[j]` in
            sample element `i`. The number -1 represents a missing value.
        graph: dict from RandomVariables to sets of RandomVariables
            the graph for the probabilistic graphical model
        """
        var_index = {v: i for (i, v) in enumerate(self.scope)}

        best_ll = float('-inf')
        best_bn = None
        for irestart in range(self.n_restarts):
            if self.verbose > 0:
                print('Restart {0}.'.format(irestart + 1))

            self.init(graph)

            known_cpds = [
                CPD(cpd.scope, cpd.values) for cpd in self.known_cpds
            ]

            M_scopes = []
            for v in self.unknown:
                M_scopes.append([v] + sorted(self.parents[v]))

            for iiteration in range(self.n_iterations):
                ess = [Factor(M_scope) for M_scope in M_scopes]

                for x in X:
                    evidence = []
                    hidden = []
                    for (i, xi) in enumerate(x):
                        if xi == -1:
                            hidden.append(self.scope[i])
                        else:
                            evidence.append((self.scope[i], xi))

                    for M in ess:
                        M_assg = x[[var_index[v] for v in M.scope]]

                        M_h = []
                        for (i, v) in enumerate(M.scope):
                            if M_assg[i] == -1:
                                M_h.append(v)

                        if M_h:
                            ve = VariableElimination(self.bn)
                            f = ve.posterior(M_h, evidence=evidence)

                            Mh_index = [M.scope.index(v) for v in f.scope]

                            for i in range(len(f.values)):
                                f_assg = f.itoa(i)
                                M_assg[Mh_index] = f_assg
                                M.values[M.atoi(M_assg)] += f.values[i]
                        else:
                            M.values[M.atoi(M_assg)] += 1

                self.bn = BayesianNetwork([M.to_cpd()
                                           for M in ess] + known_cpds)

                if self.verbose > 1:
                    print('Iteration {0}. '.format(iiteration + 1))
                if self.verbose > 2:
                    ll = self.log_likelihood(X, self.bn)
                    print('Current log-likelihood {0}.'.format(ll))

            ll = self.log_likelihood(X, self.bn)
            print('Final log-likelihood {0}.'.format(ll))
            if ll > best_ll:
                best_ll = ll
                best_bn = self.bn

        self.bn = best_bn

        return self