Esempio n. 1
0
    def generate_sample(self, initial_pos, num_samples, stepsize=None):
        """
        Returns a generator type object whose each iteration yields a sample

        Parameters
        ----------
        initial_pos: A 1d array like object
            Vector representing values of parameter position, the starting
            state in markov chain.

        num_samples: int
            Number of samples to be generated

        stepsize: float , defaults to None
            The stepsize for proposing new values of position and momentum in simulate_dynamics
            If None, then will be chosen suitably

        Returns
        -------
        generator: yielding a numpy.array type object for a sample

        Examples
        ---------
        >>> from ProbabilityModel.sampling import NoUTurnSampler as NUTS, GradLogPDFGaussian
        >>> from ProbabilityModel.factors.continuous import GaussianDistribution as JGD
        >>> import numpy as np
        >>> mean = np.array([11, -6])
        >>> covariance = np.array([[0.7, 0.2], [0.2, 14]])
        >>> model = JGD(['x', 'y'], mean, covariance)
        >>> sampler = NUTS(model=model, grad_log_pdf=GradLogPDFGaussian)
        >>> samples = sampler.generate_sample(initial_pos=np.array([1, 1]), num_samples=10, stepsize=0.4)
        >>> samples = np.array([sample for sample in samples])
        >>> samples
        array([[ 10.26357538,   0.10062725],
               [ 12.70600336,   0.63392499],
               [ 10.95523217,  -0.62079273],
               [ 10.66263031,  -4.08135962],
               [ 10.59255762,  -8.48085076],
               [  9.99860242,  -9.47096032],
               [ 10.5733564 ,  -9.83504745],
               [ 11.51302059,  -9.49919523],
               [ 11.31892143,  -8.5873259 ],
               [ 11.29008667,  -0.43809674]])
        """
        initial_pos = _check_1d_array_object(initial_pos, "initial_pos")
        _check_length_equal(initial_pos, self.model.variables, "initial_pos",
                            "model.variables")

        if stepsize is None:
            stepsize = self._find_reasonable_stepsize(initial_pos)

        position_m = initial_pos

        for _ in range(0, num_samples):

            position_m = self._sample(position_m, stepsize)

            yield position_m
Esempio n. 2
0
    def __init__(self, variable_assignments, model):

        self.variable_assignments = _check_1d_array_object(
            variable_assignments, "variable_assignments")
        _check_length_equal(
            variable_assignments,
            model.variables,
            "variable_assignments",
            "model.variables",
        )

        self.model = model

        # The gradient log of probability distribution at position
        self.grad_log = None

        # The gradient log of probability distribution at position
        self.log_pdf = None
Esempio n. 3
0
    def __init__(self,
                 model,
                 position,
                 momentum,
                 stepsize,
                 grad_log_pdf,
                 grad_log_position=None):

        position = _check_1d_array_object(position, "position")

        momentum = _check_1d_array_object(momentum, "momentum")

        if not issubclass(grad_log_pdf, BaseGradLogPDF):
            raise TypeError(
                "grad_log_pdf must be an instance" +
                " of ProbabilityModel.inference.continuous.base.BaseGradLogPDF"
            )

        _check_length_equal(position, momentum, "position", "momentum")
        _check_length_equal(position, model.variables, "position",
                            "model.variables")

        if grad_log_position is None:
            grad_log_position, _ = grad_log_pdf(position,
                                                model).get_gradient_log_pdf()

        else:
            grad_log_positon = _check_1d_array_object(grad_log_position,
                                                      "grad_log_position")
            _check_length_equal(grad_log_position, position,
                                "grad_log_position", "position")

        self.position = position
        self.momentum = momentum
        self.stepsize = stepsize
        self.model = model
        self.grad_log_pdf = grad_log_pdf
        self.grad_log_position = grad_log_position

        # new_position is the new proposed position, new_momentum is the new proposed momentum, new_grad_lop
        # is the value of grad log at new_position
        self.new_position = self.new_momentum = self.new_grad_logp = None
Esempio n. 4
0
    def generate_sample(self,
                        initial_pos,
                        num_adapt,
                        num_samples,
                        stepsize=None):
        """
        Returns a generator type object whose each iteration yields a sample

        Parameters
        ----------
        initial_pos: A 1d array like object
            Vector representing values of parameter position, the starting
            state in markov chain.

        num_adapt: int
            The number of iterations to run the adaptation of stepsize

        num_samples: int
            Number of samples to be generated

        stepsize: float , defaults to None
            The stepsize for proposing new values of position and momentum in simulate_dynamics
            If None, then will be chosen suitably

        Returns
        -------
        genrator: yielding a numpy.array type object for a sample

        Examples
        --------
        >>> from ProbabilityModel.sampling import NoUTurnSamplerDA as NUTSda, GradLogPDFGaussian
        >>> from ProbabilityModel.factors.continuous import GaussianDistribution as JGD
        >>> import numpy as np
        >>> mean = np.array([1, -100])
        >>> covariance = np.array([[-12, 45], [45, -10]])
        >>> model = JGD(['a', 'b'], mean, covariance)
        >>> sampler = NUTSda(model=model, grad_log_pdf=GradLogPDFGaussian, simulate_dynamics=LeapFrog)
        >>> samples = sampler.generate_sample(initial_pos=np.array([12, -4]), num_adapt=10,
        ...                                   num_samples=10, stepsize=0.1)
        >>> samples
        <generator object NoUTurnSamplerDA.generate_sample at 0x7f4fed46a4c0>
        >>> samples_array = np.array([sample for sample in samples])
        >>> samples_array
        array([[ 11.89963386,  -4.06572636],
               [ 10.3453755 ,  -7.5700289 ],
               [-26.56899659, -15.3920684 ],
               [-29.97143077, -12.0801625 ],
               [-29.97143077, -12.0801625 ],
               [-33.07960829,  -8.90440347],
               [-55.28263496, -17.31718524],
               [-55.28263496, -17.31718524],
               [-56.63440044, -16.03309364],
               [-63.880094  , -19.19981944]])
        """
        initial_pos = _check_1d_array_object(initial_pos, "initial_pos")
        _check_length_equal(initial_pos, self.model.variables, "initial_pos",
                            "model.variables")

        if stepsize is None:
            stepsize = self._find_reasonable_stepsize(initial_pos)

        if num_adapt <= 1:  # return sample generated using Simple HMC algorithm
            for sample in NoUTurnSampler(
                    self.model, self.grad_log_pdf,
                    self.simulate_dynamics).generate_sample(
                        initial_pos, num_samples, stepsize):
                yield sample
            return
        mu = np.log(10.0 * stepsize)

        stepsize_bar = 1.0
        h_bar = 0.0

        position_m = initial_pos.copy()
        num_adapt += 1

        for i in range(1, num_samples + 1):

            position_m, alpha, n_alpha = self._sample(position_m, stepsize)

            if i <= num_adapt:
                stepsize, stepsize_bar, h_bar = self._adapt_params(
                    stepsize, stepsize_bar, h_bar, mu, i, alpha, n_alpha)
            else:
                stepsize = stepsize_bar

            yield position_m
Esempio n. 5
0
    def sample(
        self,
        initial_pos,
        num_adapt,
        num_samples,
        stepsize=None,
        return_type="dataframe",
    ):
        """
        Returns samples using No U Turn Sampler with dual averaging

        Parameters
        ----------
        initial_pos: A 1d array like object
            Vector representing values of parameter position, the starting
            state in markov chain.

        num_adapt: int
            The number of iterations to run the adaptation of stepsize

        num_samples: int
            Number of samples to be generated

        stepsize: float , defaults to None
            The stepsize for proposing new values of position and momentum in simulate_dynamics
            If None, then will be chosen suitably

        return_type: string (dataframe | recarray)
            Return type for samples, either of 'dataframe' or 'recarray'.
            Defaults to 'dataframe'

        Returns
        -------
        sampled: A pandas.DataFrame or a numpy.recarray object depending upon return_type argument


        Examples
        ---------
        >>> from ProbabilityModel.sampling import NoUTurnSamplerDA as NUTSda, GradLogPDFGaussian, LeapFrog
        >>> from ProbabilityModel.factors.continuous import GaussianDistribution as JGD
        >>> import numpy as np
        >>> mean = np.array([10, -13])
        >>> covariance = np.array([[16, -3], [-3, 13]])
        >>> model = JGD(['x', 'y'], mean, covariance)
        >>> sampler = NUTSda(model=model, grad_log_pdf=GradLogPDFGaussian, simulate_dynamics=LeapFrog)
        >>> samples = sampler.sample(initial_pos=np.array([12, -4]), num_adapt=10, num_samples=10,
        ...                          stepsize=0.1, return_type='dataframe')
        >>> samples
                   x          y
        0  12.000000  -4.000000
        1  11.864821  -3.696109
        2  10.546986  -4.892169
        3   8.526596 -21.555793
        4   8.526596 -21.555793
        5  11.343194  -6.353789
        6  -1.583269 -12.802931
        7  12.411957 -11.704859
        8  13.253336 -20.169492
        9  11.295901  -7.665058
        """
        initial_pos = _check_1d_array_object(initial_pos, "initial_pos")
        _check_length_equal(initial_pos, self.model.variables, "initial_pos",
                            "model.variables")

        if stepsize is None:
            stepsize = self._find_reasonable_stepsize(initial_pos)

        if num_adapt <= 1:
            return NoUTurnSampler(self.model, self.grad_log_pdf,
                                  self.simulate_dynamics).sample(
                                      initial_pos, num_samples, stepsize)

        mu = np.log(10.0 * stepsize)
        stepsize_bar = 1.0
        h_bar = 0.0

        types = [(var_name, "float") for var_name in self.model.variables]
        samples = np.zeros(num_samples, dtype=types).view(np.recarray)
        samples[0] = tuple(initial_pos)
        position_m = initial_pos

        for i in tqdm(range(1, num_samples)):

            position_m, alpha, n_alpha = self._sample(position_m, stepsize)
            samples[i] = tuple(position_m)

            if i <= num_adapt:
                stepsize, stepsize_bar, h_bar = self._adapt_params(
                    stepsize, stepsize_bar, h_bar, mu, i, alpha, n_alpha)
            else:
                stepsize = stepsize_bar

        return _return_samples(return_type, samples)
