def test_bayesian_importance_sampling_avar(self): np.random.seed(1) nrandom_vars = 2 Amat = np.array([[-0.5, 1]]) noise_std = 0.1 prior_variable = IndependentMultivariateRandomVariable( [stats.norm(0, 1)] * nrandom_vars) prior_mean = prior_variable.get_statistics('mean') prior_cov = np.diag(prior_variable.get_statistics('var')[:, 0]) prior_cov_inv = np.linalg.inv(prior_cov) noise_cov_inv = np.eye(Amat.shape[0]) / noise_std**2 true_sample = np.array([.4] * nrandom_vars)[:, None] collected_obs = Amat.dot(true_sample) collected_obs += np.random.normal(0, noise_std, (collected_obs.shape)) exact_post_mean, exact_post_cov = \ laplace_posterior_approximation_for_linear_models( Amat, prior_mean, prior_cov_inv, noise_cov_inv, collected_obs) chol_factor = np.linalg.cholesky(exact_post_cov) chol_factor_inv = np.linalg.inv(chol_factor) def g_model(samples): return np.exp( np.sum(chol_factor_inv.dot(samples - exact_post_mean), axis=0))[:, None] nsamples = int(1e6) prior_samples = generate_independent_random_samples( prior_variable, nsamples) posterior_samples = chol_factor.dot( np.random.normal(0, 1, (nrandom_vars, nsamples))) + exact_post_mean g_mu, g_sigma = 0, np.sqrt(nrandom_vars) f, f_cdf, f_pdf, VaR, CVaR, ssd, ssd_disutil = \ get_lognormal_example_exact_quantities(g_mu, g_sigma) beta = .1 cvar_exact = CVaR(beta) cvar_mc = conditional_value_at_risk(g_model(posterior_samples), beta) prior_pdf = prior_variable.pdf post_pdf = stats.multivariate_normal(mean=exact_post_mean[:, 0], cov=exact_post_cov).pdf weights = post_pdf(prior_samples.T) / prior_pdf(prior_samples)[:, 0] weights /= weights.sum() cvar_im = conditional_value_at_risk(g_model(prior_samples), beta, weights) # print(cvar_exact, cvar_mc, cvar_im) assert np.allclose(cvar_exact, cvar_mc, rtol=1e-3) assert np.allclose(cvar_exact, cvar_im, rtol=2e-3)
def solve_quantile_regression(tau, samples, values, eval_basis_matrix, normalize_vals=False, opts={}): basis_matrix = eval_basis_matrix(samples) if basis_matrix.shape[0] < basis_matrix.shape[1]: raise ValueError("System is under-determined") if normalize_vals is True: factor = values[:, 0].std() vals = values.copy() / factor else: vals = values quantile_coef = quantile_regression(basis_matrix, vals.squeeze(), tau=tau, opts=opts) if normalize_vals is True: quantile_coef *= factor # assume first coefficient is for constant term quantile_coef[0] = 0 centered_approx_vals = basis_matrix.dot(quantile_coef)[:, 0] deviation = conditional_value_at_risk(values[:, 0] - centered_approx_vals, tau) quantile_coef[0] = deviation return quantile_coef
def oed_conditional_value_at_risk_deviation(beta, samples, weights, samples_sorted=True): cvars = np.empty(samples.shape[0]) for ii in range(samples.shape[0]): mean = np.sum(samples[ii, :] * weights[ii, :]) cvars[ii] = conditional_value_at_risk( samples[ii, :], beta, weights[ii, :], samples_sorted) - mean return cvars[:, None]
def test_triangle_superquantile(self): c = 0.5 loc = -0.5 scale = 2 u = np.asarray([0.3, 0.75]) cvar = triangle_superquantile(u, c, loc, scale) samples = triangle_quantile(np.random.uniform(0, 1, (100000)), c, loc, scale) for ii in range(len(u)): mc_cvar = conditional_value_at_risk(samples, u[ii]) assert abs(cvar[ii] - mc_cvar) < 1e-2
def solve_quantile_regression(tau, samples, values, eval_basis_matrix): basis_matrix = eval_basis_matrix(samples) quantile_coef = quantile_regression(basis_matrix, values.squeeze(), tau=tau) # assume first coefficient is for constant term quantile_coef[0] = 0 centered_approx_vals = basis_matrix.dot(quantile_coef)[:, 0] deviation = conditional_value_at_risk(values[:, 0] - centered_approx_vals, tau) quantile_coef[0] = deviation return quantile_coef
def test_conditional_value_at_risk(self): N = 6 p = np.ones(N) / N X = np.random.normal(0, 1, N) # X = np.arange(1,N+1) X = np.sort(X) beta = 7 / 12 i_beta_exact = 3 VaR_exact = X[i_beta_exact] cvar_exact = 1 / 5 * VaR_exact + 2 / 5 * (np.sort(X)[i_beta_exact + 1:]).sum() ecvar, evar = conditional_value_at_risk(X, beta, return_var=True) # print(cvar_exact,ecvar) assert np.allclose(cvar_exact, ecvar)
def test_weighted_value_at_risk_normal(self): mu, sigma = 1, 1 # bias_mu,bias_sigma=1.0,1 bias_mu, bias_sigma = mu, sigma from scipy.special import erf def VaR(alpha): return stats.norm.ppf(alpha, loc=mu, scale=sigma) def CVaR(alpha): vals = 0.5 * mu vals -= 0.5*mu*erf((VaR(alpha)-mu)/(np.sqrt(2)*sigma)) -\ sigma*np.exp(-(mu-VaR(alpha))**2/(2*sigma**2))/np.sqrt(2*np.pi) vals /= (1 - alpha) return vals alpha = 0.8 print(CVaR(alpha), cvar_gaussian_variable(stats.norm(loc=mu, scale=sigma), alpha)) assert np.allclose( CVaR(alpha), cvar_gaussian_variable(stats.norm(loc=mu, scale=sigma), alpha)) num_samples = int(1e5) samples = np.random.normal(bias_mu, bias_sigma, num_samples) target_pdf_vals = stats.norm.pdf(samples, loc=mu, scale=sigma) bias_pdf_vals = stats.norm.pdf(samples, loc=bias_mu, scale=bias_sigma) II = np.where(bias_pdf_vals < np.finfo(float).eps)[0] assert np.all(target_pdf_vals[II] < np.finfo(float).eps) J = np.where(bias_pdf_vals >= np.finfo(float).eps)[0] weights = np.zeros_like(target_pdf_vals) weights[J] = target_pdf_vals[J] / bias_pdf_vals[J] weights /= weights.sum() empirical_VaR, __ = value_at_risk(samples, alpha, weights, samples_sorted=False) # print('VaR',VaR(alpha),empirical_VaR) assert np.allclose(VaR(alpha), empirical_VaR, rtol=1e-2) empirical_CVaR = conditional_value_at_risk(samples, alpha, weights) # print('CVaR',CVaR(alpha),empirical_CVaR) assert np.allclose(CVaR(alpha), empirical_CVaR, rtol=1e-2)
def test_conditional_value_at_risk_using_opitmization_formula(self): """ Compare value obtained via optimization and analytical formula """ plot = False num_samples = 5 alpha = np.array([1. / 3., 0.5, 0.85]) samples = np.random.normal(0, 1, (num_samples)) for ii in range(alpha.shape[0]): ecvar, evar = conditional_value_at_risk(samples, alpha[ii], return_var=True) def objective(tt): return np.asarray([ t + 1 / (1 - alpha[ii]) * np.maximum(0, samples - t).mean() for t in tt ]) tol = 1e-8 method = 'L-BFGS-B' options = {'disp': False, 'gtol': tol, 'ftol': tol} init_guess = 0 result = minimize(objective, init_guess, method=method, options=options) value_at_risk = result['x'] cvar = result['fun'] print(alpha[ii], value_at_risk, cvar, ecvar) assert np.allclose(ecvar, cvar) assert np.allclose(evar, value_at_risk) if plot: rv = stats.norm lb, ub = rv.interval(.99) xx = np.linspace(lb, ub, 101) obj_vals = objective(xx) plt.plot(xx, obj_vals) plt.plot(value_at_risk, cvar, 'ro') plt.show()
def plot_lognormal_example_exact_quantities( num_samples=int(2e5), plot=False, mu=0, sigma=1): num_vars = 1 if plot: assert num_samples <= 1e5 else: assert num_samples >= 1e4 f, f_cdf, f_pdf, VaR, CVaR, ssd, ssd_disutil = \ get_lognormal_example_exact_quantities(mu, sigma) from pyapprox.low_discrepancy_sequences import transformed_halton_sequence # samples = np.random.normal(mu,sigma,(num_vars,num_samples)) # values = f(samples)[:,0] samples = transformed_halton_sequence( [partial(stats.norm.ppf, loc=mu, scale=sigma)], num_vars, num_samples) values = f(samples)[:, 0] if plot: import matplotlib.pyplot as plt fig, axs = plt.subplots(1, 6, sharey=False, figsize=(16, 6)) # from pyapprox.density import EmpiricalCDF ygrid = np.linspace(-1, 5, 100) # ecdf = EmpiricalCDF(values) # axs[0].plot(ygrid,ecdf(ygrid),'-') axs[0].plot(ygrid, f_cdf(ygrid), '--') # axs[0].set_xlim(ygrid.min(),ygrid.max()) axs[0].set_title('CDF') # ecdf = EmpiricalCDF(-values) # axs[0].plot(-ygrid,ecdf(-ygrid),'-') ygrid = np.linspace(-1, 20, 100) # axs[1].hist(values,bins='auto',density=True) axs[1].plot(ygrid, f_pdf(ygrid), '--') axs[1].set_xlim(ygrid.min(), ygrid.max()) axs[1].set_title('PDF') pgrid = np.linspace(1e-2, 1 - 1e-2, 100) evar = np.array([value_at_risk(values, p)[0] for p in pgrid]) # print(np.linalg.norm(evar.squeeze()-VaR(pgrid),ord=np.inf)) if plot: axs[2].plot(pgrid, evar, '-') axs[2].plot(pgrid, VaR(pgrid), '--') axs[2].set_title('VaR') else: assert np.allclose(evar.squeeze(), VaR(pgrid), atol=2e-1) pgrid = np.linspace(1e-2, 1 - 1e-2, 100) ecvar = np.array([conditional_value_at_risk(values, y) for y in pgrid]) # print(np.linalg.norm(ecvar.squeeze()-CVaR(pgrid).squeeze(),ord=np.inf)) print(CVaR(0.8)) if plot: axs[3].plot(pgrid, ecvar, '-') axs[3].plot(pgrid, CVaR(pgrid), '--') axs[3].set_xlim(pgrid.min(), pgrid.max()) axs[3].set_title('CVaR') else: assert np.allclose(ecvar.squeeze(), CVaR(pgrid).squeeze(), rtol=4e-2) # ygrid = np.linspace(-1,10,100) ygrid = np.linspace(stats.lognorm.ppf(0.0, np.exp(mu), sigma), stats.lognorm.ppf(0.9, np.exp(mu), sigma), 101) essd = compute_conditional_expectations(ygrid, values, False) # print(np.linalg.norm(essd.squeeze()-ssd(ygrid),ord=np.inf)) if plot: axs[4].plot(ygrid, essd, '-') axs[4].plot(ygrid, ssd(ygrid), '--') axs[4].set_xlim(ygrid.min(), ygrid.max()) axs[4].set_title(r'$E[(\eta-Y)^+]$') axs[4].set_xlabel(r'$\eta$') else: assert np.allclose(essd.squeeze(), ssd(ygrid), atol=1e-3) # zoom into ygrid over high probability region of -Y ygrid = -ygrid[::-1] disutil_essd = compute_conditional_expectations(ygrid, values, True) assert np.allclose(disutil_essd, compute_conditional_expectations(ygrid, -values, False)) # print(np.linalg.norm(disutil_essd.squeeze()-ssd_disutil(ygrid),ord=np.inf)) if plot: axs[5].plot(ygrid, disutil_essd, '-', label='Empirical') axs[5].plot(ygrid, ssd_disutil(ygrid), '--', label='Exact') axs[5].set_xlim((ygrid).min(), (ygrid).max()) axs[5].set_title(r'$E[(\eta-(-Y))^+]$') axs[5].set_xlabel(r'$\eta$') axs[5].plot([0], [np.exp(mu + sigma**2 / 2)], 'o') axs[5].legend() plt.show() else: assert np.allclose(disutil_essd.squeeze(), ssd_disutil(ygrid), atol=1e-3)
def plot_truncated_lognormal_example_exact_quantities(num_samples=int(1e5), plot=False, mu=0, sigma=1): if plot: assert num_samples <= 1e5 lb, ub = -1, 3 f, f_cdf, f_pdf, VaR, CVaR, ssd, ssd_disutil = \ get_truncated_lognormal_example_exact_quantities(lb, ub, mu, sigma) # lb,ub passed to stats.truncnorm are defined for standard normal. # Adjust for mu and sigma using alpha, beta = (lb - mu) / sigma, (ub - mu) / sigma samples = stats.truncnorm.rvs(alpha, beta, mu, sigma, size=num_samples)[np.newaxis, :] values = f(samples)[:, 0] ygrid = np.linspace(np.exp(lb) - 1, np.exp(ub) * 1.1, 100) if plot: import matplotlib.pyplot as plt fig, axs = plt.subplots(1, 6, sharey=False, figsize=(16, 6)) from pyapprox.density import EmpiricalCDF ecdf = EmpiricalCDF(values) axs[0].plot(ygrid, ecdf(ygrid), '-') axs[0].plot(ygrid, f_cdf(ygrid), '--') axs[0].set_xlim(ygrid.min(), ygrid.max()) axs[0].set_title('CDF') if plot: ygrid = np.linspace(np.exp(lb) - 1, np.exp(ub) * 1.1, 100) axs[1].hist(values, bins='auto', density=True) axs[1].plot(ygrid, f_pdf(ygrid), '--') axs[1].set_xlim(ygrid.min(), ygrid.max()) axs[1].set_title('PDF') pgrid = np.linspace(0.01, 1 - 1e-2, 10) evar = np.array([value_at_risk(values, p)[0] for p in pgrid]).squeeze() if plot: axs[2].plot(pgrid, evar, '-') axs[2].plot(pgrid, VaR(pgrid), '--') axs[2].set_title('VaR') else: assert np.allclose(evar, VaR(pgrid), rtol=2e-2) pgrid = np.linspace(0, 1 - 1e-2, 100) ecvar = np.array([conditional_value_at_risk(values, p) for p in pgrid]) # CVaR for alpha=0 should be the mean assert np.allclose(ecvar[0], values.mean()) if plot: axs[3].plot(pgrid, ecvar, '-') axs[3].plot(pgrid, CVaR(pgrid), '--') axs[3].set_xlim(pgrid.min(), pgrid.max()) axs[3].set_title('CVaR') else: assert np.allclose(ecvar.squeeze(), CVaR(pgrid).squeeze(), rtol=1e-2) ygrid = np.linspace(np.exp(lb) - 10, np.exp(ub) + 1, 100) essd = compute_conditional_expectations(ygrid, values, False) if plot: axs[4].plot(ygrid, essd, '-') axs[4].plot(ygrid, ssd(ygrid), '--') axs[4].set_xlim(ygrid.min(), ygrid.max()) axs[4].set_title(r'$E[(\eta-Y)^+]$') axs[5].set_xlabel(r'$\eta$') else: assert np.allclose(essd.squeeze(), ssd(ygrid), rtol=2e-2) # zoom into ygrid over high probability region of -Y ygrid = -ygrid[::-1] disutil_essd = compute_conditional_expectations(ygrid, values, True) assert np.allclose(disutil_essd, compute_conditional_expectations(ygrid, -values, False)) # print(np.linalg.norm(disutil_essd.squeeze()-ssd_disutil(ygrid),ord=np.inf)) if plot: axs[5].plot(ygrid, disutil_essd, '-', label='Empirical') axs[5].plot(ygrid, ssd_disutil(ygrid), '--', label='Exact') axs[5].set_xlim(ygrid.min(), ygrid.max()) axs[5].set_title(r'$E[(\eta-(-Y))^+]$') axs[5].set_xlabel(r'$\eta$') axs[5].legend() plt.show()