How to integrate bivariate normal using quadpy - python

I am trying to use quadpy to integrate a function against the bivariate normal dist. To test it is working, I tried
from scipy.stats import multivariate_normal
import numpy as np
import quadpy
rho = 0.95
cov = np.array([[1, rho], [rho, 1]])
bivn = multivariate_normal(mean=None, cov=cov)
pdfer2 = lambda x: bivn.pdf(np.stack(x,axis=1))*np.exp(x[0]**2 + x[1]**2)
scheme = quadpy.e2r2.get_good_scheme(3)
val = scheme.integrate(pdfer2)
The result I get is val=1.25, which is quite far from 1. If I remove the np.stack, I get an error:
File "C:\Users\steve\anaconda3\lib\site-packages\scipy\stats_multivariate.py", line 473, in _logpdf
dev = x - mean
ValueError: operands could not be broadcast together with shapes (2,6) (2,)
Any idea what I am doing wrong? Or is this level of error expected? Is there an error estimate available? (integrate just seems to return a single value).
Thanks!

Related

Tensorflow-probability error with 'Tensor is unhashable' in Gaussian Process

I am trying to get a minimal gaussian process example working in tensorflow probability. I can get everything to work until I try defining the log marginal likelihood. At this stage I get the error TypeError: Tensor is unhashable if Tensor equality is enabled. Instead, use tensor.experimental_ref() as the key. I have tried reshaping the x and y arrays but that doesn't seem to be the issue. I also had this error when I tried following the google gaussian process regression colab. Can anyone give me some pointers on what I am doing wrong? Below is a minimal example.
import numpy as np
import tensorflow as tf
import tensorflow_probability as tfp
# Make some data
x = np.array([1, 2, 4, 0, -1, -2, -3], dtype=np.float64)
y = np.sin(x)
noise = x * 0 + 0.1
# Define a mean function
def meanfn(y):
return tf.constant([np.mean(y)], dtype=np.float64)
# Define the kernel
periodic_amplitude = tf.exp(tf.Variable(np.float64(0)), name='periodic_amplitude')
periodic_length_scale = tf.exp(tf.Variable(np.float64(1)), name='periodic_length_scale')
periodic_period = tf.exp(tf.Variable(np.float64(0)), name='periodic_period')
local_periodic_kernel = tfp.positive_semidefinite_kernels.ExpSinSquared(amplitude=periodic_amplitude, length_scale=periodic_length_scale, period=periodic_period)
# Define the gp
gp = tfp.distributions.GaussianProcess(
mean_fn=meanfn,
kernel=local_periodic_kernel,
index_points=x.reshape(-1,1),
observation_noise_variance=noise)
# Negative marginal likelihood
neg_marginal_lik = -gp.log_prob(y)
On my computer the versions are tensorflow=2.0.0, tensorflow-probability=0.7.0, numpy=1.17.2.
With TF 2.0.0 you should use TFP 0.8.0.

How to find Eigenspace of a matrix using python

I have a matrix which is I found its Eigenvalues and EigenVectors, but now I want to solve for eigenspace, which is Find a basis for each of the corresponding eigenspaces! and don't know how to start! by finding the null space from scipy or solve for reef(), I tried but didn't work! please help!
this is the code I am using
# import packages
import numpy as np
from numpy import linalg as LA
from scipy.linalg import null_space
# define matrix and vector
M = np.array([[0.82, 0.1],[0.18,0.9]])
v0 = np.array([[15000],[800]])
eigenVal, eigenVec = LA.eig(M)
print(eigenVal)
# Based on the Characteristic polynomial formula
#pol_formula =(A- \lambda I)\mathbf{v} = 0\)
identity = np.identity(2, dtype=float)
lamdbdaI= eigenVal*identity
## Apply the Characteristic polynomial formula using ###M matrix
char_poly = M-lamdbdaI
print(char_poly)
Here I am stuck !
The np.linalg.eig functions already returns the eigenvectors, which are exactly the basis vectors for your eigenspaces. More precisely:
v1 = eigenVec[:,0]
v2 = eigenVec[:,1]
span the corresponding eigenspaces for eigenvalues lambda1 = eigenVal[0] and lambda2 = eigenvVal[1].

Python fmin(find minimum) for a vector function

I would like to find the minimum of 3dvar function defined as:
J(x)=(x-x_b)B^{-1}(x-x_b)^T + (y-H(x)) R^{-1} (y-H(x))^T (latex code)
with B,H,R,x_b,y given.
I would like to find the argmin(J(x)). However it seems fmin in python does not work. (the function J works correctly)
Here is my code:
import numpy as np
from scipy.optimize import fmin
import math
def dvar_3(x):
B=np.eye(5)
H=np.ones((3,5))
R=np.eye(3)
xb=np.ones(5)
Y=np.ones(3)
Y.shape=(Y.size,1)
xb.shape=(xb.size,1)
value=np.dot(np.dot(np.transpose(x-xb),(np.linalg.inv(B))),(x-xb)) +np.dot(np.dot(np.transpose(Y-np.dot(H,x)),(np.linalg.inv(R))),(Y-np.dot(H,x)))
return value[0][0]
ini=np.ones(5) #
ini.shape=(ini.size,1) #change initial to vertical vector
fmin(dvar_3,ini) #start at initial vector
I receive this error:
ValueError: operands could not be broadcast together with shapes (5,5) (3,3)
How can I solve this problem? Thank you in advance.
reshape argument x in the function dvar_3, the init argument of fmin() needs a one-dim array.
import numpy as np
from scipy.optimize import fmin
import math
def dvar_3(x):
x = x[:, None]
B=np.eye(5)
H=np.ones((3,5))
R=np.eye(3)
xb=np.ones(5)
Y=np.ones(3)
Y.shape=(Y.size,1)
xb.shape=(xb.size,1)
value=np.dot(np.dot(np.transpose(x-xb),(np.linalg.inv(B))),(x-xb)) +np.dot(np.dot(np.transpose(Y-np.dot(H,x)),(np.linalg.inv(R))),(Y-np.dot(H,x)))
return value[0][0]
ini=np.ones(5) #
fmin(dvar_3,ini) #start at initial vector

