예제 #1
0
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()
예제 #2
0
    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)
예제 #3
0
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()
예제 #4
0
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
예제 #5
0
        # 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)