コード例 #1
0
def update_mean(manifold, solver, data, land, k, param):
    N, D = data.shape
    Logmaps = land['Logmaps'][k, :, :]  # N x D
    mu = land['means'][k, :].reshape(-1, 1)  # D x 1
    Sigma = land['Sigmas'][k, :, :]  # D x D
    Resp = land['Resp'][:, k].reshape(-1, 1)  # N x 1
    Const = land['Consts'][k]
    V_samples = land['V_samples'][
        k, :, :]  # S x D, Use the samples from the last Const estimation
    volM_samples = land['volM_samples'][:, k].reshape(-1, 1)  # S x 1
    Z_eucl = land['Z_eucl'][k]

    for iteration in range(param['max_iter']):

        print('[Updating mean: {}] [Iteration: {}/{}]'.format(
            k + 1, iteration + 1, param['max_iter']))

        # Use the non-failed only
        inds = np.isnan(Logmaps[:, 0])  # The failed logmaps
        grad_term1 = Logmaps[~inds, :].T @ Resp[~inds, :] / Resp[
            ~inds, :].sum()
        grad_term2 = V_samples.T @ volM_samples.reshape(
            -1, 1) * Z_eucl / (Const * param['S'])

        # We do not multiply in front the invSigma because we use the steepest direction
        grad = (grad_term1 - grad_term2)
        curve, failed = geodesics.expmap(manifold, mu,
                                         grad * param['step_size'])
        mu_new = curve(1)[0]

        # Compute the logmaps for the new mean
        for n in range(N):
            _, logmap, curve_length, failed, sol \
                = geodesics.compute_geodesic(solver, manifold, mu_new, data[n, :].reshape(-1, 1))
            if failed:
                Logmaps[n, :] = np.nan  # We do NOT use the straight geodesic
            else:
                Logmaps[n, :] = logmap.flatten()

        # Compute the constant for the new mean
        Const, V_samples, volM_samples, Z_eucl, _ = \
            estimate_norm_constant(manifold, mu_new, Sigma, param['S'])

        cond = np.sum((mu - mu_new)**2)  # The condition to stop
        mu = mu_new.copy()
        if cond < param['tol']:  # Stop if lower than tolerance the change
            break

    return mu.flatten(), Logmaps, Const, V_samples, volM_samples.flatten(
    ), Z_eucl
コード例 #2
0
def land_predict(manifold, solver, land, data):
    N, D = data.shape
    K = land['means'].shape[0]
    responsibilities = np.zeros((N, K))
    Logmaps = np.zeros((K, N, D))

    for k in range(K):
        mu = land['means'][k, :].reshape(-1, 1)
        for n in range(N):
            print('[Center: {}/{}] [Point: {}/{}]'.format(k + 1, K, n + 1, N))
            _, logmap, _, failed, _ \
                = geodesics.compute_geodesic(solver, manifold, mu, data[n, :].reshape(-1, 1))
            Logmaps[k, n, :] = logmap.flatten(
            )  # Use the geodesic even if it is the failed line

    for k in range(K):
        responsibilities[:, k] = land['Weights'][k] \
                             * evaluate_pdf_land(Logmaps[k, :, :],
                                                                   land['Sigmas'][k, :, :],
                                                                   land['Consts'][k]).flatten()

    responsibilities = responsibilities / responsibilities.sum(axis=1,
                                                               keepdims=True)
    return responsibilities
コード例 #3
0
# Construct the manifold
manifold_latent = manifolds.MlpMeanInvRbfVar(G_model_parameters)
# Rescale the metric such that the maximum measure on the data to be 1
beta_rbf = 1 / (np.sqrt(
    np.linalg.det(manifold_latent.metric_tensor(MU_Z_data.T)).max()))
G_model_parameters['beta'] = beta_rbf**(2 / d)  # Rescale the pull-back metric
manifold_latent = manifolds.MlpMeanInvRbfVar(G_model_parameters)

z1min, z2min = MU_Z_data.min(0) - 0.5
z1max, z2max = MU_Z_data.max(0) + 0.5
plt.figure()
utils.plot_measure(manifold_latent, np.linspace(z1min, z1max, 100),
                   np.linspace(z2min, z2max, 100))
utils.my_plot(MU_Z_data, c='k', s=5, alpha=0.3)

# Compute some random curves using a heuristic graph solver
GRAPH_DATA = KMeans(n_clusters=100, n_init=30,
                    max_iter=1000).fit(MU_Z_data).cluster_centers_
solver_graph = geodesics.SolverGraph(manifold_latent,
                                     data=GRAPH_DATA,
                                     kNN_num=5,
                                     tol=1e-2)
for _ in range(20):
    ind_0, ind_1 = np.random.choice(N_train, 2, replace=False)
    c0 = MU_Z_data[ind_0, :].reshape(-1, 1)
    c1 = MU_Z_data[ind_1, :].reshape(-1, 1)

    curve_graph, logmap_graph, curve_length_graph, failed_graph, solution_graph \
        = geodesics.compute_geodesic(solver_graph, manifold_latent, c0, c1)
    geodesics.plot_curve(curve_graph, c='r', linewidth=2)