The shape variable in pymc3.DensityDist does not work properly

I am trying to define a multivariate custom distribution through pymc3.DensityDist(); however, I keep getting the following error that dimensions do not match:
"LinAlgError: 0-dimensional array given. Array must be two-dimensional"
I have already seen https://github.com/pymc-devs/pymc3/issues/535 but I could not find the answer to my question. Just for clarity, here is my simple example
import numpy as np
import pymc3 as pm
def pdf(x):
y = 0
print(x)
sigma = np.identity(2)
isigma = sigma
mu = np.array([[1,2],[3,4]])
for i in range(2):
x0 = x- mu[i,:]
xsinv = np.linalg.multi_dot([x0,isigma,x0])
y = y + np.exp(-0.5*xsinv)
return y
logp = lambda x: np.log(pdf(x))
with pm.Model() as model:
pm.DensityDist('x',logp, shape=2)
step = pm.Metropolis(tune=False, S=np.identity(2))
trace = pm.sample(100000, step=step, chain=1, tune=0,progressbar=False)
result = trace['x']
In this simple code I want to define an unnormilized pdf function, which is sum of two unnormalized normal distributions, and take samples from this pdf through Metropolis algorithm.
Thanks,
Try replacing numpy for theano in the following lines:
xsinv = tt.dot(tt.dot(x0, isigma), x0)
y = y + tt.exp(-0.5 * xsinv)
as a side note, try using NUTS instead of metropolis and let PyMC3 choose the sampling method for you, just do
trace = pm.sample(1000)
For future reference you can also ask questions here

Scipy fmin_slsqp error "failed in converting 8th argument `g' of _slsqp.slsqp to C/Fortran array"

I have seen this question or a variant asked elsewhere e.g.
Scipy error using optimization module. Failure converting array to fortran
http://numpy-discussion.10968.n7.nabble.com/minimize-Algorithmen-Problem-with-boundarys-td37709.html
But they are not really put with a simple hackable example code. Nor are there any real answers (probably because of the lack of a simple demo of the problem).
The problem is, when trying to fit a function using scipy.optimise fmin_slsqp method you get this pretty opaque error
"failed in converting 8th argument `g' of _slsqp.slsqp to C/Fortran array"
In the code below I fit a linear function to random correlated data using the leastsq method. From the .docs I can see no reason that the same syntax shouldn't do the same thing using fmin_slsqp, but it doesn't.
Does anybody know why?
import numpy as nm
from scipy.optimize import leastsq, fmin_slsqp
import matplotlib.pyplot as plt
# residuals of linear function
def res(params,x,y_real):
y_fit = params[0] +x*params[1]
res = y_fit-y_real
return res
#generate correlated data
xx = nm.array([-0.51, 51.2])
yy = nm.array([0.33, 51.6])
means = [xx.mean(), yy.mean()]
stds = [xx.std() / 3, yy.std() / 3]
corr = 0.8 # correlation
covs = [[stds[0]**2 , stds[0]*stds[1]*corr],
[stds[0]*stds[1]*corr, stds[1]**2]]
m = nm.random.multivariate_normal(means, covs, 100)
x = m[:,0]
y = m[:,1]
# Initial values of parameters
initvals = [0,0]
fit1,j = leastsq(res, initvals, args=(x,y))
#Plot fit 1
y_fit = fit1[0] + fit1[1]*x
plt.scatter(x,y)
plt.plot(x,y_fit)
plt.show()
fit2 = fmin_slsqp(res, initvals, args=(x,y))
I get the same error when the return from the Objective function is not a scalar. A minimal example which causes this error is
from scipy.optimize import fmin_slsqp
def fn(x):
return [0.,1.]
x = [0, 1., 2.]
minsoln = fmin_slsqp(fn, x)
while the following does not raise the error,
from scipy.optimize import fmin_slsqp
def fn(x):
return 0.
x = [0, 1., 2.]
minsoln = fmin_slsqp(fn, x)
I think this is either a bug or should have a clearer error message. I've raise an issue.
UPDATE:
This has now been resolved by b-carter to give a clear error message,
"Objective function must return a scalar"
with the documentation updated, see this thread for discussion.
Hi I had the same error with the following:
def ptf_returns(weights,returns):
return pd.DataFrame(np.array(returns).T*(weights)).T.mean().mean()
When I add the following it works:
def ptf_returns(weights,returns):
return float(pd.DataFrame(np.array(returns).T*(weights)).T.mean().mean())
The bug seems to be oriented around the type() of the response.

Categories

Resources