def pca_prune(self, meshes): """ PCA on TriMeshes features. Parameters: meshes (list of TriMesh): meshes to be PCA Return: PCA model """ # process mesh files to have the same number of points meshes = self.analyse_meshes(meshes) pca_model = PCAModel(samples=meshes, verbose=True) n_comps_retained = int(sum(pca_model.eigenvalues_cumulative_ratio() < self.n_components)) if \ self.n_components >= 1 else self.n_components if self.verbose: print( '\nRetaining {:.2%} of eigenvalues keeps {} components'.format( self.n_components, n_comps_retained)) pca_model.trim_components(self.n_components) print( "Final PCA Model:\n# of components: {}\n# of points for each mesh (3 dims total): {}\n" "eigen value accumulative ratios: {}".format( str(pca_model.components.shape[0]), str(pca_model.components.shape[1]), str(pca_model.eigenvalues_cumulative_ratio()))) return pca_model
def test_pca_init_from_covariance(): n_samples = 30 n_features = 10 n_dims = 2 centre_values = [True, False] for centre in centre_values: # generate samples list and convert it to nd.array samples = [ PointCloud(np.random.randn(n_features, n_dims)) for _ in range(n_samples) ] data, template = as_matrix(samples, return_template=True) # compute covariance matrix and mean if centre: mean_vector = np.mean(data, axis=0) mean = template.from_vector(mean_vector) X = data - mean_vector C = np.dot(X.T, X) / (n_samples - 1) else: mean = samples[0] C = np.dot(data.T, data) / (n_samples - 1) # create the 2 pca models pca1 = PCAModel.init_from_covariance_matrix(C, mean, centred=centre, n_samples=n_samples) pca2 = PCAModel(samples, centre=centre) # compare them assert_array_almost_equal(pca1.component_vector(0, with_mean=False), pca2.component_vector(0, with_mean=False)) assert_array_almost_equal( pca1.component(7).as_vector(), pca2.component(7).as_vector()) assert_array_almost_equal(pca1.components, pca2.components) assert_array_almost_equal(pca1.eigenvalues, pca2.eigenvalues) assert_array_almost_equal(pca1.eigenvalues_cumulative_ratio(), pca2.eigenvalues_cumulative_ratio()) assert_array_almost_equal(pca1.eigenvalues_ratio(), pca2.eigenvalues_ratio()) weights = np.random.randn(pca1.n_active_components) assert_array_almost_equal( pca1.instance(weights).as_vector(), pca2.instance(weights).as_vector()) weights2 = np.random.randn(pca1.n_active_components - 4) assert_array_almost_equal(pca1.instance_vector(weights2), pca2.instance_vector(weights2)) assert_array_almost_equal(pca1.mean().as_vector(), pca2.mean().as_vector()) assert_array_almost_equal(pca1.mean_vector, pca2.mean_vector) assert (pca1.n_active_components == pca2.n_active_components) assert (pca1.n_components == pca2.n_components) assert (pca1.n_features == pca2.n_features) assert (pca1.n_samples == pca2.n_samples) assert (pca1.noise_variance() == pca2.noise_variance()) assert (pca1.noise_variance_ratio() == pca2.noise_variance_ratio()) assert_almost_equal(pca1.variance(), pca2.variance()) assert_almost_equal(pca1.variance_ratio(), pca2.variance_ratio()) assert_array_almost_equal(pca1.whitened_components(), pca2.whitened_components())
def test_pca_init_from_covariance(): n_samples = 30 n_features = 10 n_dims = 2 centre_values = [True, False] for centre in centre_values: # generate samples list and convert it to nd.array samples = [PointCloud(np.random.randn(n_features, n_dims)) for _ in range(n_samples)] data, template = as_matrix(samples, return_template=True) # compute covariance matrix and mean if centre: mean_vector = np.mean(data, axis=0) mean = template.from_vector(mean_vector) X = data - mean_vector C = np.dot(X.T, X) / (n_samples - 1) else: mean = samples[0] C = np.dot(data.T, data) / (n_samples - 1) # create the 2 pca models pca1 = PCAModel.init_from_covariance_matrix(C, mean, centred=centre, n_samples=n_samples) pca2 = PCAModel(samples, centre=centre) # compare them assert_array_almost_equal(pca1.component_vector(0, with_mean=False), pca2.component_vector(0, with_mean=False)) assert_array_almost_equal(pca1.component(7).as_vector(), pca2.component(7).as_vector()) assert_array_almost_equal(pca1.components, pca2.components) assert_array_almost_equal(pca1.eigenvalues, pca2.eigenvalues) assert_array_almost_equal(pca1.eigenvalues_cumulative_ratio(), pca2.eigenvalues_cumulative_ratio()) assert_array_almost_equal(pca1.eigenvalues_ratio(), pca2.eigenvalues_ratio()) weights = np.random.randn(pca1.n_active_components) assert_array_almost_equal(pca1.instance(weights).as_vector(), pca2.instance(weights).as_vector()) weights2 = np.random.randn(pca1.n_active_components - 4) assert_array_almost_equal(pca1.instance_vector(weights2), pca2.instance_vector(weights2)) assert_array_almost_equal(pca1.mean().as_vector(), pca2.mean().as_vector()) assert_array_almost_equal(pca1.mean_vector, pca2.mean_vector) assert(pca1.n_active_components == pca2.n_active_components) assert(pca1.n_components == pca2.n_components) assert(pca1.n_features == pca2.n_features) assert(pca1.n_samples == pca2.n_samples) assert(pca1.noise_variance() == pca2.noise_variance()) assert(pca1.noise_variance_ratio() == pca2.noise_variance_ratio()) assert_almost_equal(pca1.variance(), pca2.variance()) assert_almost_equal(pca1.variance_ratio(), pca2.variance_ratio()) assert_array_almost_equal(pca1.whitened_components(), pca2.whitened_components())
def pca_and_weights(meshes, retain_eig_cum_val=0.997, verbose=False): model = PCAModel(meshes, verbose=verbose) n_comps_retained = (model.eigenvalues_cumulative_ratio() < retain_eig_cum_val).sum() if verbose: print('\nRetaining {:.2%} of eigenvalues keeps {} components'.format( retain_eig_cum_val, n_comps_retained)) model.trim_components(retain_eig_cum_val) if verbose: meshes = print_progress(meshes, prefix='Calculating weights') weights = (np.vstack([model.project(m) for m in meshes]) / np.sqrt(model.eigenvalues)) return model, weights