def test_archetypalAnalysis(): img_file = 'lena.png' try: img = Image.open(img_file) except Exception as e: print("Cannot load image %s (%s) : skipping test" %(img_file,e)) return None I = np.array(img) / 255. if I.ndim == 3: A = np.asfortranarray(I.reshape((I.shape[0],I.shape[1] * I.shape[2])),dtype = myfloat) rgb = True else: A = np.asfortranarray(I,dtype = myfloat) rgb = False m = 8;n = 8; X = spams.im2col_sliding(A,m,n,rgb) X = X - np.tile(np.mean(X,0),(X.shape[0],1)) X = np.asfortranarray(X / np.tile(np.sqrt((X * X).sum(axis=0)),(X.shape[0],1)),dtype = myfloat) K = 64 # learns a dictionary with 64 elements robust = False # use robust archetypal analysis or not, default parameter(True) epsilon = 1e-3 # width in Huber loss, default parameter(1e-3) computeXtX = True # memorize the product XtX or not default parameter(True) stepsFISTA = 0 # 3 alternations by FISTA, default parameter(3) # a for loop in FISTA is used, we stop at 50 iterations # remember that we are not guarantee to descent in FISTA step if 50 is too small stepsAS = 10 # 7 alternations by activeSet, default parameter(50) randominit = True # random initilazation, default parameter(True) ############# FIRST EXPERIMENT ################## tic = time.time() # learn archetypes using activeSet method for each convex sub-problem (Z,A,B) = spams.archetypalAnalysis(np.asfortranarray(X[:, :10000]), returnAB= True, p = K, robust = robust, epsilon = epsilon, computeXtX = computeXtX, stepsFISTA = stepsFISTA , stepsAS = stepsAS, numThreads = -1) tac = time.time() t = tac - tic print('time of computation for Archetypal Dictionary Learning: %f' %t) print('Evaluating cost function...') alpha = spams.decompSimplex(np.asfortranarray(X[:, :10000]),Z = Z, computeXtX = True, numThreads = -1) xd = X[:,:10000] - Z * alpha R = np.sum(xd*xd) print("objective function: %f" %R) ############# FIRST EXPERIMENT ################## tic = time.time() # learn archetypes using activeSet method for each convex sub-problem Z2 = spams.archetypalAnalysis(np.asfortranarray(X[:, :10000]), Z0 = Z, robust = robust, epsilon = epsilon, computeXtX = computeXtX , stepsFISTA = stepsFISTA,stepsAS = stepsAS, numThreads = -1) tac = time.time() t = tac - tic print('time of computation for Archetypal Dictionary Learning (Continue): %f' %t) print('Evaluating cost function...') alpha = spams.decompSimplex(np.asfortranarray(X[:, :10000]),Z = np.asfortranarray(Z2), computeXtX = True, numThreads = -1) xd = X[:,:10000] - Z2 * alpha R = np.sum(xd*xd) print("objective function: %f" %R) # learn archetypes using activeSet method for each convex sub-problem (Z3,A3,B3) = spams.archetypalAnalysis(np.asfortranarray(X[:, :10000]), returnAB= True, p = K, robust = True, epsilon = epsilon, computeXtX = computeXtX, stepsFISTA = stepsFISTA , stepsAS = stepsAS, numThreads = -1) tac = time.time() t = tac - tic print('time of computation for Robust Archetypal Dictionary Learning: %f' %t)
def run_AA(data, n_archetypes, true_archetypal_coords=None, true_archetypes=None, method='PCHA', n_subsample=None, n_batches=40000, latent_noise=0.05, arch=[1024, 512, 256, 128], seed=42): """Runs Chen at al. 2014 on input data and calculates errors on the data in the archetypal space and the error between the learned vs true archetypes. Parameters ---------- data : [samples, features] Data in the feature space true_archetypal_coords : [samples, archetypes] Ground truth archetypal coordinates. Rows must sum to 1. true_archetypes : [archetypes, features] Ground truth archetypes in the feature space n_archetypes : int Number of archetypes to be learned method : ['PCHA', 'kernelPCHA', 'Chen', 'Javadi', 'NMF', 'PCHA_on_AE', 'AAnet'] The method to use for archetypal analysis n_subsample : int Number of data points to subsample seed : int Random seed batches : int Number of batches used to train AAnet or AutoEncoder Returns ------- mse_archetypes: float Mean squared error between the learned archetypes and the ground truth archetypes as calculated in the feature space mse_encoding: float Mean squared error between the true coordinates of the data in the archetypal space and the coordinates in the learned space new_archetypal_coords: [samples, archetypes] Learned encoding of the samples in the archetypal space new_archetypes: [archetypes, features] Learned archetypes in the feature space """ tic = time.time() # Select a subsample of the data np.random.seed(seed) if n_subsample is not None: r_idx = np.random.choice(data.shape[0], n_subsample, replace=False) data = data[r_idx, :] # otherwise really slow true_archetypal_coords = true_archetypal_coords[r_idx, :] if method == 'Chen': '''AA as implemented in Chen et al. 2014 https://arxiv.org/abs/1405.6472''' new_archetypes, new_archetypal_coords, _ = sp.archetypalAnalysis( np.asfortranarray(data.T), p=n_archetypes, returnAB=True, numThreads=-1) # Fix transposition new_archetypal_coords = new_archetypal_coords.toarray().T new_archetypes = new_archetypes.T elif method == 'Javadi': '''AA as implemented in Javadi et al. 2017 https://arxiv.org/abs/1705.02994''' new_archetypal_coords, new_archetypes, _, _ = javadi.acc_palm_nmf( data, r=n_archetypes, maxiter=25, plotloss=False, ploterror=False) elif method == 'PCHA': '''Principal convex hull analysis as implemented by Morup and Hansen 2012. https://www.sciencedirect.com/science/article/pii/S0925231211006060 ''' new_archetypes, new_archetypal_coords, _, _, _ = PCHA(data.T, noc=n_archetypes) new_archetypes = np.array(new_archetypes.T) new_archetypal_coords = np.array(new_archetypal_coords.T) elif method == 'kernelPCHA': '''PCHA in a kernel space as described by Morup and Hansen 2012. https://www.sciencedirect.com/science/article/pii/S0925231211006060 ''' D = scipy.spatial.distance.pdist(data) D = scipy.spatial.distance.squareform(D) sigma = np.std(D) #K = np.exp(-((D**2)/sigma)) K = data @ data.T _, new_archetypal_coords, C, _, _ = PCHA(K, noc=n_archetypes) new_archetypes = np.array(data.T @ C).T new_archetypal_coords = np.array(new_archetypal_coords.T) elif method == 'NMF': '''Factor analysis using non-negative matrix factorization (NMF)''' nnmf = NMF(n_components=n_archetypes, init='nndsvda', tol=1e-4, max_iter=1000) new_archetypal_coords = nnmf.fit_transform(data - np.min(data)) new_archetypes = nnmf.components_ elif method == 'PCHA_on_AE': ############## # MODEL PARAMS ############## noise_z_std = 0 z_dim = arch act_out = tf.nn.tanh input_dim = data.shape[1] enc_AE = network.Encoder(num_at=n_archetypes, z_dim=z_dim) dec_AE = network.Decoder(x_dim=input_dim, noise_z_std=noise_z_std, z_dim=z_dim, act_out=act_out) # By setting both gammas to zero, we arrive at the standard autoencoder AE = AAnet.AAnet(enc_AE, dec_AE, gamma_convex=0, gamma_nn=0) ########## # TRAINING ########## # AE AE.train(data, batch_size=256, num_batches=n_batches) latent_encoding = AE.data2z(data) # PCHA learns an encoding into a simplex new_archetypes, new_archetypal_coords, _, _, _ = PCHA( latent_encoding.T, noc=n_archetypes) new_archetypes = np.array(new_archetypes.T) new_archetypal_coords = np.array(new_archetypal_coords.T) # Decode ATs new_archetypes = AE.z2data(new_archetypes) elif method == 'AAnet': ############## # MODEL PARAMS ############## noise_z_std = latent_noise z_dim = arch act_out = tf.nn.tanh input_dim = data.shape[1] enc_net = network.Encoder(num_at=n_archetypes, z_dim=z_dim) dec_net = network.Decoder(x_dim=input_dim, noise_z_std=noise_z_std, z_dim=z_dim, act_out=act_out) model = AAnet.AAnet(enc_net, dec_net) ########## # TRAINING ########## model.train(data, batch_size=256, num_batches=n_batches) ################### # GETTING OUTPUT ################### new_archetypal_coords = model.data2at(data) new_archetypes = model.get_ats_x() else: raise ValueError('{} is not a valid method'.format(method)) toc = time.time() - tic # Calculate MSE if given ground truth if true_archetypes is not None: mse_archetypes, _, _ = calc_MSE(new_archetypes, true_archetypes) else: mse_archetypes = None if true_archetypal_coords is not None: mse_encoding, _, _ = calc_MSE(new_archetypal_coords.T, true_archetypal_coords.T) else: mse_encoding = None return mse_archetypes, mse_encoding, new_archetypal_coords, new_archetypes, toc
def test_archetypalAnalysis(): img_file = 'lena.png' try: img = Image.open(img_file) except Exception as e: print "Cannot load image %s (%s) : skipping test" %(img_file,e) return None I = np.array(img) / 255. if I.ndim == 3: A = np.asfortranarray(I.reshape((I.shape[0],I.shape[1] * I.shape[2])),dtype = myfloat) rgb = True else: A = np.asfortranarray(I,dtype = myfloat) rgb = False m = 8;n = 8; X = spams.im2col_sliding(A,m,n,rgb) X = X - np.tile(np.mean(X,0),(X.shape[0],1)) X = np.asfortranarray(X / np.tile(np.sqrt((X * X).sum(axis=0)),(X.shape[0],1)),dtype = myfloat) K = 64 # learns a dictionary with 64 elements robust = False # use robust archetypal analysis or not, default parameter(True) epsilon = 1e-3 # width in Huber loss, default parameter(1e-3) computeXtX = True # memorize the product XtX or not default parameter(True) stepsFISTA = 0 # 3 alternations by FISTA, default parameter(3) # a for loop in FISTA is used, we stop at 50 iterations # remember that we are not guarantee to descent in FISTA step if 50 is too small stepsAS = 10 # 7 alternations by activeSet, default parameter(50) randominit = True # random initilazation, default parameter(True) ############# FIRST EXPERIMENT ################## tic = time.time() # learn archetypes using activeSet method for each convex sub-problem (Z,A,B) = spams.archetypalAnalysis(np.asfortranarray(X[:, :10000]), returnAB= True, p = K, robust = robust, epsilon = epsilon, computeXtX = computeXtX, stepsFISTA = stepsFISTA , stepsAS = stepsAS, numThreads = -1) tac = time.time() t = tac - tic print 'time of computation for Archetypal Dictionary Learning: %f' %t print 'Evaluating cost function...' alpha = spams.decompSimplex(np.asfortranarray(X[:, :10000]),Z = Z, computeXtX = True, numThreads = -1) xd = X[:,:10000] - Z * alpha R = np.sum(xd*xd) print "objective function: %f" %R ############# FIRST EXPERIMENT ################## tic = time.time() # learn archetypes using activeSet method for each convex sub-problem Z2 = spams.archetypalAnalysis(np.asfortranarray(X[:, :10000]), Z0 = Z, robust = robust, epsilon = epsilon, computeXtX = computeXtX , stepsFISTA = stepsFISTA,stepsAS = stepsAS, numThreads = -1) tac = time.time() t = tac - tic print 'time of computation for Archetypal Dictionary Learning (Continue): %f' %t print 'Evaluating cost function...' alpha = spams.decompSimplex(np.asfortranarray(X[:, :10000]),Z = np.asfortranarray(Z2), computeXtX = True, numThreads = -1) xd = X[:,:10000] - Z2 * alpha R = np.sum(xd*xd) print "objective function: %f" %R # learn archetypes using activeSet method for each convex sub-problem (Z3,A3,B3) = spams.archetypalAnalysis(np.asfortranarray(X[:, :10000]), returnAB= True, p = K, robust = True, epsilon = epsilon, computeXtX = computeXtX, stepsFISTA = stepsFISTA , stepsAS = stepsAS, numThreads = -1) tac = time.time() t = tac - tic print 'time of computation for Robust Archetypal Dictionary Learning: %f' %t
L = 1 log.info('ArchetypalAnalysis for ' + str(L) + ' layers') X = torch.load('tensors/tensor' + str(L) + '.pt') X = torch.t(X).numpy() K = 32 # learns a dictionary with 32 elements robust = True # use robust archetypal analysis or not, default parameter(True) epsilon = 1e-3 # width in Huber loss, default parameter(1e-3) computeXtX = True # memorize the product XtX or not default parameter(True) stepsFISTA = 0 # 3 alternations by FISTA, default parameter(3) # a for loop in FISTA is used, we stop at 50 iterations # remember that we are not guarantee to descent in FISTA step if 50 is too small stepsAS = 25 # 7 alternations by activeSet, default parameter(50) randominit = True # random initilazation, default para (Z,A,B) = spams.archetypalAnalysis(np.asfortranarray(X), returnAB= True, p = K, \ robust = robust, epsilon = epsilon, computeXtX = computeXtX, stepsFISTA = stepsFISTA , stepsAS = stepsAS, numThreads = -1) print('Evaluating cost function...') alpha = spams.decompSimplex(np.asfortranarray(X), Z=Z, computeXtX=True, numThreads=-1) xd = X - Z * alpha R = np.sum(xd * xd) print("objective function: %f" % R) print(Z.shape) print(A.shape) print(B.shape) torch.save(Z, 'tensors/Z' + str(L) + '.pt') torch.save(A, 'tensors/A' + str(L) + '.pt') torch.save(B, 'tensors/B' + str(L) + '.pt')