def __init__(self): #the n_components is temporary, the loaded model will overwrite it self.gmm_vaeenc_bp = gmm.GMM(n_components=2) self.gmm_vaeenc_bp.load_model(gmm_vaeenc_bp_model_file) self.gmm_vaeenc_sp = gmm.GMM(n_components=2) self.gmm_vaeenc_sp.load_model(gmm_vaeenc_sp_model_file) return
def predict(self, X): n_samples, n_dim = X.shape # use approximated GMM to capture the correlation, which provides us an initialization to iterate # the MAP estimation tmp_gmm = gmm.GMM( n_components=len(self.gmm_estimators_full_['weights']), priors=np.array(self.gmm_estimators_full_['weights']), means=np.array(self.gmm_estimators_full_['means']), covariances=self.gmm_estimators_full_['covars']) init_guess, init_covar = tmp_gmm.predict_with_covariance(indices=range(n_dim), X=X) def objfunc(x, *args): prior_mu, prior_inv_var = args vals, grads = self.value_eval_samples_helper(np.array([x]), average=False, const=True) prior_prob = .5*(x - prior_mu).dot(prior_inv_var).dot(x - prior_mu) prior_grad = prior_inv_var.dot(x-prior_mu) return vals[0] + prior_prob, grads[0] + prior_grad res = [] for sample_idx in range(n_samples): opt_res = sciopt.minimize( fun=objfunc, x0=init_guess[sample_idx, :], args=(init_guess[sample_idx, :], np.linalg.pinv(init_covar[sample_idx])), method='BFGS', jac=True, options={'gtol': 1e-8, 'disp': False}) # print opt_res.message, opt_res.x, # print opt_res.fun, opt_res.jac # print init_guess[sample_idx, :], init_covar[sample_idx], opt_res.x res.append(opt_res.x) res = np.array(res) return res
def _check_grads(self, X): n_samples, n_dim = X.shape # #predict the next state x_{t+1} given x_{t} tmp_gmm = gmm.GMM( n_components=len(self.gmm_estimators_full_['weights']), priors=np.array(self.gmm_estimators_full_['weights']), means=np.array(self.gmm_estimators_full_['means']), covariances=self.gmm_estimators_full_['covars']) init_guess, init_covar = tmp_gmm.predict_with_covariance(indices=range(n_dim), X=X) def objfunc(x, *args): prior_mu, prior_var = args vals, grads = self.value_eval_samples_helper(np.array([x]), average=False, const=True) prior_prob = .5*(x - prior_mu).dot(prior_var).dot(x - prior_mu) prior_grad = prior_var.dot(x-prior_mu) return vals[0] + prior_prob, grads[0] + prior_grad res = [] for sample_idx in range(n_samples): def check_grad_fun(x): return objfunc(x, init_guess[sample_idx, :], init_covar[sample_idx])[0] def check_grad_fun_jac(x): return objfunc(x, init_guess[sample_idx, :], init_covar[sample_idx])[1] res.append(sciopt.check_grad(check_grad_fun, check_grad_fun_jac, X[sample_idx, :])) return np.mean(res)
def _em_steps(self, estimator_idx, X, y=None): #use current estimation as initialization to perform expectation-maximization #now reuse the procedure implemented by scikit-learn, actually a costumized implementation #is required if the passive dynamics also needs to be learned. if self.verbose: if estimator_idx is not None: print 'EM steps for the estimator {0}'.format(estimator_idx) else: print 'EM steps...' if estimator_idx is not None: n_partitions=len(self.estimators_[estimator_idx]['weights']) if self.verbose: print 'num of partitions:', n_partitions #use our own initialization g = gmm.GMM(n_components=n_partitions, priors=np.array(self.estimators_[estimator_idx]['weights']), means=np.array(self.estimators_[estimator_idx]['means']), covariances=np.array(self.estimators_[estimator_idx]['covars']), n_iter=self.em_itrs, covariance_type='full') else: n_partitions=len(self.estimators_full_['weights']) g = mixture.GaussianMixture(n_components=n_partitions, priors=np.array(self.estimators_[estimator_idx]['weights']), means=np.array(self.estimators_[estimator_idx]['means']), covariances=np.array(self.estimators_[estimator_idx]['covars']), n_iter=self.em_itrs, covariance_type='full') # g.fit(X[:, (X.shape[1]/2):]) g.fit(X) #prepare to return a defaultdict res=defaultdict(list) res['means']=list(g.means) res['covars']=list(g.covariances) res['weights']=list(g.priors) return res
def fit(self, X, y=None): ''' X - an array of concatenated features X_i = (x_{t-1}, x_{t}) corresponding to the infinite horizon case ''' #check parameters... assert(type(self.n_estimators)==int) assert(self.n_estimators > 0) assert(type(self.max_depth)==int) assert(self.max_depth > 0) assert(type(self.min_samples_split)==int) assert(self.min_samples_split > 0) assert(type(self.min_samples_leaf)==int) assert(self.min_samples_leaf > 0) assert(type(self.em_itrs)==int) n_samples, n_dims = X.shape #an initial partitioning of data with random forest embedding self.random_embedding_mdl_ = RandomTreesEmbedding( n_estimators=self.n_estimators, max_depth=self.max_depth, min_samples_split=self.min_samples_split, min_samples_leaf=self.min_samples_leaf, random_state=self.random_state ) #we probably do not need the data type to differentiate it is a demonstration #of trajectory or commanded state, do we? if self.passive_dyn_func is not None and self.passive_dyn_ctrl is not None and self.passive_dyn_noise is not None: # self.random_embedding_mdl_.fit(X[:, X.shape[1]/2:]) # indices = self.random_embedding_mdl_.apply(X[:, X.shape[1]/2:]) self.random_embedding_mdl_.fit(X[:, :X.shape[1]/2]) indices = self.random_embedding_mdl_.apply(X[:, :X.shape[1]/2]) # X_tmp = np.array(X) # X_tmp[:, X.shape[1]/2:] = X_tmp[:, X.shape[1]/2:] - X_tmp[:, :X.shape[1]/2] # self.random_embedding_mdl_.fit(X_tmp) # indices = self.random_embedding_mdl_.apply(X_tmp) else: self.random_embedding_mdl_.fit(X) #figure out indices indices = self.random_embedding_mdl_.apply(X) #prepare ensemble for prediction self.random_prediction_mdl_ = RandomForestRegressor( n_estimators=self.n_estimators, max_depth=self.max_depth, min_samples_split=self.min_samples_split, min_samples_leaf=self.min_samples_leaf, random_state=self.random_state ) self.random_prediction_mdl_.fit(X[:, :X.shape[1]/2], X[:, X.shape[1]/2:]) if self.clustering > 0: #we need to force the data to situate in clusters with the given number and the random embeddings #first construct affinity #use extracted indices as sparse features to construct an affinity matrix if self.n_estimators > 1: if self.verbose: print 'Building {0} subset of data depending on their random embedding similarity...'.format(self.clustering) #it makes sense to use the random embedding to do the clustering if we have ensembled features aff_mat = _affinity_matrix_from_indices(indices, 'binary') #using spectral mapping (Laplacian eigenmap) self.cluster = SpectralClustering(n_clusters=self.clustering, affinity='precomputed') self.cluster.fit(aff_mat) else: if self.verbose: print 'Building {0} subset of data depending on their Euclidean similarity...'.format(self.clustering) #otherwise, use euclidean distance, this should be enough when the state space is low dimensional self.cluster = KMeans(n_clusters=self.clustering, max_iter=200, n_init=5) self.cluster.fit(X) partitioned_data = defaultdict(list) leaf_idx = defaultdict(set) weight_idx = defaultdict(float) for d_idx, d, p_idx in zip(range(len(X)), X, self.cluster.labels_): partitioned_data[0, p_idx].append(d) leaf_idx[0] |= {p_idx} for p_idx in range(self.clustering): weight_idx[0, p_idx] = 1./self.clustering num_estimators = 1 else: partitioned_data = defaultdict(list) leaf_idx = defaultdict(set) weight_idx = defaultdict(float) #group data belongs to the same partition and have the weights... #is weight really necessary for EM steps? Hmm, seems to be for the initialization #d_idx: data index; p_idx: partition index (comprised of estimator index and leaf index) for d_idx, d, p_idx in zip(range(len(X)), X, indices): for e_idx, l_idx in enumerate(p_idx): partitioned_data[e_idx, l_idx].append(d) leaf_idx[e_idx] |= {l_idx} for e_idx, l_idx in enumerate(p_idx): weight_idx[e_idx, l_idx] = float(len(partitioned_data[e_idx, l_idx])) / len(X) # weight_idx[e_idx, l_idx] = 1. / len(p_idx) num_estimators = self.n_estimators #for each grouped data, solve an easy IOC problem by assuming quadratic cost-to-go function #note that, if the passive dynamics need to be learned, extra steps is needed to train a regressor with weighted data #otherwise, just a simply gaussian for each conditional probability distribution model self.estimators_ = [] #another copy to store the parameters all together, for EM/evaluation on all of the models self.estimators_full_ = defaultdict(list) #<hyin/Feb-6th-2016> an estimator and leaf indexed structure to record the passive likelihood of data... passive_likelihood_dict = defaultdict(list) for e_idx in range(num_estimators): #for each estimator estimator_parms = defaultdict(list) for l_idx in leaf_idx[e_idx]: if self.verbose: print 'Processing {0}-th estimator and {1}-th leaf/partition...'.format(e_idx, l_idx) #and for each data partition data_partition=np.array(partitioned_data[e_idx, l_idx]) estimator_parms['means'].append(np.mean(data_partition, axis=0)) estimator_parms['covars'].append(np.cov(data_partition.T) + np.eye(data_partition.shape[1])*self.reg) #for MaxEnt, uniform passive likelihood passive_likelihood_dict[e_idx, l_idx] = np.ones(len(data_partition)) / float(len(data_partition)) estimator_parms['weights'].append(weight_idx[e_idx, l_idx]) self.estimators_.append(estimator_parms) #can stop here or go for expectation maximization for each estimator... if self.em_itrs > 0: #prepare em results for each estimator em_res = [self._em_steps(e_idx, X, y) for e_idx in range(num_estimators)] self.estimators_ = em_res #record the gmm approximation self.gmm_estimators_ = copy.deepcopy(self.estimators_) self.gmm_estimators_full_ = defaultdict(list) for est in self.estimators_: for comp_idx in range(len(est['weights'])): est['means'][comp_idx] = est['means'][comp_idx][(n_dims/2):] est['covars'][comp_idx] = est['covars'][comp_idx][(n_dims/2):, (n_dims/2):] self.estimators_full_['weights'].append(est['weights'][comp_idx]/float(num_estimators)) #for full estimators self.estimators_full_['means'].append(est['means'][comp_idx]) self.estimators_full_['covars'].append(est['covars'][comp_idx]) if self.passive_dyn_func is not None and self.passive_dyn_ctrl is not None and self.passive_dyn_noise is not None: X_new = X[:, X.shape[1]/2:] X_old = X[:, 0:X.shape[1]/2] #merge the model knowledge if passive dynamics model is available, use MaxEnt assumption otherwise X_new_passive = np.array([self.passive_dyn_func(X_old[sample_idx]) for sample_idx in range(X.shape[0])]) passive_likelihood = _passive_dyn_likelihood(X_new, X_new_passive, self.passive_dyn_noise, self.passive_dyn_ctrl, self.reg) weights = passive_likelihood / (np.sum(passive_likelihood) + self.reg) if np.sum(weights) < 1e-10: weights = 1./len(weights) * np.ones(len(weights)) #a GMM as a MaxEnt surrogate tmp_gmm = gmm.GMM( n_components=len(self.estimators_[0]['weights']), priors=self.estimators_[0]['weights'], means=self.estimators_[0]['means'], covariances=self.estimators_[0]['covars']) for e_idx in range(num_estimators): tmp_gmm.n_components = len(self.estimators_[e_idx]['weights']) tmp_gmm.priors = self.estimators_[e_idx]['weights'] tmp_gmm.means = self.estimators_[e_idx]['means'] tmp_gmm.covariances = self.estimators_[e_idx]['covars'] responsibilities = tmp_gmm.to_responsibilities(X_new) responsibilities = responsibilities / (np.sum(responsibilities, axis=0) + 1e-10) new_weights = (weights * responsibilities.T).T new_weights = (new_weights + 1e-10) / (np.sum(new_weights +1e-10, axis=0)) weighted_means = [np.sum((new_weight*X_new.T).T, axis=0) for new_weight in new_weights.T] weighted_covars =[ _frequency_weighted_covariance(X_new, weighted_mean, new_weight, spherical=False) for new_weight, weighted_mean in zip(new_weights.T, weighted_means)] self.estimators_[e_idx]['means'] = weighted_means self.estimators_[e_idx]['covars'] = weighted_covars self.prepare_inv_and_constants() return indices, leaf_idx, partitioned_data, passive_likelihood_dict
return d.flatten().astype(np.float32) * 1. / 255 #prepare seed to have stable shuffle np.random.seed(1234) import gmr.gmr.gmm as gmm gmm_pca_dyn_model_file = 'il_models/gmm_pca_dyn.gmm' gmm_pca_bp_model_file = 'il_models/gmm_pca_bp.gmm' gmm_pca_sp_model_file = 'il_models/gmm_pca_sp.gmm' from sklearn.externals import joblib pca = joblib.load('il_models/img_pca_99.pca') print 'pca linear subspace dimension:', pca.n_components_ gmm_pca_dyn = gmm.GMM(n_components=2) gmm_pca_dyn.load_model(gmm_pca_dyn_model_file) #auxiliary function to update the encode def update_encode(curr_state, input_img=None): if input_img is None: #use prior model to predict next encode if np.isnan(curr_state).any(): #we simply ignore the prediction encode = curr_state else: encode = gmm_pca_dyn.predict(range(pca.n_components_), np.array([curr_state]))[0] else: #we have observation now, use pca model for encodement