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