def _object_func(params, data, model_func, sel_dist, theta, lower_bound=None, upper_bound=None, verbose=0, multinom=False, flush_delay=0, func_args=[], func_kwargs={}, fixed_params=None, ll_scale=1, output_stream=sys.stdout, store_thetas=False): """ Objective function for optimization. """ global _counter _counter += 1 # Deal with fixed parameters params_up = Inference._project_params_up(params, fixed_params) # Check our parameter bounds if lower_bound is not None: for pval, bound in zip(params_up, lower_bound): if bound is not None and pval < bound: return -_out_of_bounds_val / ll_scale if upper_bound is not None: for pval, bound in zip(params_up, upper_bound): if bound is not None and pval > bound: return -_out_of_bounds_val / ll_scale ns = data.sample_sizes all_args = [params_up, ns, sel_dist, theta] + list(func_args) sfs = model_func(*all_args, **func_kwargs) if multinom: result = Inference.ll_multinom(sfs, data) else: result = Inference.ll(sfs, data) if store_thetas: global _theta_store _theta_store[tuple(params)] = optimal_sfs_scaling(sfs, data) # Bad result if numpy.isnan(result): result = _out_of_bounds_val if (verbose > 0) and (_counter % verbose == 0): param_str = 'array([%s])' % (', '.join( ['%- 12g' % v for v in params_up])) output_stream.write('%-8i, %-12g, %s%s' % (_counter, result, param_str, os.linesep)) Misc.delayed_flush(delay=flush_delay) return -result / ll_scale
def optimize(p0, data1, data2, cache1, cache2, model_func, sel_dist, scal_fac1, scal_fac2, theta1, theta2, lower_bound=None, upper_bound=None, verbose=0, flush_delay=0.5, epsilon=1e-3, gtol=1e-5, multinom=False, maxiter=None, full_output=False, func_args=[], func_kwargs={}, fixed_params=None, ll_scale=1, output_file=None): if output_file: output_stream = file(output_file, 'w') else: output_stream = sys.stdout args = (data1, data2, cache1, cache2, model_func, sel_dist, scal_fac1, scal_fac2, theta1, theta2, lower_bound, upper_bound, verbose, multinom, flush_delay, func_args, func_kwargs, fixed_params, ll_scale, output_stream) p0 = Inference._project_params_down(p0, fixed_params) outputs = scipy.optimize.fmin_bfgs(_object_func, p0, epsilon=epsilon, args=args, gtol=gtol, full_output=True, disp=False, maxiter=maxiter) xopt, fopt, gopt, Bopt, func_calls, grad_calls, warnflag = outputs xopt = Inference._project_params_up(xopt, fixed_params) if output_file: output_stream.close() if not full_output: return [-fopt, xopt] else: return xopt, fopt, gopt, Bopt, func_calls, grad_calls, warnflag
def optimize(p0, data, model_func, sel_dist, theta, lower_bound=None, upper_bound=None, verbose=0, flush_delay=0.5, epsilon=1e-3, gtol=1e-5, multinom=False, maxiter=None, full_output=False, func_args=[], func_kwargs={}, fixed_params=None, ll_scale=1, output_file=None): """ optimizer for use with distributions where log transformations do not work, e.g. when gamma is positive and negative """ if output_file: output_stream = file(output_file, 'w') else: output_stream = sys.stdout args = (data, model_func, sel_dist, theta, lower_bound, upper_bound, verbose, multinom, flush_delay, func_args, func_kwargs, fixed_params, ll_scale, output_stream) p0 = _project_params_down(p0, fixed_params) outputs = scipy.optimize.fmin_bfgs(_object_func, p0, epsilon=epsilon, args=args, gtol=gtol, full_output=True, disp=False, maxiter=maxiter) xopt, fopt, gopt, Bopt, func_calls, grad_calls, warnflag = outputs xopt = Inference._project_params_up(xopt, fixed_params) if output_file: output_stream.close() if not full_output: return xopt else: return xopt, fopt, gopt, Bopt, func_calls, grad_calls, warnflag
def optimize_cons(p0, data, model_func, sel_dist, theta, lower_bound=None, upper_bound=None, verbose=0, flush_delay=0.5, epsilon=1e-4, constraint=None, gtol=1e-6, multinom=False, maxiter=None, full_output=False, func_args=[], func_kwargs={}, fixed_params=None, ll_scale=1, output_file=None): """ Constrained optimization needs a constraint function and bounds. """ if output_file: output_stream = file(output_file, 'w') else: output_stream = sys.stdout if not (lower_bound is None): lower_bound_a = lower_bound + [0] if not (upper_bound is None): upper_bound_a = upper_bound + [numpy.inf] args = (data, model_func, sel_dist, theta, lower_bound, upper_bound, verbose, multinom, flush_delay, func_args, func_kwargs, fixed_params, ll_scale, output_stream) p0 = Inference._project_params_down(p0, fixed_params) ####make sure to define consfunc and bnds #### if (not lower_bound is None) and (not upper_bound is None): bnds = tuple((x, y) for x, y in zip(lower_bound, upper_bound)) outputs = scipy.optimize.fmin_slsqp(_object_func, p0, bounds=bnds, args=args, f_eqcons=constraint, epsilon=epsilon, iter=maxiter, full_output=True, disp=False) xopt, fopt, func_calls, grad_calls, warnflag = outputs xopt = Inference._project_params_up(xopt, fixed_params) if output_file: output_stream.close() if not full_output: return [-fopt, xopt] else: return xopt, fopt, func_calls, grad_calls, warnflag
def _object_func(params, data1, data2, cache1, cache2, model_func, sel_dist, scal_fac1, scal_fac2, theta1, theta2, lower_bound=None, upper_bound=None, verbose=0, multinom=False, flush_delay=0, func_args=[], func_kwargs={}, fixed_params1=None, fixed_params2=None, ll_scale=1, output_stream=sys.stdout, store_thetas=False): """ Objective function for optimization. """ global _counter _counter += 1 # Scaling factors scales sel_dist differently for species 1 and species 2 sel_dist1 = copy_func( sel_dist, defaults=scal_fac1) # scal_fac1 should be 2*Nea of pop 1 sel_dist2 = copy_func( sel_dist, defaults=scal_fac2) # scal_fac2 should be 4*Nea of pop 2 # Deal with fixed parameters params_up1 = Inference._project_params_up(params, fixed_params1) params_up2 = Inference._project_params_up(params, fixed_params2) # Check our parameter bounds if lower_bound is not None: for pval, bound in zip(params_up1, lower_bound): if bound is not None and pval < bound: return -_out_of_bounds_val / ll_scale if upper_bound is not None: for pval, bound in zip(params_up1, upper_bound): if bound is not None and pval > bound: return -_out_of_bounds_val / ll_scale ns1 = data1.sample_sizes ns2 = data2.sample_sizes all_args1 = [params_up1, ns1, sel_dist1, theta1, cache1] + list(func_args) all_args2 = [params_up2, ns2, sel_dist2, theta2, cache2] + list(func_args) # Pass the pts argument via keyword, but don't alter the passed-in # func_kwargs #func_kwargs = func_kwargs.copy() #func_kwargs['pts'] = pts sfs1 = model_func(*all_args1, **func_kwargs) sfs2 = model_func(*all_args2, **func_kwargs) if multinom: result = Inference.ll_multinom(sfs1, data1) + Inference.ll_multinom( sfs2, data2) else: result = Inference.ll(sfs1, data1) + Inference.ll(sfs2, data2) # Bad result if numpy.isnan(result): result = _out_of_bounds_val if (verbose > 0) and (_counter % verbose == 0): param_str = 'array([%s])' % (', '.join( ['%- 12g' % v for v in params_up1])) output_stream.write('%-8i, %-12g, %s%s' % (_counter, result, param_str, os.linesep)) Misc.delayed_flush(delay=flush_delay) return -result / ll_scale