def als(tensor,rank,factors=None,it_max=100,tol=1e-7,list_factors=False,error_fast=True,time_rec=False): """ ALS methode of CP decomposition Parameters ---------- tensor : tensor rank : int factors : list of matrices, optional an initial factor matrices. The default is None. it_max : int, optional maximal number of iteration. The default is 100. tol : float, optional error tolerance. The default is 1e-7. list_factors : boolean, optional If true, then return factor matrices of each iteration. The default is False. error_fast : boolean, optional If true, use err_fast to compute data fitting error, otherwise, use err. The default is True. time_rec : boolean, optional If true, return computation time of each iteration. The default is False. Returns ------- the CP decomposition, number of iteration and termination criterion. list_fac and list_time are optional. """ N=tl.ndim(tensor) # order of tensor norm_tensor=tl.norm(tensor) # norm of tensor if time_rec == True : list_time=[] if list_factors==True : list_fac=[] # list of factor matrices if (factors==None): factors=svd_init_fac(tensor,rank) weights=None it=0 if list_factors==True : list_fac.append(copy.deepcopy(factors)) error=[err(tensor,weights,factors)/norm_tensor] while (error[len(error)-1]>tol and it<it_max): if time_rec == True : tic=time.time() for n in range(N): V=np.ones((rank,rank)) for i in range(len(factors)): if i != n : V=V*tl.dot(tl.transpose(factors[i]),factors[i]) W=tl.cp_tensor.unfolding_dot_khatri_rao(tensor, (None,factors), n) factors[n]= tl.transpose(tl.solve(tl.transpose(V),tl.transpose(W))) if list_factors==True : list_fac.append(copy.deepcopy(factors)) it=it+1 if (error_fast==False) : error.append(err(tensor,weights,factors)/norm_tensor) else : error.append(err_fast(norm_tensor,factors[N-1],V,W)/norm_tensor) if time_rec == True : toc=time.time() list_time.append(toc-tic) # weights,factors=tl.cp_tensor.cp_normalize((None,factors)) if list_factors==True and time_rec==True: return(weights,factors,it,error,list_fac,list_time) if time_rec==True : return(weights,factors,it,error,list_time) if list_factors==True : return(weights,factors,it,error,list_fac) return(weights,factors,it,error)
def test_err(): """ Test of err """ # create a kruskal tensor # factor matrices A = np.arange(9).reshape(3, 3) B = np.arange(6).reshape(2, 3) + 9 C = np.arange(6).reshape(2, 3) + 15 factors = [] factors += [A] factors += [B] factors += [C] t_krus = tl.cp_to_tensor((None, factors)) weights_cp, factors_cp = tl.cp_normalize((None, factors)) print(base.err(t_krus, weights_cp, factors_cp))
def nn_her_Als(tensor, rank, factors=None, it_max=100, tol=1e-7, beta=0.5, eta=1.5, gamma=1.05, gamma_bar=1.01, list_factors=False, error_fast=True, time_rec=False): """ her ALS methode of CP decomposition for non negative case Parameters ---------- tensor : tensor rank : int factors : list of matrices, optional an initial non negative factor matrices. The default is None. it_max : int, optional maximal number of iteration. The default is 100. tol : float, optional error tolerance. The default is 1e-7. beta : float, optional extrapolation parameter. The default is 0.5. eta : float, optional decrease coefficient of beta. The default is 1.5. gamma : float, optional increase coefficient of beta. The default is 1.05. gamma_bar : float, optional increase coeefficient of beta_bar. The default is 1.01. list_factors : boolean, optional If true, then return factor matrices of each iteration. The default is False. error_fast : boolean, optional If true, use err_fast to compute data fitting error, otherwise, use err. The default is True. time_rec : boolean, optional If true, return computation time of each iteration. The default is False. Returns ------- the CP decomposition, number of iteration, error and restart pourcentage. list_fac and list_time are optional. """ beta_bar = 1 N = tl.ndim(tensor) # order of tensor norm_tensor = tl.norm(tensor) # norm of tensor weights = None if time_rec == True: list_time = [] if list_factors == True: list_fac = [] if (factors == None): factors = svd_init_fac(tensor, rank) # Initialization of factor hat matrices by factor matrices factors_hat = factors if list_factors == True: list_fac.append(copy.deepcopy(factors)) it = 0 cpt = 0 F_hat_bf = err(tensor, None, factors) # cost error = [F_hat_bf / norm_tensor] while (error[len(error) - 1] > tol and it < it_max): if time_rec == True: tic = time.time() for n in range(N): V = np.ones((rank, rank)) for i in range(len(factors)): if i != n: V = V * tl.dot(tl.transpose(factors_hat[i]), factors_hat[i]) W = tl.cp_tensor.unfolding_dot_khatri_rao(tensor, (None, factors_hat), n) factor_bf = factors[n] # update fac, _, _, _ = hals_nnls(tl.transpose(W), V, tl.transpose(factors[n])) factors[n] = tl.transpose(fac) # extrapolate factors_hat[n] = tl.clip(factors[n] + beta * (factors[n] - factor_bf), a_min=0.0) if (error_fast == False): F_hat_new = err(tensor, None, factors_hat) # cost update else: F_hat_new = err_fast(norm_tensor, factors[N - 1], V, W) if (F_hat_new > F_hat_bf): factors_hat = factors beta_bar = beta beta = beta / eta cpt = cpt + 1 else: factors = factors_hat beta_bar = min(1, beta_bar * gamma_bar) beta = min(beta_bar, gamma * beta) F_hat_bf = F_hat_new it = it + 1 if list_factors == True: list_fac.append(copy.deepcopy(factors)) error.append(F_hat_new / norm_tensor) if time_rec == True: toc = time.time() list_time.append(toc - tic) if time_rec == True and list_factors == True: return (weights, factors, it, error, cpt / it, list_fac, list_time) if list_factors == True: return (weights, factors, it, error, cpt / it, list_fac) if time_rec == True: return (weights, factors, it, error, cpt / it, list_time) return (weights, factors, it, error, cpt / it)
def her_CPRAND(tensor, rank, n_samples, factors=None, exact_err=True, it_max=100, err_it_max=20, tol=1e-7, beta=0.1, eta=3, gamma=1.01, gamma_bar=1.005, list_factors=False, time_rec=False): """ herCPRAND for CP-decomposition return also exact error Parameters ---------- tensor : tensor rank : int n_samples : int sample size factors : list of matrices, optional an initial factor matrices. The default is None. exact_err : boolean, optional whether use err or err_rand_fast for terminaison criterion. The default is False. (not useful for this version) it_max : int, optional maximal number of iteration. The default is 100. err_it_max : int, optional maximal of iteration if terminaison critirion is not improved. The default is 20. tol : float, optional error tolerance. The default is 1e-7. beta : float, optional extrapolation parameter. The default is 0.1. eta : float, optional decrease coefficient of beta. The default is 3. gamma : float, optional increase coefficient of beta. The default is 1.01. gamma_bar : float, optional increase coeefficient of beta_bar. The default is 1.005. list_factors : boolean, optional If true, then return factor matrices of each iteration. The default is False. time_rec : boolean, optional If true, return computation time of each iteration. The default is False. Returns ------- the CP decomposition, number of iteration and exact / estimated termination criterion. list_fac and list_time are optional. """ beta_bar = 1 N = tl.ndim(tensor) # order of tensor norm_tensor = tl.norm(tensor) # norm of tensor if list_factors == True: list_fac = [] if (time_rec == True): list_time = [] if (factors == None): factors = svd_init_fac(tensor, rank) # Initialization of factor hat matrice by factor matrices factors_hat = factors if list_factors == True: list_fac.append(copy.deepcopy(factors)) weights = None it = 0 err_it = 0 cpt = 0 ######################################## ######### error initialization ######### ######################################## F_hat_bf, ind_bf = err_rand(tensor, None, factors, n_samples) F_hat_bf_ex = err(tensor, None, factors) # exact cost rng = tl.random.check_random_state(None) error = [F_hat_bf / norm_tensor] error_ex = [F_hat_bf_ex / norm_tensor] min_err = error[len(error) - 1] while (min_err > tol and it < it_max and err_it < err_it_max): if time_rec == True: tic = time.time() factors_hat_bf = factors_hat for n in range(N): Zs, indices = sample_khatri_rao(factors_hat, n_samples, skip_matrix=n, random_state=rng) indices_list = [i.tolist() for i in indices] indices_list.insert(n, slice(None, None, None)) indices_list = tuple(indices_list) V = tl.dot(tl.transpose(Zs), Zs) # J'ai du mal avec la syntaxe tensor[indices_list], # Ca renvoie une matrices et non un tenseur? if (n == 0): sampled_unfolding = tensor[indices_list] else: sampled_unfolding = tl.transpose(tensor[indices_list]) W = tl.dot(sampled_unfolding, Zs) factor_bf = factors[n] # update factors[n] = tl.transpose( tl.solve(V, tl.transpose(W)) ) # solve needs a squared full rank matrix, if rank>nb_sampls ok # if (n==N-1) : F_hat_new=tl.norm(tl.dot(Zs,tl.transpose(factors[n]))-sampled_unfolding,2) # cost update # extrapolate factors_hat[n] = factors[n] + beta * (factors[n] - factor_bf) ######################################## ######### error update ######### ######################################## matrices = factors_hat_bf[:-1] Zs_bf = tl.ones((n_samples, rank), **tl.context(matrices[0])) for indices, matrix in zip(indices_list, matrices): Zs_bf = Zs_bf * matrix[indices, :] V_bf = tl.dot(tl.transpose(Zs_bf), Zs_bf) W_bf = tl.dot(tl.transpose(tensor[indices_list]), Zs_bf) F_hat_bf, a = err_rand_fast(tensor, factor_bf, V_bf, W_bf, indices_list, n_samples) F_hat_new, _ = err_rand_fast(tensor, factors[N - 1], V, W, indices_list, n_samples) if (F_hat_new > F_hat_bf): factors_hat = factors beta_bar = beta beta = beta / eta cpt = cpt + 1 else: factors = factors_hat beta_bar = min(1, beta_bar * gamma_bar) beta = min(beta_bar, gamma * beta) ######################################## ######### update for next it ######### ######################################## it = it + 1 if list_factors == True: list_fac.append(copy.deepcopy(factors)) error.append(F_hat_new / norm_tensor) if (error[len(error) - 1] < min_err): min_err = error[len(error) - 1] # err update else: err_it = err_it + 1 if time_rec == True: toc = time.time() list_time.append(toc - tic) error_ex.append(err(tensor, None, factors) / norm_tensor) # exact cost update # weights,factors=tl.cp_normalize((None,factors)) if list_factors == True and time_rec == True: return (weights, factors, it, error_ex, error, cpt / it, list_fac, list_time) if list_factors == True: return (weights, factors, it, error_ex, error, cpt / it, list_fac) if time_rec == True: return (weights, factors, it, error_ex, error, cpt / it, list_time) return (weights, factors, it, error_ex, error, cpt / it)
def test_err_fast(): """ Test err_fast for 3 tensors. plot the terminaison criterion (obtained by err_fast) and exact error. """ # create a kruskal tensor # factor matrices A = np.arange(9).reshape(3, 3) B = np.arange(6).reshape(2, 3) + 9 C = np.arange(6).reshape(2, 3) + 15 factors = [] factors += [A] factors += [B] factors += [C] t_krus = tl.cp_to_tensor((None, factors)) weights, factors, it, error, l = als(t_krus, 3, list_factors=True) err_ex = [] for i in l: err_ex += [err(t_krus, weights, i)] plt.figure(0) plt.plot(range(len(err_ex)), err_ex / tl.norm(t_krus), 'b-', label="exact") plt.plot(range(len(error)), error, 'r--', label="err fast") plt.xlabel('it') plt.yscale('log') plt.title('als for t_krus') plt.ylabel('terminaison criterion') plt.legend(loc='best') # create an complicated random tensor I = 50 J = 50 K = 50 r = 10 # rank fac_true, noise = init_factors(I, J, K, r, True) t = tl.cp_to_tensor((None, fac_true)) + noise weights, factors, it, error, l = als(t, r, list_factors=True) err_ex = [] for i in l: err_ex += [err(t, weights, i)] plt.figure(1) plt.plot(range(len(err_ex)), err_ex / tl.norm(t), 'b-', label="exact") plt.plot(range(len(error)), error, 'r--', label="err fast") plt.xlabel('it') plt.yscale('log') plt.title('als for complicated case') plt.ylabel('terminaison criterion') plt.legend(loc='best') # create a simple random tensor fac_true, noise = init_factors(I, J, K, r, False) t = tl.cp_to_tensor((None, fac_true)) + noise weights, factors, it, error, l = als(t, r, list_factors=True) err_ex = [] for i in l: err_ex += [err(t, weights, i)] plt.figure(2) plt.plot(range(len(err_ex)), err_ex / tl.norm(t), 'b-', label="exact") plt.plot(range(len(error)), error, 'r--', label="err fast") plt.xlabel('it') plt.yscale('log') plt.title('als for simple case') plt.ylabel('terminaison criterion') plt.legend(loc='best')
def CPRAND(tensor, rank, n_samples, factors=None, exact_err=False, it_max=100, err_it_max=20, tol=1e-7, list_factors=False, time_rec=False): """ CPRAND for CP-decomposition return also exact error Parameters ---------- tensor : tensor rank : int n_samples : int sample size factors : list of matrices, optional initial factor matrices. The default is None. exact_err : boolean, optional whether use err or err_rand_fast for terminaison criterion. The default is False. (not useful for this version) it_max : int, optional maximal number of iteration. The default is 100. err_it_max : int, optional maximal of iteration if terminaison critirion is not improved. The default is 20. tol : float, optional error tolerance. The default is 1e-7. list_factors : boolean, optional If true, then return factor matrices of each iteration. The default is False. time_rec : boolean, optional If true, return computation time of each iteration. The default is False. Returns ------- the CP decomposition, number of iteration and exact / estimated termination criterion. list_fac and list_time are optional. """ N = tl.ndim(tensor) # order of tensor norm_tensor = tl.norm(tensor) # norm of tensor if list_factors == True: list_fac = [] if time_rec == True: list_time = [] if (factors == None): factors = svd_init_fac(tensor, rank) # weights,factors=tl.cp_tensor.cp_normalize((None,factors)) if list_factors == True: list_fac.append(copy.deepcopy(factors)) weights = None it = 0 err_it = 0 ######################################## ######### error initialization ######### ######################################## temp, ind_err = err_rand(tensor, weights, factors, 400) error = [temp / norm_tensor] error_ex = [err(tensor, weights, factors) / norm_tensor] min_err = error[len(error) - 1] rng = tl.random.check_random_state(None) while (min_err > tol and it < it_max and err_it < err_it_max): if time_rec == True: tic = time.time() for n in range(N): Zs, indices = sample_khatri_rao(factors, n_samples, skip_matrix=n, random_state=rng) indices_list = [i.tolist() for i in indices] indices_list.insert(n, slice(None, None, None)) indices_list = tuple(indices_list) if (n == 0): sampled_unfolding = tensor[indices_list] else: sampled_unfolding = tl.transpose(tensor[indices_list]) V = tl.dot(tl.transpose(Zs), Zs) W = tl.dot(sampled_unfolding, Zs) # update factors[n] = tl.transpose(tl.solve( V, tl.transpose(W))) # solve needs a squared matrix if list_factors == True: list_fac.append(copy.deepcopy(factors)) it = it + 1 ################################ ######### error update ######### ################################ error.append( err_rand_fast(tensor, factors[N - 1], V, W, indices_list, n_samples)[0] / norm_tensor ) # same indices used as for Random Lesat Square Calculation if (error[len(error) - 1] < min_err): min_err = error[len(error) - 1] # err update else: err_it = err_it + 1 if time_rec == True: toc = time.time() list_time.append(toc - tic) error_ex.append(err(tensor, weights, factors) / norm_tensor) # weights,factors=tl.cp_tensor.cp_normalize((None,factors)) if time_rec == True and list_factors == True: return (weights, factors, it, error_ex, error, list_fac, list_time) if list_factors == True: return (weights, factors, it, error_ex, error, list_fac) if time_rec == True: return (weights, factors, it, error_ex, error, list_time) return (weights, factors, it, error_ex, error)
def her_CPRAND5(tensor, rank, n_samples, factors=None, exact_err=True, it_max=100, err_it_max=20, tol=1e-7, beta=0.1, eta=3, gamma=1.01, gamma_bar=1.005, list_factors=False, time_rec=False): """ different err sample taking mean value """ beta_bar = 1 N = tl.ndim(tensor) # order of tensor norm_tensor = tl.norm(tensor) # norm of tensor if list_factors == True: list_fac = [] if (time_rec == True): list_time = [] if (factors == None): factors = svd_init_fac(tensor, rank) # Initialization of factor hat matrice by factor matrices factors_hat = factors if list_factors == True: list_fac.append(copy.deepcopy(factors)) list_F_hat_bf = [] weights = None it = 0 err_it = 0 cpt = 0 n_samples_err = 400 # assuming that miu max = 1 ######################################## ######### error initialization ######### ######################################## F_hat_bf, ind_bf = err_rand(tensor, None, factors, n_samples_err) list_F_hat_bf.append(F_hat_bf) F_hat_bf_ex = err(tensor, None, factors) # exact cost rng = tl.check_random_state(None) error = [F_hat_bf / norm_tensor] error_ex = [F_hat_bf_ex / norm_tensor] min_err = error[len(error) - 1] while (min_err > tol and it < it_max and err_it < err_it_max): if time_rec == True: tic = time.time() for n in range(N): Zs, indices = sample_khatri_rao(factors_hat, n_samples, skip_matrix=n, random_state=rng) indices_list = [i.tolist() for i in indices] indices_list.insert(n, slice(None, None, None)) indices_list = tuple(indices_list) V = tl.dot(tl.transpose(Zs), Zs) # J'ai du mal avec la syntaxe tensor[indices_list], # Ca renvoie une matrices et non un tenseur? if (n == 0): sampled_unfolding = tensor[indices_list] else: sampled_unfolding = tl.transpose(tensor[indices_list]) W = tl.dot(sampled_unfolding, Zs) factor_bf = factors[n] # update factors[n] = tl.transpose( tl.solve(V, tl.transpose(W)) ) # solve needs a squared full rank matrix, if rank>nb_sampls ok # if (n==N-1) : F_hat_new=tl.norm(tl.dot(Zs,tl.transpose(factors[n]))-sampled_unfolding,2) # cost update # extrapolate factors_hat[n] = factors[n] + beta * (factors[n] - factor_bf) ######################################## ######### error update ######### ######################################## F_hat_new, _ = err_rand(tensor, weights, factors, n_samples_err, indices_list=ind_bf) # # added # a new sample ind_bf = [ np.random.choice(tl.shape(m)[0], n_samples_err) for m in factors ] ind_bf = [i.tolist() for i in ind_bf] ind_bf = tuple(ind_bf) list_F_hat_bf.append(F_hat_new) if (F_hat_new > F_hat_bf): factors_hat = factors beta_bar = beta beta = beta / eta cpt = cpt + 1 else: factors = factors_hat beta_bar = min(1, beta_bar * gamma_bar) beta = min(beta_bar, gamma * beta) ######################################## ######### update for next it ######### ######################################## it = it + 1 if it < 10: F_hat_bf = np.mean(list_F_hat_bf) else: F_hat_bf = np.mean(list_F_hat_bf[(len(list_F_hat_bf) - 10):(len(list_F_hat_bf) - 1)]) if list_factors == True: list_fac.append(copy.deepcopy(factors)) error.append(F_hat_new / norm_tensor) if (error[len(error) - 1] < min_err): min_err = error[len(error) - 1] # err update else: err_it = err_it + 1 if time_rec == True: toc = time.time() list_time.append(toc - tic) error_ex.append(err(tensor, None, factors) / norm_tensor) # exact cost update # weights,factors=tl.cp_normalize((None,factors)) if list_factors == True and time_rec == True: return (weights, factors, it, error_ex, error, cpt / it, list_fac, list_time) if list_factors == True: return (weights, factors, it, error_ex, error, cpt / it, list_fac) if time_rec == True: return (weights, factors, it, error_ex, error, cpt / it, list_time) return (weights, factors, it, error_ex, error, cpt / it)
def nn_her_CPRAND(tensor, rank, n_samples, n_samples_err=400, factors=None, exact_err=False, it_max=100, err_it_max=20, tol=1e-7, beta=0.1, eta=3, gamma=1.01, gamma_bar=1.005, list_factors=False, time_rec=False, filter=10): """ herCPRAND for nonnegative CP-decomposition same err sample taking mean value of last filter values Parameters ---------- tensor : tensor rank : int n_samples : int sample size n_samples_err : int, optional sample size used for error estimation. The default is 400. factors : list of matrices, optional an initial factor matrices. The default is None. exact_err : boolean, optional whether use err or err_rand_fast for terminaison criterion. The default is False. it_max : int, optional maximal number of iteration. The default is 100. err_it_max : int, optional maximal of iteration if terminaison critirion is not improved. The default is 20. tol : float, optional error tolerance. The default is 1e-7. beta : float, optional extrapolation parameter. The default is 0.5. eta : float, optional decrease coefficient of beta. The default is 1.5. gamma : float, optional increase coefficient of beta. The default is 1.05. gamma_bar : float, optional increase coeefficient of beta_bar. The default is 1.01. list_factors : boolean, optional If true, then return factor matrices of each iteration. The default is False. time_rec : boolean, optional If true, return computation time of each iteration. The default is False. filter : int, optional The filter size used for the mean value Returns ------- the CP decomposition, number of iteration, error and restart pourcentage. list_fac and list_time are optional. """ beta_bar = 1 N = tl.ndim(tensor) # order of tensor norm_tensor = tl.norm(tensor) # norm of tensor if list_factors == True: list_fac = [] if (time_rec == True): list_time = [] if (factors == None): factors = svd_init_fac(tensor, rank) # Initialization of factor hat matrice by factor matrices factors_hat = factors if list_factors == True: list_fac.append(copy.deepcopy(factors)) list_F_hat_bf = [] weights = None it = 0 err_it = 0 cpt = 0 ######################################## ######### error initialization ######### ######################################## if (exact_err == True): F_hat_bf = err(tensor, weights, factors) else: F_hat_bf, ind_bf = err_rand(tensor, None, factors, n_samples_err) list_F_hat_bf.append(F_hat_bf) rng = tl.check_random_state(None) error = [F_hat_bf / norm_tensor] min_err = error[len(error) - 1] while (min_err > tol and it < it_max and err_it < err_it_max): if time_rec == True: tic = time.time() for n in range(N): Zs, indices = sample_khatri_rao(factors_hat, n_samples, skip_matrix=n, random_state=rng) indices_list = [i.tolist() for i in indices] indices_list.insert(n, slice(None, None, None)) indices_list = tuple(indices_list) V = tl.dot(tl.transpose(Zs), Zs) if (n == 0): sampled_unfolding = tensor[indices_list] else: sampled_unfolding = tl.transpose(tensor[indices_list]) W = tl.dot(sampled_unfolding, Zs) factor_bf = factors[n] # update fac, _, _, _ = hals_nnls(tl.transpose(W), V, tl.transpose(factors[n])) factors[n] = tl.transpose( fac ) # solve needs a squared full rank matrix, if rank>nb_sampls ok # extrapolate factors_hat[n] = tl.clip(factors[n] + beta * (factors[n] - factor_bf), a_min=0.0) ######################################## ######### error update ######### ######################################## if (exact_err == False): F_hat_new, _ = err_rand(tensor, weights, factors, n_samples_err, indices_list=ind_bf) else: F_hat_new = err(tensor, weights, factors) list_F_hat_bf.append(F_hat_new) if (F_hat_new > F_hat_bf): factors_hat = factors beta_bar = beta beta = beta / eta cpt = cpt + 1 else: factors = factors_hat beta_bar = min(1, beta_bar * gamma_bar) beta = min(beta_bar, gamma * beta) ######################################## ######### update for next it ######### ######################################## it = it + 1 if (exact_err == False): if it < filter: F_hat_bf = np.mean(list_F_hat_bf) else: F_hat_bf = np.mean(list_F_hat_bf[(len(list_F_hat_bf) - filter):(len(list_F_hat_bf) - 1)]) else: F_hat_bf = F_hat_new if list_factors == True: list_fac.append(copy.deepcopy(factors)) error.append(F_hat_new / norm_tensor) if (error[len(error) - 1] < min_err): min_err = error[len(error) - 1] # err update else: err_it = err_it + 1 if time_rec == True: toc = time.time() list_time.append(toc - tic) if list_factors == True and time_rec == True: return (weights, factors, it, error, cpt / it, list_fac, list_time) if list_factors == True: return (weights, factors, it, error, cpt / it, list_fac) if time_rec == True: return (weights, factors, it, error, cpt / it, list_time) return (weights, factors, it, error, cpt / it)