Esempio n. 6
0
    def sample(self,
               initial_pos,
               num_samples,
               stepsize=None,
               return_type="dataframe"):
        """
        Method to return samples using No U Turn Sampler

        Parameters
        ----------
        initial_pos: A 1d array like object
            Vector representing values of parameter position, the starting
            state in markov chain.

        num_samples: int
            Number of samples to be generated

        stepsize: float , defaults to None
            The stepsize for proposing new values of position and momentum in simulate_dynamics
            If None, then will be choosen suitably

        return_type: string (dataframe | recarray)
            Return type for samples, either of 'dataframe' or 'recarray'.
            Defaults to 'dataframe'

        Returns
        -------
        sampled: A pandas.DataFrame or a numpy.recarray object depending upon return_type argument


        Examples
        ---------
        >>> from ProbabilityModel.sampling import NoUTurnSampler as NUTS, GradLogPDFGaussian, LeapFrog
        >>> from ProbabilityModel.factors.continuous import GaussianDistribution as JGD
        >>> import numpy as np
        >>> mean = np.array([0, 0, 0])
        >>> covariance = np.array([[6, 0.7, 0.2], [0.7, 3, 0.9], [0.2, 0.9, 1]])
        >>> model = JGD(['x', 'y', 'z'], mean, covariance)
        >>> sampler = NUTS(model=model, grad_log_pdf=GradLogPDFGaussian, simulate_dynamics=LeapFrog)
        >>> samples = sampler.sample(initial_pos=np.array([1, 1, 1]), num_samples=10,
        ...                          stepsize=0.4, return_type='dataframe')
        >>> samples
                  x         y         z
        0  1.000000  1.000000  1.000000
        1  1.760756  0.271543 -0.613309
        2  1.883387  0.990745 -0.611720
        3  0.980812  0.340336 -0.916283
        4  0.781338  0.647220 -0.948640
        5  0.040308 -1.391406  0.412201
        6  1.179549 -1.450552  1.105216
        7  1.100320 -1.313926  1.207815
        8  1.484520 -1.349247  0.768599
        9  0.934942 -1.894589  0.471772
        """
        initial_pos = _check_1d_array_object(initial_pos, "initial_pos")
        _check_length_equal(initial_pos, self.model.variables, "initial_pos",
                            "model.variables")

        if stepsize is None:
            stepsize = self._find_reasonable_stepsize(initial_pos)

        types = [(var_name, "float") for var_name in self.model.variables]
        samples = np.zeros(num_samples, dtype=types).view(np.recarray)

        samples[0] = tuple(initial_pos)
        position_m = initial_pos

        for i in tqdm(range(1, num_samples)):
            # Genrating sample
            position_m = self._sample(position_m, stepsize)
            samples[i] = tuple(position_m)

        return _return_samples(return_type, samples)
