-
Notifications
You must be signed in to change notification settings - Fork 87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conditional expected value with stochastically dep. distribution #376
Comments
In general terms being able to to do conditional expectation on a stochastic dependent variables is hard. There are lots of example where it is fine, but there are plenty of example where it is really difficult and cases where it is impossible. Know when you have what is also difficult programatically. If your dependencies are reduced to correlation however, things are a lot more doable. In that case you can just need to create a mapping to decorrelate your variable and apply a variable substitution. I can elaborate if that is what you need. As for cp.E_cond(g[0], [False, True, True], dist)
cp.E_cond(g[1], [True, False, True], dist)
cp.E_cond(g[2], [True, True, False], dist) |
Yes, we can assume a simple case of the variable correlations, the variables are from |
Here is a working example: import numpy as np
import chaospy as cp
# correlated variable:
cov = [[1, 0.5, 0.25], [0.5, 1, 0.5], [0.25, 0.5, 1]]
mean = [1, 2, 3]
dist = cp.MvNormal(mean, cov)
# target:
dist_independent = cp.Iid(cp.Normal(0, 1), 3)
# create correlation mapping:
cholmat = np.linalg.cholesky(cov)
qq = cp.inner(cp.variable(3), cholmat) + mean
# polynomial to test on:
q0, q1, q2 = cp.variable(3)
g = cp.polynomial(q0+q1*q2)
# perform substitution:
g_ = g(*qq)
# equal:
print(cp.E(g, dist))
print(cp.E(g_, dist_independent))
# equal:
print(cp.Cov(g, dist))
print(cp.Cov(g_, dist_independent)) Obviously here |
Awesome thanks, but what would be the conditional expectation for the polynomial given some correlated variables in your example? E.g. |
Ah, good point. I didn't think the example through. So the When you want to do other ordering like As I said, conditional expectation of dependent variables is difficult... |
Ok, I think I get the idea, we move the stoch. dependency from the distribution to the polynomial. Instead of using the original correlated variables, we use a linear combination (reflecting the correlation) of the uncorrelated variables. Although, in the example above,
|
Yeah, you got it.
But yeah, I might have mixed that up above. My time is a bit limited, and I am working through these examples quite fast. As for the shape, that is not right. I'd need a small working example to look at. Let see. We want something I hope that was helpful. |
Thanks Jonathan, I appreciate your time, here is a working example which should also deal with the permutation of the variables. Please let me know if that makes sense. def E_cond_corr(poly, freeze, dist):
"""
Conditional expected value of a distribution or polynomial.
The distribution of the input is stochastically dependent, where
the dependency is a simple correlation of the random variables.
1st order statistics of a polynomial on a given probability space
conditioned on some of the variables.
Args:
poly (numpoly.ndpoly):
Polynomial to find conditional expected value on.
freeze (numpy.ndpoly):
Boolean values defining the conditional variables. True values
implies that the value is conditioned on, e.g. frozen during the
expected value calculation.
dist (Distribution) :
The distributions of the input used in ``poly``.
Returns:
(numpoly.ndpoly) :
Same as ``poly``, but with the variables not tagged in ``frozen``
integrated away.
Examples:
>>> q0, q1, q2 = cp.variable(3)
>>> poly = cp.polynomial([1, q0, q1, 10*q0*q1-q2])
polynomial([1 q0 q1 10*q0*q1-q2])
>>> cov = [[1, 0.5, 0.25], [0.5, 1, 0.5], [0.25, 0.5, 1]]
>>> mean = [1, 2, 3]
>>> dist = cp.MvNormal(mean, cov)
>>> E_cond_corr(poly, q0, dist)
polynomial([1.0, q0+1.0, 0.5*q0+2.0, 5.0*q0**2+24.75*q0+17.0])
>>> E_cond_corr(poly, q1, dist)
polynomial([1.0, 1.0, 0.8660254037844386*q0+2.0,
8.660254037844386*q0+22.0])
>>> E_cond_corr(poly, [q0, q1], dist)
polynomial([1.0, q0+1.0, 0.8660254037844386*q1+0.5*q0+2.0,
8.660254037844386*q0*q1+5.0*q0**2+8.227241335952167*q1+24.75*q0+17.0])
>>> E_cond_corr(poly, [], dist)
polynomial([1.0, 1.0, 2.0, 22.0])
>>> E_cond_corr(4, [], dist)
array(4)
"""
if not dist.stochastic_dependent:
return E_cond(poly, freeze, dist)
# Format standardization of freeze [bool bool bool ...]
freeze = numpoly.aspolynomial(freeze)
if not freeze.size:
return numpoly.polynomial(cp.E(poly, dist))
if not freeze.isconstant():
freeze = [name in freeze.names for name in poly.names]
else:
freeze = freeze.tonumpy()
freeze = np.asarray(freeze, dtype=bool)
Ndim = len(dist)
cov = dist._parameters['covariance']
mu = dist._parameters['mean']
dist_independent = cp.Iid(cp.Normal(0, 1), Ndim)
# Sort freeze such that True values appear first
# we need to sort in descending order, default is ascending
# => negate the values in freeze to achive the desired sort order
freeze_inv = list(map(lambda x: 1-x, freeze))
perm = np.argsort(freeze_inv)
# Build the permutation matrix
P = np.eye(Ndim)[perm]
# Permute variables and covariance
freeze_P = np.matmul(freeze, P.transpose()) #permute cols
Q_P = np.matmul(cp.variable(Ndim), P.transpose()) #permute cols
cov_P = np.matmul(P, np.matmul(cov, P.transpose())) #permute first cols, then rows
# Create correlation mapping
cholmat = np.linalg.cholesky(cov_P)
qq = cp.inner(Q_P, cholmat) + mean
# Perform substitution
poly_ = poly(*qq)
return cp.E_cond(poly_, freeze_P, dist_independent) With the function above, and your example code from an earlier post of this thread, I get:
a = E_cond_corr(g, [q0, q1], dist)
b = cp.E_cond(g_, [q0, q1], dist_independent)
assert(a==b)
c = E_cond_corr(g, [q1, q0], dist) #swap order of q0, q1
assert(a == c)
# a = polynomial(0.375*q1**2+0.4330127018922193*q0*q1+0.125*q0**2+3.464101615137755*q1+3.0*q0+7.0) a = E_cond_corr(g, [q0], dist)
b = cp.E_cond(g_, [q0], dist_independent)
assert(a==b)
# a = polynomial(0.125*q0**2+3.0*q0+7.375)
a = E_cond_corr(g, [q1,q2], dist)
b = E_cond_corr(g, [q2,q1], dist) #swap order of q1, q2
assert(a == b)
# a = polynomial(0.25*q1**2+0.4330127018922193*q0*q1+3.5*q1+1.7320508075688772*q0+7.0) |
I haven't tested you code, but yeah, that looks about right. Good going. |
Hi Jonathan,
I would like to evaluate conditional expected value
E(g_i | X_{~i})
, whereg_i
is a component function (polynomial) which contains onlyX_i
terms and the conditional variables are all the other variables (exceptX_i
). The variablesX~N(mu, cov)
are considered to be correlated, i.e. dist=cp.MvNormal().When looking at your implementation of cp. E_cond() there is an assert which is activated when dist is stochastically dependent. I am wondering what needs to be done such that I can compute the cond. exp. value also with a stoch. dep. distribution.
My approach was to first modify your code of E_cond() such that I compute
expected.E(unfrozen, dist)
(the last line of in the E_cond source code) numerically by sampling from dist and computing a mean of evaluated unfrozen polynomials. But I think this is not enough.To elaborate a bit more, in my understanding, computing the expected value of a polynomial
g_i
, where the conditional variablesX_{~i}
are not present in the polynomial, will result in a constant numberc
, i.e.c = E(g_i | X_{~i})
and variance ofV(c) = 0
. But in case of the correlated variables, even if the conditional variablesX_{~i}
are not present in the polynomial they still interact with theX_i
variables that are ing_i
and thusE(g_i | X_{~i})
will not be a constant, is this correct?The text was updated successfully, but these errors were encountered: