def dim_reduction_nrmesup(X, P, labels, params): K = X.shape[0] nc = X.shape[1] Sw = np.zeros((nc, nc)) Sb = np.zeros((nc, nc)) for i in range(K): ci = labels[i] for j in range(K): Ci, Cj = X[i, :, :], X[j, :, :] Sij = np.dot(invsqrtm(Ci), np.dot(Cj, invsqrtm(Ci))) if (i != j) & (labels[j] == ci): Sw = Sw + powm(logm(Sij), 2) if (i != j) & (labels[j] != ci): Sb = Sb + powm(logm(Sij), 2) M = np.dot(np.linalg.inv(Sw), Sb) g, U = np.linalg.eig(M) idx = g.argsort()[::-1] g = g[idx] U = U[:, idx] B, p = sp.linalg.polar(U) W = B[:, :P] return W
def _fit(self, X): Ri = self.reference_old Rf = self.reference_new A = sqrtm(Ri) B = sqrtm(np.dot(invsqrtm(Ri), np.dot(Rf, invsqrtm(Ri)))) C = invsqrtm(Ri) W = np.dot(A, np.dot(B, C)) self.transporter_ = W
def egrad_function_pair_rie(M, M_tilde, Q): M_tilde_invsqrt = invsqrtm(M_tilde) M_sqrt = sqrtm(M) term_aux = np.dot(Q, np.dot(M, Q.T)) term_aux = np.dot(M_tilde_invsqrt, np.dot(term_aux, M_tilde_invsqrt)) return 4 * np.dot(np.dot(M_tilde_invsqrt, logm(term_aux)), np.dot( M_sqrt, Q))
def dim_reduction_nrmelandmark(X, P, labels, params): K = X.shape[0] nc = X.shape[1] S = np.zeros((nc, nc)) M = mean_riemann(X) for i in range(K): Ci = X[i, :, :] Sij = np.dot(invsqrtm(Ci), np.dot(M, invsqrtm(Ci))) S = S + powm(logm(Sij), 2) l, v = np.linalg.eig(S) idx = l.argsort()[::-1] l = l[idx] v = v[:, idx] W = v[:, :P] return W
def _transform(self, X): W = self.transporter_ Ri = self.reference_old Rf = self.reference_new Nt = X.shape[0] # detect which kind of input : tangent vectors or cov matrices if self.tangent_old: # if tangent vectors are given, transform them back to covs # (easier to have tg vectors in the form of symmetric matrices later) X = untangent_space(X, Ri) # transform covariances to their tangent vectors with respect to Ri # (these tangent vectors are in the form of symmetric matrices) eta_i = np.zeros(X.shape) Ri_sqrt = sqrtm(Ri) Ri_invsqrt = invsqrtm(Ri) for i in range(Nt): Li = logm(np.dot(Ri_invsqrt, np.dot(X[i], Ri_invsqrt))) eta_i[i, :, :] = np.dot(Ri_sqrt, np.dot(Li, Ri_sqrt)) # multiply the tangent vectors by the transport matrix W eta_f = np.zeros(X.shape) for i in range(Nt): eta_f[i, :, :] = np.dot(W, np.dot(eta_i[i], W.T)) # transform tangent vectors to covariance matrices with respect to Rf Xnew = np.zeros(X.shape) Rf_sqrt = sqrtm(Rf) Rf_invsqrt = invsqrtm(Rf) for i in range(Nt): Ef = expm(np.dot(Rf_invsqrt, np.dot(eta_f[i], Rf_invsqrt))) Xnew[i, :, :] = np.dot(Rf_sqrt, np.dot(Ef, Rf_sqrt)) # transform back to tangent vectors (flat form, not sym matrix) if needed if self.tangent_new: Xnew = tangent_space(Xnew, Rf) return Xnew
def dim_reduction_nrmeuns(X, P, labels, params): K = X.shape[0] nc = X.shape[1] S = np.zeros((nc, nc)) for i in range(K): for j in range(K): if i != j: Ci, Cj = X[i, :, :], X[j, :, :] Sij = np.dot(invsqrtm(Ci), np.dot(Cj, invsqrtm(Ci))) S = S + powm(logm(Sij), 2) l, v = np.linalg.eig(S) idx = l.argsort()[::-1] l = l[idx] v = v[:, idx] W = v[:, :P] return W
def transform(self, X): """ Detect and remove dropped. """ out = [] for x in X: if np.sum(x) != 0: cov = np.cov(x) W = invsqrtm(cov) tmp = np.dot(W.T, x) else: tmp = x out.append(tmp) return np.array(out)
def mean_riemann_custom(covmats, mean_args): """ A custom version of pyriemann.utils.mean.mean_riemann to handle singular matrices and I/O with regards to reducing samples classes. For function doc refer to the doc of pyriemann.utils.mean.mean_riemann. """ # Taking arguments tol, maxiter, init, sample_weight = mean_args # init sample_weight = _get_sample_weight(sample_weight, covmats) Nt, Ne, Ne = covmats.shape if init is None: C = np.mean(covmats, axis=0) else: C = init k = 0 nu = 1.0 tau = np.finfo(np.float64).max crit = np.finfo(np.float64).max # stop when J<10^-9 or max iteration = 50 while (crit > tol) and (k < maxiter) and (nu > tol): k = k + 1 C12 = sqrtm(C) Cm12 = invsqrtm(C) J = np.zeros((Ne, Ne)) for index in range(Nt): tmp = np.dot(np.dot(Cm12, covmats[index, :, :]), Cm12) with warnings.catch_warnings(): warnings.filterwarnings('error') try: J += sample_weight[index] * logm(tmp) except RuntimeWarning: pass crit = np.linalg.norm(J, ord='fro') h = nu * crit C = np.dot(np.dot(C12, expm(nu * J)), C12) if h < tau: nu = 0.95 * nu tau = h else: nu = 0.5 * nu return C
def mean_riemann(covmats, tol=10e-9, maxiter=50, init=None, u_prime=lambda x: 1): Nt, Ne, Ne = covmats.shape if init is None: C = np.mean(covmats, axis=0) else: C = init k = 0 nu = 1.0 tau = np.finfo(np.float64).max crit = np.finfo(np.float64).max # stop when J<10^-9 or max iteration = 50 while (crit > tol) and (k < maxiter) and (nu > tol): k = k + 1 C12 = sqrtm(C) Cm12 = invsqrtm(C) J = np.zeros((Ne, Ne)) for i in range(Nt): tmp = (Cm12 @ covmats[i, :, :]) @ Cm12 if type(u_prime(1)) == list: J += logm(tmp) * u_prime( distance_riemann(C, covmats[i, :, :])**2)[i] / Nt else: J += logm(tmp) * u_prime( distance_riemann(C, covmats[i, :, :])**2) / Nt crit = np.linalg.norm(J, ord='fro') h = nu * crit C = np.dot(np.dot(C12, expm(nu * J)), C12) if h < tau: nu = 0.95 * nu tau = h else: nu = 0.5 * nu return C
def power_means(C, p): phi = 0.375/np.abs(p) K = len(C) n = C[0].shape[0] w = np.ones(K) w = w/(1.0*len(w)) G = np.sum([wk*powm(Ck, p) for (wk,Ck) in zip(w,C)], axis=0) if p > 0: X = invsqrtm(G) else: X = sqrtm(G) zeta = 10e-10 test = 10*zeta while test > zeta: H = np.sum([wk*powm(np.dot(X, np.dot(powm(Ck, np.sign(p)), X.T)), np.abs(p)) for (wk,Ck) in zip(w,C)], axis=0) X = np.dot(powm(H, -phi), X) test = 1.0/np.sqrt(n) * np.linalg.norm(H - np.eye(n)) if p > 0: P = np.dot(np.linalg.inv(X), np.linalg.inv(X.T)) else: P = np.dot(X.T, X) return P
def exp_riemann(X, Y): """ exp_X(Y) = X exp(X^{-1}Y) = X^{1/2} exp(X^{-1/2} Y X^{-1/2}) X^{1/2}""" Xsqrt = sqrtm(X) Xinvsqrt = invsqrtm(X) return Xsqrt @ expm(Xinvsqrt @ Y @ Xinvsqrt) @ Xsqrt
def transform_org2opt(source, target_train, target_test): target_opt_train = {} target_opt_test = {} target_opt_train['labels'] = target_train['labels'] target_opt_test['labels'] = target_test['labels'] # get cost matrix Cs = source['covs'] ys = source['labels'] Ct_train = target_train['covs'] Ct_test = target_test['covs'] M = np.zeros((len(Cs), len(Ct_train))) for i, Cs_i in enumerate(Cs): for j, Ct_j in enumerate(Ct_train): M[i, j] = distance_riemann(Cs_i, Ct_j)**2 # get the transportation plan mu_s = distribution_estimation_uniform(Cs) mu_t = distribution_estimation_uniform(Ct_train) gamma = sinkhorn_lpl1_mm(mu_s, ys, mu_t, M, reg=1.0) # transport the target matrices (train) Ct_train_transported = np.zeros(Ct_train.shape) for j in range(len(Ct_train_transported)): Ct_train_transported[j] = mean_riemann(Cs, sample_weight=gamma[:, j]) target_opt_train['covs'] = Ct_train_transported # transport the target matrices (test) D = np.zeros((len(Ct_test), len(Ct_train))) for k, Ct_k in enumerate(Ct_test): for l, Ct_l in enumerate(Ct_train): D[k, l] = distance_riemann(Ct_k, Ct_l)**2 idx = np.argmin(D, axis=1) # nearest neighbour to each target test matrix Ct_test_transported = np.zeros(Ct_test.shape) for i in range(len(Ct_test)): j = idx[i] Ci = Ct_test[i] Ri = Ct_train[j] Rf = Ct_train_transported[j] Ri_sqrt = sqrtm(Ri) Ri_invsqrt = invsqrtm(Ri) Li = logm(np.dot(Ri_invsqrt, np.dot(Ci, Ri_invsqrt))) eta_i = np.dot(Ri_sqrt, np.dot(Li, Ri_sqrt)) Ri_Rf = geodesic_riemann(Rf, Ri, alpha=0.5) Ri_inv = np.linalg.inv(Ri) eta_f = np.dot(Ri_inv, np.dot(eta_i, Ri_inv)) eta_f = np.dot(Ri_Rf, np.dot(eta_f, Ri_Rf)) Rf_sqrt = sqrtm(Rf) Rf_invsqrt = invsqrtm(Rf) Ef = expm(np.dot(Rf_invsqrt, np.dot(eta_f, Rf_invsqrt))) Ct_test_transported[i] = np.dot(Rf_sqrt, np.dot(Ef, Rf_sqrt)) target_opt_test['covs'] = Ct_test_transported return source, target_opt_train, target_opt_test
def parallel_transport_covariance_matrix(C, R): return np.dot(invsqrtm(R), np.dot(C, invsqrtm(R)))
def fit(self, data): ''' Calculate average covariance matrices and return freatures of training data Parameters ---------- data: array, shape (n_tr_trial,n_channel,n_samples) input training time samples Return ------ train_feat: array, shape: if vectorized: (n_tr_trial,(n_temp x n_freq x n_riemann) else (n_tr_trial,n_temp , n_freq , n_riemann) ''' n_tr_trial, n_channel, _ = data.shape self.n_channel = n_channel self.n_riemann = int((n_channel + 1) * n_channel / 2) cov_mat = np.zeros( (n_tr_trial, self.n_temp, self.n_freq, n_channel, n_channel)) # calculate training covariance matrices for trial_idx in range(n_tr_trial): for temp_idx in range(self.n_temp): t_start, t_end = self.temp_windows[ temp_idx, 0], self.temp_windows[temp_idx, 1] n_samples = t_end - t_start for freq_idx in range(self.n_freq): # filter signal data_filter = butter_fir_filter( data[trial_idx, :, t_start:t_end], self.filter_bank[freq_idx]) # regularized covariance matrix cov_mat[trial_idx, temp_idx, freq_idx] = 1 / (n_samples - 1) * np.dot( data_filter, np.transpose(data_filter) ) + self.rho / n_samples * np.eye(n_channel) # calculate mean covariance matrix self.c_ref_invsqrtm = np.zeros((self.n_freq, n_channel, n_channel)) for freq_idx in range(self.n_freq): if self.riem_opt == 'No_Adaptation': self.c_ref_invsqrtm[freq_idx] = np.eye(n_channel) else: # Mean covariance matrix over all trials and temp winds per frequency band cov_avg = mean.mean_covariance(cov_mat[:, :, freq_idx].reshape( -1, n_channel, n_channel), metric=self.mean_metric) self.c_ref_invsqrtm[freq_idx] = base.invsqrtm(cov_avg) # calculate training features train_feat = np.zeros( (n_tr_trial, self.n_temp, self.n_freq, self.n_riemann)) for trial_idx in range(n_tr_trial): for temp_idx in range(self.n_temp): for freq_idx in range(self.n_freq): train_feat[trial_idx, temp_idx, freq_idx] = self.riem_kernel( cov_mat[trial_idx, temp_idx, freq_idx], self.c_ref_invsqrtm[freq_idx]) if self.vectorized: return train_feat.reshape(n_tr_trial, -1) else: return train_feat
def log_riemann(X, Y): """ log_X(Y) = X log(X^{-1}Y) = X^{1/2} log(X^{-1/2} Y X^{-1/2}) X^{1/2}""" Xsqrt = sqrtm(X) Xinvsqrt = invsqrtm(X) return Xsqrt @ logm(Xinvsqrt @ Y @ Xinvsqrt) @ Xsqrt
def score_ensemble_rot(settings, subject_target, ntop): dataset = settings['dataset'] paradigm = settings['paradigm'] session = settings['session'] storage = settings['storage'] filepath = '../results/' + dataset + '/TL_intra-subject_scores.pkl' acc_intra_dict = joblib.load(filepath) scores = [] subject_sources = [] for subject in settings['subject_list']: if subject == subject_target: continue else: scores.append(acc_intra_dict[subject]) subject_sources.append(subject) scores = np.array(scores) subject_sources = np.array(subject_sources) idx_sort = scores.argsort()[::-1] scores = scores[idx_sort] subject_sources = subject_sources[idx_sort] subject_sources_ntop = subject_sources[:ntop] # get the geometric means for each subject (each class and also the center) filename = '../results/' + dataset + '/subject_means.pkl' subj_means = joblib.load(filename) # get the data for the target subject target_org = GD.get_dataset(dataset, subject_target, session, storage) if paradigm == 'MI': # things here are only implemented for MI for now target_org['covs'] = Covariances(estimator='oas').fit_transform( target_org['signals']) target_org['labels'] = target_org['labels'] ncovs = settings['ncovs_list'][0] nrzt = 10 score_rzt = 0.0 for rzt in range(nrzt): # split randomly the target dataset target_org_train, target_org_test = get_target_split_motorimagery( target_org, ncovs) covs_train_target = target_org_train['covs'] labs_train_target = target_org_train['labels'] MC_target = mean_riemann(covs_train_target) M1_target = mean_riemann( covs_train_target[labs_train_target == 'left_hand']) M2_target = mean_riemann( covs_train_target[labs_train_target == 'right_hand']) M1_target_rct = np.dot(invsqrtm(MC_target), np.dot(M1_target, invsqrtm(MC_target))) M2_target_rct = np.dot(invsqrtm(MC_target), np.dot(M2_target, invsqrtm(MC_target))) covs_train_target = np.stack([M1_target_rct, M2_target_rct]) labs_train_target = np.array(['left_hand', 'right_hand']) clf = [] for subj_source in subject_sources_ntop: MC_source = subj_means[subj_source]['center'] M1_source = subj_means[subj_source]['left_hand'] M2_source = subj_means[subj_source]['right_hand'] M1_source_rct = np.dot(invsqrtm(MC_source), np.dot(M1_source, invsqrtm(MC_source))) M2_source_rct = np.dot(invsqrtm(MC_source), np.dot(M2_source, invsqrtm(MC_source))) M = [M1_target_rct, M2_target_rct] Mtilde = [M1_source_rct, M2_source_rct] R = manifoptim.get_rotation_matrix(M, Mtilde) M1_source_rot = np.dot(R, np.dot(M1_source_rct, R.T)) M2_source_rot = np.dot(R, np.dot(M2_source_rct, R.T)) covs_train_source = np.stack([M1_source_rot, M2_source_rot]) labs_train_source = np.array(['left_hand', 'right_hand']) covs_train = np.concatenate([covs_train_source, covs_train_target]) labs_train = np.concatenate([labs_train_source, labs_train_target]) clfi = MDM() # problems here when using integer instead of floats on the sample_weight clfi.fit(covs_train, labs_train, sample_weight=np.array( [200.0, 200.0, 2.0 * ncovs, 2.0 * ncovs])) clf.append(clfi) covs_test = target_org_test['covs'] labs_test = target_org_test['labels'] ypred = [] for clfi in clf: yi = clfi.predict(covs_test) ypred.append(yi) ypred = np.array(ypred) majorvoting = [] for j in range(ypred.shape[1]): ypredj = ypred[:, j] values_unique, values_count = np.unique(ypredj, return_counts=True) majorvoting.append(values_unique[np.argmax(values_count)]) majorvoting = np.array(majorvoting) score_rzt = score_rzt + np.mean(majorvoting == labs_test) score = score_rzt / nrzt return score
def test_invsqrtm(): """Test matrix inverse square root""" C = 2*np.eye(3) Ctrue = (1.0/np.sqrt(2))*np.eye(3) assert_array_almost_equal(invsqrtm(C),Ctrue)
def test_invsqrtm(): """Test matrix inverse square root""" C = 2 * np.eye(3) Ctrue = (1.0 / np.sqrt(2)) * np.eye(3) assert_array_almost_equal(invsqrtm(C), Ctrue)
def score_pooling_rct(settings, subject_target, ntop): dataset = settings['dataset'] paradigm = settings['paradigm'] session = settings['session'] storage = settings['storage'] filepath = '../results/' + dataset + '/TL_intra-subject_scores.pkl' acc_intra_dict = joblib.load(filepath) scores = [] subject_sources = [] for subject in settings['subject_list']: if subject == subject_target: continue else: scores.append(acc_intra_dict[subject]) subject_sources.append(subject) scores = np.array(scores) subject_sources = np.array(subject_sources) idx_sort = scores.argsort()[::-1] scores = scores[idx_sort] subject_sources = subject_sources[idx_sort] subject_sources_ntop = subject_sources[:ntop] # get the geometric means for each subject (each class and also the center) filename = '../results/' + dataset + '/subject_means.pkl' subj_means = joblib.load(filename) # get the data for the target subject target_org = GD.get_dataset(dataset, subject_target, session, storage) if paradigm == 'MI': # things here are only implemented for MI for now target_org['covs'] = Covariances(estimator='oas').fit_transform( target_org['signals']) target_org['labels'] = target_org['labels'] ncovs = settings['ncovs_list'][0] score_rzt = 0.0 nrzt = 10 for rzt in range(nrzt): # split randomly the target dataset target_org_train, target_org_test = get_target_split_motorimagery( target_org, ncovs) # get the data from the sources and pool it all together class_mean_1 = [] class_mean_2 = [] for subj_source in subject_sources_ntop: MC_source = subj_means[subj_source]['center'] M1_source = subj_means[subj_source]['left_hand'] M2_source = subj_means[subj_source]['right_hand'] M1_source_rct = np.dot(invsqrtm(MC_source), np.dot(M1_source, invsqrtm(MC_source))) class_mean_1.append(M1_source_rct) M2_source_rct = np.dot(invsqrtm(MC_source), np.dot(M2_source, invsqrtm(MC_source))) class_mean_2.append(M2_source_rct) class_mean_1_source = np.stack(class_mean_1) class_mean_2_source = np.stack(class_mean_2) covs_train_source = np.concatenate( [class_mean_1_source, class_mean_2_source]) labs_train_source = np.concatenate([ len(class_mean_1_source) * ['left_hand'], len(class_mean_2_source) * ['right_hand'] ]) # re-center data for the target covs_train_target = target_org['covs'] MC_target = mean_riemann(covs_train_target) labs_train_target = target_org['labels'] class_mean_1_target = mean_riemann( covs_train_target[labs_train_target == 'left_hand']) class_mean_1_target = np.dot( invsqrtm(MC_target), np.dot(class_mean_1_target, invsqrtm(MC_target))) class_mean_2_target = mean_riemann( covs_train_target[labs_train_target == 'right_hand']) class_mean_2_target = np.dot( invsqrtm(MC_target), np.dot(class_mean_2_target, invsqrtm(MC_target))) covs_train_target = np.stack( [class_mean_1_target, class_mean_2_target]) labs_train_target = np.array(['left_hand', 'right_hand']) covs_train = np.concatenate([covs_train_source, covs_train_target]) labs_train = np.concatenate([labs_train_source, labs_train_target]) covs_test = target_org_test['covs'] labs_test = target_org_test['labels'] # do the classification clf = MDM() clf.fit(covs_train, labs_train) score_rzt = score_rzt + clf.score(covs_test, labs_test) score = score_rzt / nrzt return score