class Lighton_random_features(feature_map): ''' This class affords an approximation of the Gaussian kernel using random features. When initializing a new instance, you should pass: sigma: STD of the Gaussian kernel input_dim, features_num: size of projection matrix ''' 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 transform(self, A): A=np.uint8(A.T) train_random_features = self.random_mapping.transform(A) return train_random_features.astype('float32').T def close(self): self.random_mapping.opu.close()
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)
class Lighton_random_features(feature_map): ''' This class computes optical random features with the help of OPUs technology developed by LightOn company. When initializing a new instance, you should pass: input_dim, features_num: size of projection matrix ''' 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 transform(self, A): A = np.uint8(A.T) train_random_features = self.random_mapping.transform(A) return train_random_features.astype('float32').T def close(self): self.random_mapping.opu.close()
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
# 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 X = opu_mapping.transform(Xencode) del Xencode trajprojection[:, i * nc:(i + 1) * nc] = X[:, :] del X print("Starting second sketch.") opu_mapping = OPUMap(n_components=m_OPU) n_levels = 38 minX, maxX = np.min(trajprojection), np.max(trajprojection) print('Rescaling X') X = 255 * ((trajprojection - minX) / (maxX - minX)) X = X.astype('uint8') print('Encoding X with the multi threshold encoder') thresholds = np.arange(n_levels, step=8)
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:") print(t_opu) np.save(results_dir + "opu_time", t_opu) np.save(results_dir + "opu_loadingtime", t_lopu)