def generate_lds_clusters(cluster_centers, num_systems, cluster_radius, diagonalizable=True): """Generates clusters of linear dynamical systems. Args: cluster_centers: A list of LinearDynamicalSystem instances. num_systems: Total number of systems in all clusters. cluster_radius: Desired mean distance from the centers. Returns: - A list of LinearDynamicalSystem of size num_systems. - A list of true cluster ids. """ num_clusters = len(cluster_centers) cluster_id = np.random.randint(0, num_clusters, num_systems) hidden_state_dim = cluster_centers[0].hidden_state_dim for c in cluster_centers: if c.hidden_state_dim != hidden_state_dim: raise ValueError('Hidden state dimension mismatch.') generated_systems = [] dist_to_center = np.zeros(num_systems) for i in xrange(num_systems): c = cluster_centers[cluster_id[i]] if diagonalizable: eigvalues_new = c.get_spectrum() + cluster_radius / np.sqrt( hidden_state_dim) * np.random.randn(hidden_state_dim) generated_systems.append( lds.generate_linear_dynamical_system(hidden_state_dim, eigvalues=eigvalues_new)) else: transition_matrix = c.transition_matrix + cluster_radius / np.sqrt( hidden_state_dim) * np.random.randn(hidden_state_dim, hidden_state_dim) generated_systems.append( lds.LinearDynamicalSystem( transition_matrix, np.random.randn(c.input_matrix.shape[0], c.input_matrix.shape[1]), np.random.randn(c.output_matrix.shape[0], c.output_matrix.shape[1]))) dist_to_center[i] = lds.eig_dist(c, generated_systems[-1]) # For logging purpose. dist_bw_centers = np.zeros((num_clusters, num_clusters)) for i in xrange(num_clusters): for j in xrange(num_clusters): dist_bw_centers[i, j] = lds.eig_dist(cluster_centers[i], cluster_centers[j]) logging.info('Distances between cluster centers:\n%s', str(dist_bw_centers)) logging.info('Average distance from cluster centers: %.3f', np.average(dist_to_center)) for i in xrange(num_clusters): logging.info('Eigenvalues of cluster center %d: %s', i, str(cluster_centers[i].get_spectrum())) return generated_systems, cluster_id
def generate_cluster_centers(num_clusters, hidden_state_dim, input_dim, cluster_center_dist_lower_bound, diagonalizable=True): """Generates cluster center eigenvalues with distance requirement. The generated eigenvalues are drawn uniformly from (-1, 1) until the pairwise distance between cluster center eigenvalues >= lower bound. """ min_cluster_center_dist = -1. while min_cluster_center_dist < cluster_center_dist_lower_bound: cluster_centers = [] for _ in xrange(num_clusters): c = lds.generate_linear_dynamical_system( hidden_state_dim, input_dim, diagonalizable=diagonalizable) cluster_centers.append(c) min_cluster_center_dist = np.inf for s1 in xrange(num_clusters): for s2 in xrange(s1 + 1, num_clusters): d = lds.eig_dist(cluster_centers[s1], cluster_centers[s2]) if d < min_cluster_center_dist: min_cluster_center_dist = d logging.info('generated min_cluster_center_dist %.2f', min_cluster_center_dist) return cluster_centers
import lds import matplotlib.pyplot as plt import numpy as np import seaborn as sns sns.set(style='whitegrid') num_pairs = 100 plt.figure(figsize=(8, 4)) plt.subplot(1, 2, 1) hidden_state_dim = 2 lds_pairs = [(lds.generate_linear_dynamical_system(hidden_state_dim), lds.generate_linear_dynamical_system(hidden_state_dim)) for i in xrange(num_pairs)] lds_distances = [ lds.eig_dist(system1, system2) for (system1, system2) in lds_pairs ] expected_ar_distances = [ np.linalg.norm(system1.get_expected_arparams() - system2.get_expected_arparams()) for (system1, system2) in lds_pairs ] print(np.corrcoef(lds_distances, expected_ar_distances)[0, 1]) ax = sns.regplot(x=lds_distances, y=expected_ar_distances) ax.set(xlabel='l-2 distance b/w eigenvalues', ylabel='l-2 distance b/w ' 'corresponding AR params', title='Hidden dim = 2') plt.subplot(1, 2, 2) hidden_state_dim = 3 lds_pairs = [(lds.generate_linear_dynamical_system(hidden_state_dim),