コード例 #4
0
def land_mixture_model(manifold, solver, data, param):
    K = param['K']

    N, D = data.shape

    # Initializations
    solutions = {}

    # Initialize the land
    land = {}
    land['Resp'] = np.zeros((N, K))  # 1 failed, 0 not failed
    land['Logmaps'] = np.zeros((K, N, D))
    land['Logmaps'][:] = np.nan
    land['Consts'] = np.zeros((K, 1))
    land['means'] = param['means'].copy()
    land['Sigmas'] = np.zeros((K, D, D))
    land['Weights'] = np.zeros((K, 1))  # The mixing components
    land['Failed'] = np.zeros((N, K))  # 1 failed, 0 not failed
    land['V_samples'] = np.zeros((K, param['S'], D))
    land['volM_samples'] = np.zeros((param['S'], K))
    land['Z_eucl'] = np.zeros((K, 1))

    # Initialize components
    for k in range(K):
        for n in range(N):

            print('[Initialize: {}/{}] [Process point: {}/{}]'.format(
                k + 1, K, n + 1, N))
            key = 'k_' + str(k) + '_n_' + str(n)
            _, logmap, curve_length, failed, sol \
                = geodesics.compute_geodesic(solver, manifold,
                                             land['means'][k, :].reshape(-1, 1), data[n, :].reshape(-1, 1))
            if failed:
                land['Failed'][n, k] = True
                land['Logmaps'][
                    k, n, :] = logmap.flatten()  # The straight line geodesic
                land['Resp'][
                    n,
                    k] = 1 / curve_length  # If points are far lower responsibility
                solutions[key] = None
            else:
                land['Failed'][n, k] = False
                land['Logmaps'][k, n, :] = logmap.flatten()
                land['Resp'][n, k] = 1 / curve_length
                solutions[key] = sol

    land['Resp'] = land['Resp'] / land['Resp'].sum(
        axis=1, keepdims=True)  # Compute the responsibilities
    land['Weights'] = np.sum(land['Resp'], axis=0).reshape(-1, 1) / N

    # Use the closest points to estimate the Sigmas and the normalization constants
    for k in range(K):
        inds_k = (land['Resp'].argmax(axis=1) == k
                  )  # The closest points to the k-th center
        land['Sigmas'][k, :, :] = np.cov(land['Logmaps'][k, inds_k, :].T) * (
            1 - param['mixing_param']) + np.eye(D) * param['mixing_param']
        land['Consts'][k], land['V_samples'][k, :, :], land['volM_samples'][:, k], land['Z_eucl'][k], _ \
            = estimate_norm_constant(manifold, land['means'][k, :].reshape(-1, 1), land['Sigmas'][k, :, :], param['S'])

    negLogLikelihood = compute_negLogLikelihood(land)
    negLogLikelihoods = [negLogLikelihood]

    for iteration in range(param['max_iter']):
        print('[Iteration: {}/{}] [Negative log-likelihood: {}]'.format(
            iteration + 1, param['max_iter'], negLogLikelihood))

        # ----- E-step ----- #
        for k in range(K):
            land['Resp'][:, k] = land['Weights'][k] \
                                 * evaluate_pdf_land(land['Logmaps'][k, :, :],
                                                                       land['Sigmas'][k, :, :],
                                                                       land['Consts'][k]).flatten()
        land['Resp'] = land['Resp'] / land['Resp'].sum(axis=1, keepdims=True)

        # ----- M-step ----- #
        # Update the means
        for k in range(K):
            land['means'][k, :], land['Logmaps'][k, :, :], land['Consts'][k], land['V_samples'][k, :, :], land['volM_samples'][:, k], land['Z_eucl'][k] = \
                update_mean(manifold, solver, data, land, k, param)
        # Update the covariances
        for k in range(K):
            land['Sigmas'][k, :, :], land['Consts'][k], land['V_samples'][k, :, :], land['volM_samples'][:, k], land['Z_eucl'][k] = \
                update_Sigma(manifold, solver, data, land, k, param)
        # Update the constants
        for k in range(K):
            land['Consts'][k], land['V_samples'][k, :, :], land['volM_samples'][:, k], land['Z_eucl'][k], _ \
                = estimate_norm_constant(manifold, land['means'][k, :].reshape(-1, 1), land['Sigmas'][k, :, :], param['S'])
        # Update the mixing components
        land['Weights'] = np.sum(land['Resp'], axis=0).reshape(-1, 1) / N

        # Compute the new likelihood and store it
        newNegLogLikelihood = compute_negLogLikelihood(land)
        negLogLikelihoods = np.concatenate(
            (negLogLikelihoods, [newNegLogLikelihood]), axis=0)

        # Check the difference in log-likelihood between updates
        if (newNegLogLikelihood - negLogLikelihood)**2 < param['tol']:
            break
        else:
            negLogLikelihood = newNegLogLikelihood

    land['negLogLikelihoods'] = negLogLikelihoods
    return land
