def forward(self, x, z): """ Forward pass ------------ Args: x (FloatTensor): input of the function z (FloatTensor): representation of the function Returns: FloatTensor: the output of the function """ # checks the size of the tensor if len(x.size()) != 2: printl(ERROR, f'x must have 2 axis, now {len(x.size())}') raise AttributeError # checks if the data is one dimensional if x.size()[-1] != 1: printl(ERROR, f'x must have 1 dimensions, now {x.size()[-1]}') raise AttributeError # computes the parameters of the function a = self.a(z) f = self.f(z) p = self.p(z) # expand x for one-time computation xx = x.expand(-1, self.nb_sin) # computes all sinus and mixes them yy = a * torch.sin(f * xx + p) y = yy.sum(dim=1) return y
def forward(self, x, z): """ Forward pass ------------ Args: x (FloatTensor): input of the function z (FloatTensor): representation of the function Returns: FloatTensor: the output of the function """ # checks the size of the tensor if len(x.size()) != 2: printl(ERROR, f'x must have 2 axis, now {len(x.size())}') raise AttributeError # checks if the data is one dimensional if x.size()[-1] != 1: printl(ERROR, f'x must have 1 dimensions, now {x.size()[-1]}') raise AttributeError # computes the parameters of the function a = self.a(z) b = self.b(z) c = self.c(z) # computes the slope y = a * x**2 + b * x + c return y
def create_dataset(dataset_type, root, train_ratio, create_fct, **config): """ Creates an arbitrary dataset ---------------------------- Args: dataset_type (str): type of the selected dataset root (str): path where to save the dataset train_ratio (float): ratio of the train dataset create_fct (function): function of the selected dataset config (dict): configuration of the selected dataset """ # check if the dataset folder already exists if os.path.isdir(root): printl(ERROR, 'A dataset already exists at this location') exit() # creates the datasets printl(INFO, 'Creating the dataset') dataset = create_fct(**config) # splits the dataset in train and test train_size = int(train_ratio * len(dataset)) train_idx = random.sample(range(len(dataset)), k=train_size) train_set = [dataset[i] for i in range(len(dataset)) if i in train_idx] test_set = [dataset[i] for i in range(len(dataset)) if i not in train_idx] # creates the root folder os.mkdir(root) # creates the paths config_path = os.path.join(root, 'config.json') train_path = os.path.join(root, 'train.pt') test_path = os.path.join(root, 'test.pt') # save the config config['type'] = dataset_type config['train_size'] = train_size config['test_size'] = len(dataset) - train_size config['timestamp'] = time.time() with open(config_path, 'w') as f: json.dump(config, f) # save the dataset torch.save(train_set, train_path) torch.save(test_set, test_path)
def create(size, nb_sin, x_range, x_length, y_range, f_range): """ Creates a SinMix dataset ------------------------ Args: size (int): the size of the dataset nb_sin (int): the number of sinus in a mix y_range (int): guarantees an output x inside [-x_range, x_range] x_length (int): the number of sampled x y_range (int): guarantees an output y inside [-y_range, y_range] f_range (int): the range of f [-a_range, a_range] Returns: List of List of FloatTensor: the dataset """ # informs the user printl( INFO, f"""A new SinMix dataset will be created with > {nb_sin} sinus > x_min: {x_range}, > x_length: {x_length} > y range: [-{y_range}, {y_range}] > f range: [0, {f_range}]""") # computes a new range a_range = y_range / nb_sin # main creation loop data, list_params = [], [] for i in range(size): # creates the x and y space x = np.linspace(-x_range, x_range, x_length) y = np.zeros_like(x) # creates random mixture of sin aa, ff, pp = [], [], [] for _ in range(nb_sin): # draws parameter a a = 0 while a == 0: a = random.random() * a_range * 2 - a_range # draws parameter f f = 0 while f == 0: f = random.random() * f_range # draws parameter p p = random.random() * 2 * np.pi # computes the outputs y += a * np.sin(f * x + p) # adds to the accumulators aa.append(a) ff.append(f) pp.append(p) # checks if the y range works assert (np.abs(y) < y_range).all() # checks if the function already exists in the dataset if [aa, ff, pp] in list_params: printl(INFO, 'The function is already chosen, skipping it') else: # adds the parameters to the list of parameters list_params.append([aa, ff, pp]) # converts to torch tensor y = torch.FloatTensor(y).float() params = torch.FloatTensor([aa, ff, pp]).float() # adds the function to data data.append([y, params]) # prints to screen if (i + 1) % int(0.1 * size) == 0: printl( INFO, 'Mixture {:3}% done'.format(int(100 * ((i + 1) / size)))) return data
def create(size, x_range, x_length, y_range, h_range): """ Creates a Parabolas dataset ------------------------ Args: size (int): the size of the dataset x_range (int): guarantees an output x inside [-x_range, x_range] x_length (int): the number of sampled x y_range (int): guarantees an output y inside [-y_range, y_range] h_range (int): the range of the maxima's x [-h_range, h_range] Returns: List of List of FloatTensor: the dataset """ # informs the user printl( INFO, f"""A new Parabolas dataset will be created with > x_range: [-{x_range}, {x_range}], > x_length: {x_length} > y range: [-{y_range}, {y_range}] > h range: [-{h_range}, {h_range}]""") # main creation loop data, list_params = [], [] for i in range(size): # creates the x and y space x = np.linspace(-x_range, x_range, x_length) # draws parameter h h = random.random() * h_range * 2 - h_range # computes repetitive quantities pre_min = (x_range + h)**2 pre_max = (x_range - h)**2 # draws parameter a and k if abs(h) > x_range: # computes range of parameter a a_range = 2 * y_range / (pre_max - pre_min) a_min = -a_range a_max = a_range # draws parameter a a = 0 while a == 0: a = random.random() * (a_max - a_min) + a_min # computes range for parameter k if h < -x_range and a > 0 or h > x_range and a < 0: k_min = -y_range - a * pre_min k_max = y_range - a * pre_max else: k_min = -y_range - a * pre_max k_max = y_range - a * pre_min else: # computes range of parameter a if h < 0: a_range = 2 * y_range / pre_max else: a_range = 2 * y_range / pre_min a_min = -a_range a_max = a_range # draws parameter a a = random.random() * (a_max - a_min) + a_min # computes range for parameter k if h < 0 and a > 0: k_min = -y_range k_max = y_range - a * pre_max elif h > 0 and a < 0: k_min = -y_range - a * pre_min k_max = y_range elif h < 0 and a < 0: k_min = -y_range - a * pre_max k_max = y_range else: k_min = -y_range k_max = y_range - a * pre_min # draws parameter k k = random.random() * (k_max - k_min) + k_min # convert to a, b, c b = -2 * a * h c = a * (h**2) + k # computes the outputs y = a * x**2 + b * x + c # checks if the y range works try: assert (np.abs(y) <= y_range).all() except AssertionError: print('-> {:.2f}'.format(2 * y_range / (pre_max - pre_min))) import matplotlib.pyplot as plt _, (ax1, ax2) = plt.subplots(1, 2) ax1.plot(x, y) ax2.plot(x, a * (x - h)**2 + k) plt.show() raise AssertionError # checks if the function already exists in the dataset if [a, b, c] in list_params: printl(INFO, 'The function is already chosen, skipping it') else: # adds the parameters to the list of parameters list_params.append([a, b, c]) # converts to torch tensor y = torch.FloatTensor(y).float() params = torch.FloatTensor([a, b, c]).float() # adds the function to data data.append([y, params]) # prints to screen if (i + 1) % int(0.1 * size) == 0: printl( INFO, 'Parabolas {:3}% done'.format(int(100 * ((i + 1) / size)))) return data