def _repeat_param(param, length): # This function repeats out a parameter so that time-homogeneous models, # which only have one tuple of lds pair parameters, are represented as # time-inhomogeneous models (with a list of T lds pair parameter tuples). if depth(param) == 1: param = [param] * length elif len(param) != length: param = zip(*param) assert depth(param) == 2 and len(param) == length return param
def _repeat_param(param, length): # This function repeats out a parameter so that time-homogeneous models, # which only have one tuple of lds pair parameters, are represented as # time-inhomogeneous models (with a list of T lds pair parameter tuples). if depth(param) == 1: param = [param]*length elif len(param) != length: param = zip(*param) assert depth(param) == 2 and len(param) == length return param
def natural_smoother_general(forward_messages, init_params, pair_params, node_params): prediction_messages, filter_messages = uninterleave(forward_messages) inhomog = depth(pair_params) == 2 T = len(prediction_messages) pair_params, orig_pair_params = _repeat_param(pair_params, T - 1), pair_params node_params = list(zip(*_canonical_node_params(node_params))) def unit(filtered_message): J, h = filtered_message mu, Sigma = natural_to_mean(filtered_message) ExxT = Sigma + np.outer(mu, mu) return tuple_(J, h, mu), [(mu, ExxT, 0.)] def bind(result, step): next_smooth, stats = result J, h, (mu, ExxT, ExxnT) = step(next_smooth) return tuple_(J, h, mu), [(mu, ExxT, ExxnT)] + stats rts = lambda next_pred, filtered, pair_param: lambda next_smooth: \ natural_rts_backward_step(next_smooth, next_pred, filtered, pair_param) steps = reversed( list( map(rts, prediction_messages[1:], filter_messages[:-1], pair_params))) _, expected_stats = monad_runner(bind)(unit(filter_messages[-1]), steps) def make_init_stats(a): mu, ExxT, _ = a return (ExxT, mu, 1., 1.)[:len(init_params)] def make_pair_stats(a, b): (mu, ExxT, ExnxT), (mu_n, ExnxnT, _) = a, b return ExxT, ExnxT.T, ExnxnT, 1. is_diagonal = node_params[0][0].ndim == 1 if is_diagonal: def make_node_stats(a): mu, ExxT, _ = a return np.diag(ExxT), mu, 1. else: def make_node_stats(a): mu, ExxT, _ = a return ExxT, mu, 1. E_init_stats = make_init_stats(expected_stats[0]) E_pair_stats = list( map(make_pair_stats, expected_stats[:-1], expected_stats[1:])) E_node_stats = list(map(make_node_stats, expected_stats)) if not inhomog: E_pair_stats = reduce(add, E_pair_stats, zeros_like(orig_pair_params)) E_node_stats = list(map(np.array, list(zip(*E_node_stats)))) return E_init_stats, E_pair_stats, E_node_stats
def natural_smoother_general(forward_messages, init_params, pair_params, node_params): prediction_messages, filter_messages = uninterleave(forward_messages) inhomog = depth(pair_params) == 2 T = len(prediction_messages) pair_params, orig_pair_params = _repeat_param(pair_params, T-1), pair_params node_params = zip(*_canonical_node_params(node_params)) def unit(filtered_message): J, h = filtered_message mu, Sigma = natural_to_mean(filtered_message) ExxT = Sigma + np.outer(mu, mu) return make_tuple(J, h, mu), [(mu, ExxT, 0.)] def bind(result, step): next_smooth, stats = result J, h, (mu, ExxT, ExxnT) = step(next_smooth) return make_tuple(J, h, mu), [(mu, ExxT, ExxnT)] + stats rts = lambda next_pred, filtered, pair_param: lambda next_smooth: \ natural_rts_backward_step(next_smooth, next_pred, filtered, pair_param) steps = reversed(map(rts, prediction_messages[1:], filter_messages[:-1], pair_params)) _, expected_stats = monad_runner(bind)(unit(filter_messages[-1]), steps) def make_init_stats(a): mu, ExxT, _ = a return (ExxT, mu, 1., 1.)[:len(init_params)] def make_pair_stats(a, b): (mu, ExxT, ExnxT), (mu_n, ExnxnT, _) = a, b return ExxT, ExnxT.T, ExnxnT, 1. is_diagonal = node_params[0][0].ndim == 1 if is_diagonal: def make_node_stats(a): mu, ExxT, _ = a return np.diag(ExxT), mu, 1. else: def make_node_stats(a): mu, ExxT, _ = a return ExxT, mu, 1. E_init_stats = make_init_stats(expected_stats[0]) E_pair_stats = map(make_pair_stats, expected_stats[:-1], expected_stats[1:]) E_node_stats = map(make_node_stats, expected_stats) if not inhomog: E_pair_stats = reduce(add, E_pair_stats, zeros_like(orig_pair_params)) E_node_stats = map(np.array, zip(*E_node_stats)) return E_init_stats, E_pair_stats, E_node_stats