Esempio n. 7
0
    def generate_sample(self,
                        initial_pos,
                        num_adapt,
                        num_samples,
                        trajectory_length,
                        stepsize=None):
        """
        Method returns a generator type object whose each iteration yields a sample
        using Hamiltonian Monte Carlo

        Parameters
        ----------
        initial_pos: A 1d array like object
            Vector representing values of parameter position, the starting
            state in markov chain.

        num_adapt: int
            The number of iterations to run the adaptation of stepsize

        num_samples: int
            Number of samples to be generated

        trajectory_length: int or float
            Target trajectory length, stepsize * number of steps(L),
            where L is the number of steps taken to propose new values of position and momentum
            per HMC iteration and stepsize is step size.

        stepsize: float , defaults to None
            The stepsize for proposing new values of position and momentum in simulate_dynamics
            If None, then will be chosen suitably

        Returns
        -------
        genrator: yielding a numpy.array type object for a sample

        Examples
        --------
        >>> from ProbabilityModel.sampling import HamiltonianMCDA as HMCda, GradLogPDFGaussian as GLPG, LeapFrog
        >>> from ProbabilityModel.factors.continuous import GaussianDistribution as JGD
        >>> import numpy as np
        >>> mean = np.array([1, 1])
        >>> covariance = np.array([[1, 0.7], [0.7, 3]])
        >>> model = JGD(['x', 'y'], mean, covariance)
        >>> sampler = HMCda(model=model, grad_log_pdf=GLPG, simulate_dynamics=LeapFrog)
        >>> gen_samples = sampler.generate_sample(np.array([1, 1]), num_adapt=10000,
        ...                                       num_samples = 10000, trajectory_length=2, stepsize=None)
        >>> samples_array = np.array([sample for sample in gen_samples])
        >>> np.cov(samples_array.T)
        array([[ 0.98432155,  0.69517394],
               [ 0.69517394,  2.95449533]])
        """
        self.accepted_proposals = 0
        initial_pos = _check_1d_array_object(initial_pos, "initial_pos")
        _check_length_equal(initial_pos, self.model.variables, "initial_pos",
                            "model.variables")

        if stepsize is None:
            stepsize = self._find_reasonable_stepsize(initial_pos)

        if num_adapt <= 1:  # return sample generated using Simple HMC algorithm
            for sample in HamiltonianMC.generate_sample(
                    self, initial_pos, num_samples, trajectory_length,
                    stepsize):
                yield sample
            return
        mu = np.log(10.0 * stepsize)

        stepsize_bar = 1.0
        h_bar = 0.0

        position_m = initial_pos.copy()
        num_adapt += 1

        for i in range(1, num_samples + 1):

            position_m, alpha = self._sample(position_m, trajectory_length,
                                             stepsize)

            if i <= num_adapt:
                stepsize, stepsize_bar, h_bar = self._adapt_params(
                    stepsize, stepsize_bar, h_bar, mu, i, alpha)
            else:
                stepsize = stepsize_bar

            yield position_m

        self.acceptance_rate = self.accepted_proposals / num_samples