コード例 #5
0
                                                 data=GRAPH_DATA,
                                                 kNN_num=int(np.log(N_nodes)),
                                                 tol=1e-2)

Dists_euclidean = np.zeros((N_points, N_points))
Dists_pca = np.zeros((N_points, N_points))
Dists_lda = np.zeros((N_points, N_points))
Dists_cost = np.zeros((N_points, N_points))

for n1 in range(N_points):
    for n2 in range(n1 + 1, N_points):
        c0 = POINTS[n1, :].reshape(-1, 1)
        c1 = POINTS[n2, :].reshape(-1, 1)

        _, _, curve_length_euclidean, _, _ \
            = geodesics.compute_geodesic(solver_graph_latent_euclidean, manifold_latent_euclidean, c0, c1)
        _, _, curve_length_pca, _, _ \
            = geodesics.compute_geodesic(solver_graph_latent_pca, manifold_latent_pca, c0, c1)
        _, _, curve_length_lda, _, _ \
            = geodesics.compute_geodesic(solver_graph_latent_lda, manifold_latent_lda, c0, c1)
        _, _, curve_length_cost, _, _ \
            = geodesics.compute_geodesic(solver_graph_latent_cost, manifold_latent_cost, c0, c1)

        Dists_euclidean[n1, n2] = curve_length_euclidean
        Dists_pca[n1, n2] = curve_length_pca
        Dists_lda[n1, n2] = curve_length_lda
        Dists_cost[n1, n2] = curve_length_cost

Res_euclidean = Dists_euclidean[np.triu_indices(N_points, k=1)]
Res_pca = Dists_pca[np.triu_indices(N_points, k=1)]
Res_lda = Dists_lda[np.triu_indices(N_points, k=1)]
コード例 #6
0
# Initialize the geodesic solvers
solver_bvp = geodesics.SolverBVP(NMax=1000, tol=1e-1)
solver_fp = geodesics.SolverFP(D=2, N=10, tol=1e-1)
N_nodes = 30
solver_graph = geodesics.SolverGraph(manifold, data=KMeans(n_clusters=N_nodes, n_init=30, max_iter=1000).fit(data).cluster_centers_,
                                     kNN_num=int(np.log(N_nodes)), tol=1e-2)
solver_comb = geodesics.SolverComb(solver_1=solver_bvp, solver_2=solver_graph)


# Compute the shortest path between two points
c0 = utils.my_vector([-1, 0])
c1 = utils.my_vector([1, 0])

curve_bvp, logmap_bvp, curve_length_bvp, failed_bvp, solution_bvp \
                = geodesics.compute_geodesic(solver_bvp, manifold, c0, c1)
geodesics.plot_curve(curve_bvp, c='r', linewidth=2, label='bvp')

curve_fp, logmap_fp, curve_length_fp, failed_fp, solution_fp \
                = geodesics.compute_geodesic(solver_fp, manifold, c0, c1)
geodesics.plot_curve(curve_fp, c='g', linewidth=2, label='fp')

curve_graph, logmap_graph, curve_length_graph, failed_graph, solution_graph \
                = geodesics.compute_geodesic(solver_graph, manifold, c0, c1)
geodesics.plot_curve(curve_graph, c='m', linewidth=2, label='graph')

curve_comb, logmap_comb, curve_length_comb, failed_comb, solution_comb \
                = geodesics.compute_geodesic(solver_comb, manifold, c0, c1)
geodesics.plot_curve(curve_comb, c='y', linestyle='--', linewidth=2, label='comb (graph -> bvp)')

plt.legend()
コード例 #7
0
                                                      solver=solver,
                                                      data=LAND_DATA,
                                                      param=params)

# Plot the density
z1min, z2min = data.min(0) - 0.5
z1max, z2max = data.max(0) + 0.5
N_Z_grid = 20
Z_grid = utils.my_meshgrid(z1min, z1max, z2min, z2max, N=N_Z_grid)
Logmaps = np.zeros(
    (2, Z_grid.shape[0], data.shape[1]))  # The logmaps for each center
for k in range(2):
    for n in range(Z_grid.shape[0]):
        # If the solver fails then the logmap is overestimated (straight line)
        curve_bvp, logmap_bvp, curve_length_bvp, failed_bvp, solution_bvp \
            = geodesics.compute_geodesic(solver, manifold,
                                         land_res_prior['means'][k, :].reshape(-1, 1),
                                         Z_grid[n, :].reshape(-1, 1))
        Logmaps[k, n, :] = logmap_bvp.ravel()

pdf_vals = np.zeros((Z_grid.shape[0], 1))
for k in range(2):
    pdf_vals += land_res_prior['Weights'][k, 0] * (
        np.exp(-0.5 * np.diag(Logmaps[k, :, :] @ np.linalg.inv(
            land_res_prior['Sigmas'][k, :, :]) @ Logmaps[k, :, :].T)) /
        land_res_prior['Consts'][k, 0]).reshape(-1, 1)
plt.imshow(pdf_vals.reshape(N_Z_grid, N_Z_grid),
           interpolation='bicubic',
           extent=(z1min, z1max, z2min, z2max),
           origin='lower')