Пример #1
0
 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
Пример #2
0
    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
Пример #3
0
    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)
Пример #4
0
    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
Пример #5
0
    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