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
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
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
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
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)
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)
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
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)
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
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)