def __init__(self, k=2, gamma=1, n_components=500, metric='rbf', y_gamma=100, opu=None, x_opu=False, y_opu=False, x_postproc=None, y_postproc=None, feature_encoder=None): super().__init__() self.k = k self.opu = opu self.gamma = gamma if opu is None: self.metric = metric self.x_features = RBFSampler(gamma=gamma, n_components=n_components) self.y_features = RBFSampler(gamma=y_gamma, n_components=self.k) else: if x_opu: self.x_features = make_pipeline( feature_encoder, OPUMap(n_components=n_components, opu=opu, verbose_level=0)) else: self.x_features = RBFSampler(gamma=gamma, n_components=n_components) if y_opu: # n_components should be k but since it's the same OPU object it would mess with x_features self.y_features = OPUMap(n_components=n_components, opu=opu, verbose_level=0) else: self.y_features = RBFSampler(gamma=y_gamma, n_components=self.k) self.x_postproc = x_postproc self.y_postproc = y_postproc self.U = None self.psi = None self.train_data = None
def __init__(self, k=2, y_gamma=100, opu=None, postproc=None): super().__init__() self.k = k self.opu = opu self.postproc = postproc if opu is None: self.y_features = RBFSampler(gamma=y_gamma, n_components=self.k) else: self.y_features = OPUMap(n_components=k, opu=opu) self.U = None
def forward(self, data): if self.precomputed is None: # The opu needs data to be in numpy uint8 binary format! data = data.numpy().astype('uint8') # append bias to the data # for the real OPU, the bias is represented by an array of ones # unlike for the simulated OPU, the value already needs to be squared bias_vector = np.ones((len(data), self.bias**2)).astype('uint8') data = np.hstack([data, bias_vector]) # this part communicates with the physical device from lightonml.projections.sklearn import OPUMap from lightonopu.opu import OPU with OPU(n_components=self.output_features) as opu_dev: random_mapping = OPUMap(opu=opu_dev, n_components=self.output_features, ndims=1) random_mapping.opu.device.exposure_us = self.eposure_us random_mapping.opu.device.frametime_us = self.eposure_us + 100 output = random_mapping.transform(data).astype('float32') else: output = self.precomputed.astype('float32') if self.raw_features: return output # Now we have to be careful: # The OPU has an unknown variance defined by physical settings # However, we can estimate it and normalize the projection to var=0.5 opu_var = self.estimate_opu_variance(data, output) # We have OPU(x)_i = (w_i @ x)**2 + (v_i @ x)**2 # = opu_var * (N(0,I) @ x)**2 + (N(0,I) @ x)**2 # => We need to divide the projection by opu_var and multiply by 0.5 output = output / opu_var * 0.5 # => We have sampled all real entries from N(0, 0.5) like for the simulated device! output = output**(self.degree // 2) output = self.scale * output # We convert the data back to PyTorch format return torch.from_numpy(output).type(torch.FloatTensor)
def __init__(self, input_dim, features_num): self.features_num = features_num self.random_mapping = OPUMap(n_components=features_num) self.random_mapping.opu.open()
def get_random_features(X, n_components, opu_map=None, matrix=None, conv_blocks=1, device="cuda:0"): """ Performs the random projection of the encoded random features X using the OPU. Parameters ---------- X: numpy 2d array or torch.tensor, encoded convolutional training features. Make sure that the dtype is int8 if n_components!=0. n_components: int, number of random projections. opu_map: OPUMap object or None, OPUMap object for performing the projection with the OPU. If None, it is generated automatically. You should pass it when you plan to do multiple projections in the same script. matrix: None or torch.tensor, Matrix to use for the random projection on GPU. If None, the OPU will be used. conv_blocks: int, number of splits for the input matrix if GPU is used. device: str, device for the random projection if the OPU is not used. Examples are "cpu" or "cuda:0". Returns ------- proj_time: float, projection time for the features. random_features: numpy 2d array, random features of the training set. If n_components=0, the original train random features are returned. """ if n_components == 0: train_time = 0. # The conversion to numpy is needed for compatibility with the MixingBitPlanDecoder. if type(X) is not np.ndarray: X = X.numpy() return train_time, X if matrix is not None: if isinstance(X, np.ndarray): X = torch.FloatTensor(X) X_blocks = X.split(conv_blocks) random_features, train_time = get_rand_features_GPU(X_blocks, matrix, device=device) else: if opu_map is None: opu_map = OPUMap(n_components=n_components) since = time() random_features = opu_map.transform(X) train_time = time() - since return train_time, random_features
def main(args): if args.save_path is not None: folder_name = os.path.join( args.save_path, "graph_nodes_{}_clique_{}_{}".format(args.n_nodes, args.clique_size, args.device)) pathlib.Path(folder_name).mkdir(parents=True, exist_ok=True) else: folder_name = None # Erase this, I hardcoded the number of components and the clique_size if args.device == "opu": R = None generation_time = 0. conv_blocks = 1 opu_map = OPUMap(n_components=args.n_components) else: print("Generating random matrix of size ({} x {})".format( args.n_nodes, args.n_components)) GPU_optimizer = GPU_matrix(n_samples=args.n_nodes, n_features=args.n_nodes, n_components=args.n_components, GPU_memory=args.GPU_memory) R, generation_time = GPU_optimizer.generate_RM() conv_blocks = args.n_nodes // GPU_optimizer.conv_blocks_size print("Generation time = {0:3.2f} s".format(generation_time)) print("Splits size: R = {}\t conv = {}\n".format( GPU_optimizer.R_blocks_size, GPU_optimizer.conv_blocks_size)) opu_map = None graph = Graph(n_nodes=args.n_nodes, p_edges=args.p_edges, clique_size=args.clique_size, clique_step=args.clique_step, noise_ratio=args.noise_ratio, save_path=folder_name) graph.__info__() newma = NEWMA(args.n_nodes, args.n_components, time_window=args.time_window, l_ratio=args.l_ratio, eta=args.eta, rescale_tau=args.rescale_tau, power_iter=args.power_iter, save_path=folder_name) with torch.no_grad(): for t in range(1, args.t_end): new_edges = graph.evolve() if args.t_clique <= t <= args.t_clique + args.clique_step: graph.create_clique(progression=t - args.t_clique + 1) Adj_matrix = torch.FloatTensor(nx.to_numpy_array(graph.G)) if args.device == "opu": Adj_matrix = Adj_matrix.bool() proj_time, random_features = get_random_features( Adj_matrix, args.n_components, opu_map=opu_map, matrix=R, conv_blocks=conv_blocks, device=args.device) newma.detect(random_features.float(), t=t) eigenvector = newma.compute_eigenvector(Adj_matrix.float()) newma.update_log(t, graph.G.number_of_edges(), generation_time, proj_time) if args.save_path is not None and t >= args.t_start: graph.update_plot(new_edges, eigenvector, newma, args.t_start, args.t_end, args.t_clique) newma.update_threshold() return
B = 250 # window size d = n_feat # Forget factors chosen with heuristic in the paper big_Lambda, small_lambda = algos.select_optimal_parameters(B) thres_ff = small_lambda # Number of random features is set automatically with this criterion m = int((1 / 4) / (small_lambda + big_Lambda)**2) m_OPU = 10 * m print(f'{m_OPU} random features.') if pyramid: # Pyramid sketch nc = 60000 # Opening the OPU opu_mapping = OPUMap(n_components=nc) # First encoding encoder = BinaryThresholdEncoder(threshold_enc=10) minX, maxX = np.min(traj), np.max(traj) length_simulation = traj.shape[0] trajprojection = np.zeros((length_simulation, 3 * nc)) for i in range(3): print(f"First sketch of the data... Step {i + 1} out of 3.") cut = n_atoms X = traj[:, cut * i:cut * (i + 1)] X = 255 * ((X - minX) / (maxX - minX)) X = X.astype('uint8') Xencode = encoder.transform(X) del X
t_lopu = empty((len(d_list), len(p_list))) for i in range(len(d_list)): d = d_list[i] print("d = " + str(d), end=".\n") print("Sampling x...", end=" ") x = torch.distributions.Binomial(1, r).sample( (repetitions, n, d)).type(dtype).numpy().astype('uint8') print("Done.") for j in range(len(p_list)): p = p_list[j] print("p = " + str(p), end=".\n") print("Building OPU object...") e1_lopu = time.time() #opu = OPU(p) random_mapping = OPUMap(n_components=p, ndims=1) e2_lopu = time.time() t_lopu[i, j] = e2_lopu - e1_lopu print("Done.") print("Start matmuls...") e1_opu = time.time() for repe in range(repetitions): _ = random_mapping.transform(x[repe, :, :]) e2_opu = time.time() print("Done.") t_opu[i, j] = (e2_opu - e1_opu) / repetitions print("OPU loading time:") print(t_lopu) print("OPU time:")