Esempio n. 8
0
    def sample(
        self,
        initial_pos,
        num_adapt,
        num_samples,
        trajectory_length,
        stepsize=None,
        return_type="dataframe",
    ):
        """
        Method to return samples using Hamiltonian Monte Carlo

        Parameters
        ----------
        initial_pos: A 1d array like object
            Vector representing values of parameter position, the starting
            state in markov chain.

        num_adapt: int
            The number of iterations to run the adaptation of stepsize

        num_samples: int
            Number of samples to be generated

        trajectory_length: int or float
            Target trajectory length, stepsize * number of steps(L),
            where L is the number of steps taken per HMC iteration,
            and stepsize is step size for splitting time method.

        stepsize: float , defaults to None
            The stepsize for proposing new values of position and momentum in simulate_dynamics
            If None, then will be chosen suitably

        return_type: string (dataframe | recarray)
            Return type for samples, either of 'dataframe' or 'recarray'.
            Defaults to 'dataframe'

        Returns
        -------
        sampled: A pandas.DataFrame or a numpy.recarray object depending upon return_type argument

        Examples
        ---------
        >>> from ProbabilityModel.sampling import HamiltonianMCDA as HMCda, GradLogPDFGaussian as GLPG, LeapFrog
        >>> from ProbabilityModel.factors.continuous import GaussianDistribution as JGD
        >>> import numpy as np
        >>> mean = np.array([1, 1])
        >>> covariance = np.array([[1, 0.7], [0.7, 3]])
        >>> model = JGD(['x', 'y'], mean, covariance)
        >>> sampler = HMCda(model=model, grad_log_pdf=GLPG, simulate_dynamics=LeapFrog)
        >>> samples = sampler.sample(np.array([1, 1]), num_adapt=10000, num_samples = 10000,
        ...                          trajectory_length=2, stepsize=None, return_type='recarray')
        >>> samples_array = np.array([samples[var_name] for var_name in model.variables])
        >>> np.cov(samples_array)
        array([[ 0.98432155,  0.66517394],
               [ 0.66517394,  2.95449533]])

        """

        self.accepted_proposals = 1.0

        initial_pos = _check_1d_array_object(initial_pos, "initial_pos")
        _check_length_equal(initial_pos, self.model.variables, "initial_pos",
                            "model.variables")

        if stepsize is None:
            stepsize = self._find_reasonable_stepsize(initial_pos)

        if num_adapt <= 1:  # Return samples genrated using Simple HMC algorithm
            return HamiltonianMC.sample(self, initial_pos, num_samples,
                                        trajectory_length, stepsize)

        # stepsize is epsilon
        # freely chosen point, after each iteration xt(/position) is shrunk towards it
        mu = np.log(10.0 * stepsize)
        # log(10 * stepsize) large values to save computation
        # stepsize_bar is epsilon_bar
        stepsize_bar = 1.0
        h_bar = 0.0
        # See equation (6) section 3.2.1 for details

        types = [(var_name, "float") for var_name in self.model.variables]
        samples = np.zeros(num_samples, dtype=types).view(np.recarray)
        samples[0] = tuple(initial_pos)
        position_m = initial_pos

        for i in tqdm(range(1, num_samples)):

            # Genrating sample
            position_m, alpha = self._sample(position_m, trajectory_length,
                                             stepsize)
            samples[i] = tuple(position_m)

            # Adaptation of stepsize till num_adapt iterations
            if i <= num_adapt:
                stepsize, stepsize_bar, h_bar = self._adapt_params(
                    stepsize, stepsize_bar, h_bar, mu, i, alpha)
            else:
                stepsize = stepsize_bar

        self.acceptance_rate = self.accepted_proposals / num_samples

        return _return_samples(return_type, samples)
Esempio n. 9
0
    def generate_sample(self,
                        initial_pos,
                        num_samples,
                        trajectory_length,
                        stepsize=None):
        """
        Method returns a generator type object whose each iteration yields a sample
        using Hamiltonian Monte Carlo

        Parameters
        ----------
        initial_pos: A 1d array like object
            Vector representing values of parameter position, the starting
            state in markov chain.

        num_samples: int
            Number of samples to be generated

        trajectory_length: int or float
            Target trajectory length, stepsize * number of steps(L),
            where L is the number of steps taken per HMC iteration,
            and stepsize is step size for splitting time method.

        stepsize: float , defaults to None
            The stepsize for proposing new values of position and momentum in simulate_dynamics
            If None, then will be chosen suitably

        Returns
        -------
        genrator: yielding a 1d numpy.array type object for a sample

        Examples
        --------
        >>> from ProbabilityModel.sampling import HamiltonianMC as HMC, GradLogPDFGaussian as GLPG
        >>> from ProbabilityModel.factors import GaussianDistribution as JGD
        >>> import numpy as np
        >>> mean = np.array([4, -1])
        >>> covariance = np.array([[3, 0.4], [0.4, 3]])
        >>> model = JGD(['x', 'y'], mean, covariance)
        >>> sampler = HMC(model=model, grad_log_pdf=GLPG)
        >>> gen_samples = sampler.generate_sample(np.array([-1, 1]), num_samples = 10000,
        ...                                       trajectory_length=2, stepsize=0.25)
        >>> samples_array = np.array([sample for sample in gen_samples])
        >>> samples_array
        array([[ 0.1467264 ,  0.27143857],
               [ 4.0371448 ,  0.15871274],
               [ 3.24656208, -1.03742621],
               ...,
               [ 6.45975905,  1.97941306],
               [ 4.89007171,  0.15413156],
               [ 5.9528083 ,  1.92983158]])
        >>> np.cov(samples_array.T)
        array([[ 2.95692642,  0.4379419 ],
               [ 0.4379419 ,  3.00939434]])
        >>> sampler.acceptance_rate
        0.9969
        """

        self.accepted_proposals = 0
        initial_pos = _check_1d_array_object(initial_pos, "initial_pos")
        _check_length_equal(initial_pos, self.model.variables, "initial_pos",
                            "model.variables")

        if stepsize is None:
            stepsize = self._find_reasonable_stepsize(initial_pos)

        lsteps = int(max(1, round(trajectory_length / stepsize, 0)))
        position_m = initial_pos.copy()

        for i in range(0, num_samples):

            position_m, _ = self._sample(position_m, trajectory_length,
                                         stepsize, lsteps)

            yield position_m

        self.acceptance_rate = self.accepted_proposals / num_samples
