if not oracle: Q2, r2 = invert_normal_params(S2, m2, out_A='in-place', out_b='in-place') r2s[:, i] = r2 Q2s[:, :, i] = Q2 # Get samples samp = N1.rvs(n) mt = np.mean(samp, axis=0) samp -= mt St = np.dot(samp.T, samp).T # olse olse(St / n, n, P=Q1 if oracle else Q2, out=Q_hats[:, :, i]) r_hats[:, i] = Q_hats[:, :, i].dot(mt) # Basic sample estimates St /= n - 1 invert_normal_params(St, mt, out_A=Q_samps[:, :, i], out_b=r_samps[:, i]) # Unbiased natural parameter estimates unbias_k = (n - d - 2) / (n - 1) Q_samps[:, :, i] *= unbias_k r_samps[:, i] *= unbias_k # Print result statistics print 'Statistics of {} estimates'.format(N) print('{:9}' + 4 * ' {:>13}').format('estimate', 'me (bias)', 'std', 'mse', '97.5se') print 65 * '-'
def tilted(self, dQi, dri, save_fit=False): """Estimate the tilted distribution parameters. This method estimates the tilted distribution parameters and calculates the resulting site parameter updates into the given arrays. The cavity distribution has to be calculated before this method is called, i.e. the method cavity has to be run before this. After calling this method the instance variables self.Mat and self.vec hold the tilted distribution moment parameters (note however that the covariance matrix is unnormalised and the number of samples contributing to this matrix is stored in the instance variable self.nsamp). Parameters ---------- dQi, dri : ndarray Output arrays where the site parameter updates are placed. save_fit : bool, optional If True, the Stan fit-object is saved into the instance variable `fit` for later use. Default is False. Returns ------- pos_def True if the estimated tilted distribution covariance matrix is positive definite. False otherwise. """ if self.phase != 1: raise RuntimeError('Cavity has to be calculated before tilted.') # FIXME: Temp fix for RandomState problem in 32-bit Python if self.fix32bit: self.stan_params['seed'] = self.rstate.randint(2**31 - 1) # Sample from the model with suppress_stdout(): time_start = timer() fit = self.stan_model.sampling(data=self.data, **self.stan_params) time_end = timer() self.last_time = (time_end - time_start) if self.verbose: # Mean stepsize steps = [ np.mean(p['stepsize__']) for p in fit.get_sampler_params() ] print '\n mean stepsize: {:.4}'.format(np.mean(steps)) # Max Rhat (from all but last row in the last column) print ' max Rhat: {:.4}'.format( np.max(fit.summary()['summary'][:-1, -1])) if self.init_prev: # Store the last sample of each chain if isinstance(self.stan_params['init'], basestring): # No samples stored before ... initialise list of dicts self.stan_params['init'] = get_last_fit_sample(fit) else: get_last_fit_sample(fit, out=self.stan_params['init']) # Extract samples # TODO: preallocate space for samples samp = copy_fit_samples(fit, self.fit_pnames) self.nsamp = samp.shape[0] if save_fit: # Save fit self.fit = fit else: # Dereference fit here so that it can be garbage collected fit = None # Estimate precision matrix try: # Basic sample estimate if self.prec_estim == 'sample' or self.prec_estim_skip > 0: # Mean mt = np.mean(samp, axis=0, out=self.vec) # Center samples samp -= mt # Use QR-decomposition for obtaining Cholesky of the scatter # matrix (only R needed, Q-less algorithm would be nice) _, _, _, info = dgeqrf_routine(samp, overwrite_a=True) if info: raise linalg.LinAlgError( "dgeqrf LAPACK routine failed with error code {}". format(info)) # Copy the relevant part of the array into contiguous memory np.copyto(self.Mat, samp[:self.dphi, :]) invert_normal_params(self.Mat, mt, out_A=dQi, out_b=dri, cho_form=True) # Unbiased (for normal distr.) natural parameter estimates unbias_k = (self.nsamp - self.dphi - 2) dQi *= unbias_k dri *= unbias_k if self.prec_estim_skip > 0: self.prec_estim_skip -= 1 # Optimal linear shrinkage estimate elif self.prec_estim == 'olse': # Mean mt = np.mean(samp, axis=0, out=self.vec) # Center samples samp -= mt # Sample covariance np.dot(samp.T, samp, out=self.Mat.T) # Normalise self.Mat into dQi np.divide(self.Mat, self.nsamp, out=dQi) # Estimate olse(dQi, self.nsamp, P=self.Q, out='in-place') np.dot(dQi, mt, out=dri) # Graphical lasso with cross validation elif self.prec_estim == 'glassocv': # Mean mt = np.mean(samp, axis=0, out=self.vec) # Center samples samp -= mt # Fit self.glassocv.fit(samp) if self.verbose: print ' glasso alpha: {:.4}'.format( self.glassocv.alpha_) np.copyto(dQi, self.glassocv.precision_.T) # Calculate corresponding r np.dot(dQi, mt, out=dri) else: raise ValueError("Invalid value for option `prec_estim`") # Calculate the difference into the output arrays np.subtract(dQi, self.Q, out=dQi) np.subtract(dri, self.r, out=dri) except linalg.LinAlgError: # Precision estimate failed pos_def = False self.phase = 0 dQi.fill(0) dri.fill(0) if self.init_prev: # Reset initialisation method self.init = self.init_orig else: # Set return and phase flag pos_def = True self.phase = 2 self.iteration += 1 return pos_def
Q1, r1 = invert_normal_params(S1, m1) r1s[:, i] = r1 Q1s[:, :, i] = Q1 if not oracle: Q2, r2 = invert_normal_params(S2, m2, out_A="in_place", out_b="in_place") r2s[:, i] = r2 Q2s[:, :, i] = Q2 # Get samples samp = N1.rvs(n) mt = np.mean(samp, axis=0) samp -= mt St = np.dot(samp.T, samp).T # olse olse(St / n, n, P=Q1 if oracle else Q2, out=Q_hats[:, :, i]) r_hats[:, i] = Q_hats[:, :, i].dot(mt) # Basic sample estimates St /= n - 1 invert_normal_params(St, mt, out_A=Q_samps[:, :, i], out_b=r_samps[:, i]) # Unbiased natural parameter estimates unbias_k = (n - d - 2) / (n - 1) Q_samps[:, :, i] *= unbias_k r_samps[:, i] *= unbias_k # Print result statistics print "Statistics of {} estimates".format(N) print ("{:9}" + 4 * " {:>13}").format("estimate", "me (bias)", "std", "mse", "97.5se") print 65 * "-" for i in xrange(min(d, print_max)):
def tilted(self, dQi, dri): """Estimate the tilted distribution parameters. This method estimates the tilted distribution parameters and calculates the resulting site parameter updates into the given arrays. The cavity distribution has to be calculated before this method is called, i.e. the method cavity has to be run before this. After calling this method the instance variables self.Mat and self.vec hold the tilted distribution moment parameters (note however that the covariance matrix is unnormalised and the number of samples contributing to this matrix is stored in the instance variable self.nsamp). Parameters ---------- dQi, dri : ndarray Output arrays where the site parameter updates are placed. Returns ------- pos_def True if the estimated tilted distribution covariance matrix is positive definite. False otherwise. """ if self.phase != 1: raise RuntimeError('Cavity has to be calculated before tilted.') # FIXME: Temp fix for RandomState problem in 32-bit Python if self.fix32bit: self.stan_params['seed'] = self.rstate.randint(2**31 - 1) # Sample from the model try: with suppress_stdout(): fit = self.stan_model.sampling(data=self.data, pars=('phi'), **self.stan_params) except ValueError: print 'Worker {} failed'.format(self.index) with open('stan_params.pkl', 'wb') as f: pickle.dump(self.stan_params, f) with open('data.pkl', 'wb') as f: pickle.dump(self.data, f) raise ValueError('Jaahast') if self.init_prev: # Store the last sample of each chain if isinstance(self.stan_params['init'], basestring): # No samples stored before ... initialise list of dicts self.stan_params['init'] = get_last_sample(fit) else: get_last_sample(fit, out=self.stan_params['init']) # TODO: Make a non-copying extract samp = fit.extract(pars='phi')['phi'] self.nsamp = samp.shape[0] # Assign arrays St = self.Mat mt = self.vec # Sample mean and covariance np.mean(samp, axis=0, out=mt) samp -= mt np.dot(samp.T, samp, out=St.T) if not self.smooth is None: # Smoothen the distribution (use dri and dQi as temp arrays) St, mt = self._apply_smooth(dri, dQi) # Estimate precision matrix try: # Basic sample estimate if self.prec_estim == 'sample' or self.prec_estim_skip > 0: # Normalise St unbiased into dQi np.divide(St, self.nsamp - 1, out=dQi) # Convert moment params to natural params invert_normal_params(dQi, mt, out_A='in_place', out_b=dri) # Unbiased natural parameter estimates unbias_k = (self.nsamp - self.dphi - 2) / (self.nsamp - 1) dQi *= unbias_k dri *= unbias_k # Optimal linear shrinkage estimate elif self.prec_estim == 'olse': # Normalise St into dQi np.divide(St, self.nsamp, out=dQi) # Estimate olse(dQi, self.nsamp, P=self.Q, out='in_place') np.dot(dQi, mt, out=dri) else: raise ValueError("Invalid value for option `prec_estim`") # Calculate the difference into the output arrays np.subtract(dQi, self.Q, out=dQi) np.subtract(dri, self.r, out=dri) except linalg.LinAlgError: # Precision estimate failed pos_def = False self.phase = 0 dQi.fill(0) dri.fill(0) if not self.smooth is None: # Reset tilted memory self.prev_stored = 0 if self.init_prev: # Reset initialisation method self.init = self.init_orig else: # Set return and phase flag pos_def = True self.phase = 2 self.iteration += 1 return pos_def