Esempio n. 10
0
    def sample(
        self,
        initial_pos,
        num_samples,
        trajectory_length,
        stepsize=None,
        return_type="dataframe",
    ):
        """
        Method to return samples using Hamiltonian Monte Carlo

        Parameters
        ----------
        initial_pos: A 1d array like object
            Vector representing values of parameter position, the starting
            state in markov chain.

        num_samples: int
            Number of samples to be generated

        trajectory_length: int or float
            Target trajectory length, stepsize * number of steps(L),
            where L is the number of steps taken per HMC iteration,
            and stepsize is step size for splitting time method.

        stepsize: float , defaults to None
            The stepsize for proposing new values of position and momentum in simulate_dynamics
            If None, then will be chosen suitably

        return_type: string (dataframe | recarray)
            Return type for samples, either of 'dataframe' or 'recarray'.
            Defaults to 'dataframe'

        Returns
        -------
        sampled: A pandas.DataFrame or a numpy.recarray object depending upon return_type argument

        Examples
        --------
        >>> from ProbabilityModel.sampling import HamiltonianMC as HMC, GradLogPDFGaussian, ModifiedEuler
        >>> from ProbabilityModel.factors.continuous import GaussianDistribution as JGD
        >>> import numpy as np
        >>> mean = np.array([1, -1])
        >>> covariance = np.array([[1, 0.2], [0.2, 1]])
        >>> model = JGD(['x', 'y'], mean, covariance)
        >>> sampler = HMC(model=model, grad_log_pdf=GradLogPDFGaussian, simulate_dynamics=ModifiedEuler)
        >>> samples = sampler.sample(np.array([1, 1]), num_samples = 5,
        ...                          trajectory_length=6, stepsize=0.25, return_type='dataframe')
        >>> samples
                       x              y
        0   1.000000e+00   1.000000e+00
        1   1.592133e+00   1.152911e+00
        2   1.608700e+00   1.315349e+00
        3   1.608700e+00   1.315349e+00
        4   6.843856e-01   6.237043e-01
        >>> mean = np.array([4, 1, -1])
        >>> covariance = np.array([[1, 0.7 , 0.8], [0.7, 1, 0.2], [0.8, 0.2, 1]])
        >>> model = JGD(['x', 'y', 'z'], mean, covariance)
        >>> sampler = HMC(model=model, grad_log_pdf=GLPG)
        >>> samples = sampler.sample(np.array([1, 1]), num_samples = 10000,
        ...                          trajectory_length=6, stepsize=0.25, return_type='dataframe')
        >>> np.cov(samples.values.T)
        array([[ 1.00795398,  0.71384233,  0.79802097],
               [ 0.71384233,  1.00633524,  0.21313767],
               [ 0.79802097,  0.21313767,  0.98519017]])
        """

        self.accepted_proposals = 1.0
        initial_pos = _check_1d_array_object(initial_pos, "initial_pos")
        _check_length_equal(initial_pos, self.model.variables, "initial_pos",
                            "model.variables")

        if stepsize is None:
            stepsize = self._find_reasonable_stepsize(initial_pos)

        types = [(var_name, "float") for var_name in self.model.variables]
        samples = np.zeros(num_samples, dtype=types).view(np.recarray)

        # Assigning after converting into tuple because value was being changed after assignment
        # Reason for this is unknown
        samples[0] = tuple(initial_pos)
        position_m = initial_pos

        lsteps = int(max(1, round(trajectory_length / stepsize, 0)))
        for i in tqdm(range(1, num_samples)):

            # Genrating sample
            position_m, _ = self._sample(position_m, trajectory_length,
                                         stepsize, lsteps)
            samples[i] = tuple(position_m)

        self.acceptance_rate = self.accepted_proposals / num_samples

        return _return_samples(return_type, samples)