Custom multivariate Dirichlet priors in pymc3 - pymc3

Is it possible create custom multivariate distributions in pymc3? In the following, I have tried to create a linear transformation of a Dirichlet distribution. All variants on this have returned numerous errors, perhaps to do with theano data types? Any help would be gratefully appreciated.
import numpy as np
import pymc3 as pymc
import theano.tensor as tt
# data
n = 5
prior_params = np.ones(n - 1) / (n - 1)
mx = np.array([[0.25 , 0.5 , 0.75 , 1. ],
[0.25 , 0.333, 0.25 , 0. ],
[0.25 , 0.167, 0. , 0. ],
[0.25 , 0. , 0. , 0. ]])
# Note that the matrix mx takes the unit simplex into the unit simplex.
# custom log-liklihood
def generate_function(mx, prior_params):
def log_trunc_dir(x):
return pymc.Dirichlet.dist(a=prior_params).logp(mx.dot(x.T)).eval()
return log_trunc_dir
#model
with pymc.Model() as simple_model:
x = pymc.Dirichlet('x', a=np.ones(n - 1))
q = pymc.DensityDist('q', generate_function(mx, prior_params), observed={'x': x})

Thanks to significant help from the PyMC3 development community, I can post the
following working example of a customised Dirichlet prior in PyMC3.
import pymc3 as pm
import numpy as np
import scipy.special as special
import theano.tensor as tt
import matplotlib.pyplot as plt
n = 4
with pm.Model() as model:
prior = np.ones(n) / n
def dirich_logpdf(value=prior):
return -n * special.gammaln(1/n) + (-1 + 1/n) * tt.log(value).sum()
stick = pm.distributions.transforms.StickBreaking()
probs = pm.DensityDist('probs', dirich_logpdf, shape=n,
testval=np.array(prior), transform=stick)
data = np.array([5, 7, 1, 0])
sfs_obs = pm.Multinomial('sfs_obs', n=np.sum(data), p=probs, observed=data)
with model:
step = pm.Metropolis()
trace = pm.sample(100000, tune=10000, step=step)
print('MLE = ', data / np.sum(data))
print(pm.summary(trace))
pm.traceplot(trace, [probs])
plt.show()

Related

PyMC3 Bayesian Inference with NUTS initialization

I'm trying to implement a simple Bayesian Inference using a ODE model. I want to use the NUTS algorithm to sample but it gives me an initialization error. I do not know much about the PyMC3 as I'm new to this. Please take a look and tell me what is wrong.
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
import seaborn
import pymc3 as pm
import theano.tensor as T
from theano.compile.ops import as_op
#Actual Solution of the Differential Equation(Used to generate data)
def actual(a,b,x):
Y = np.exp(-b*x)*(a*np.exp(b*x)*(b*x-1)+a+b**2)/b**2
return Y
#Method For Solving the ODE
def lv(xdata, a=5.0, b=0.2):
def dy_dx(y, x):
return a*x - b*y
y0 = 1.0
Y, dict = odeint(dy_dx,y0,xdata,full_output=True)
return Y
#Generating Data for Bayesian Inference
a0, b0 = 5, 0.2
xdata = np.linspace(0, 21, 100)
ydata = actual(a0,b0,xdata)
# Adding some error to the ydata points
yerror = 10*np.random.rand(len(xdata))
ydata += np.random.normal(0.0, np.sqrt(yerror))
ydata = np.ravel(ydata)
#as_op(itypes=[T.dscalar, T.dscalar], otypes=[T.dvector])
def func(al,be):
Q = lv(xdata, a=al, b=be)
return np.ravel(Q)
# Number of Samples and Initial Conditions
nsample = 5000
y0 = 1.0
# Model for Bayesian Inference
model = pm.Model()
with model:
# Priors for unknown model parameters
alpha = pm.Uniform('alpha', lower=a0/2, upper=a0+a0/2)
beta = pm.Uniform('beta', lower=b0/2, upper=b0+b0/2)
# Expected value of outcome
mu = func(alpha,beta)
# Likelihood (sampling distribution) of observations
Y_obs = pm.Normal('Y_obs', mu=mu, sd=yerror, observed=ydata)
trace = pm.sample(nsample, nchains=1)
pm.traceplot(trace)
plt.show()
The error that I get is
Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Initializing NUTS failed. Falling back to elementwise auto-assignment.
Any help would be really appreciated

Trying to divide by solution of odeint

I am using odeint in python to solve something (the Friedmann equation for a matter only universe) and it gives me the values of a that i want. However, how do i get it to return/plot (da/dt)/a? i.e how can divide the values for the function for the derivative by the corresponding values of the solution?
This is my attempted code: (ignore the earlier bits i.e the figure 1 plot; its the part with H i'm concerned about)
import numpy as np
import matplotlib.pyplot as plt
import scipy as sp
from scipy.integrate import odeint
t_0 = 0.0004
a_0 = 0.001
omega_m = 1.0 #for EdS
H_0 = 1./13.7
#the function for EdS universe
def Friedmann(a, t):
dadt = H_0 * (omega_m)**(1./2.) * a**(-1./2.)
return dadt
t = np.linspace(t_0,13.7,101)
a = odeint(Friedmann, a_0, t)
a = np.array(a).flatten()
plt.figure(1)
plt.subplot(211)
plt.plot(t, a)
plt.title("Einstein-de Sitter Universe")
plt.xlabel("t")
plt.ylabel("a")
#comparing to analytic solution
an = (((3. / 2.) * (H_0 * omega_m**(1./2.)) * (t - t_0)) + a_0**(3. / 2.))**(2. / 3.)
an = np.array(an).flatten()
plt.figure(1)
plt.subplot(212)
plt.plot(t, a, t, an, "+")
H = [x/y for x, y in zip(Friedmann(a, t), a)]
plt.figure(2)
plt.plot(t, H)
plt.show()
Any help is much appreciated.

write a recursive function to find hermite polynomials

# I have the recursive relationship of the Hermite Polynomials:
Hn+1(x)=2xHn(x)−2nHn−1(x), n≥1,
H0(x)=1, H1(x)=2x.
I need to write def hermite(x,n) for any hermite polynomial Hn(x) using python 2.7
and make a plot of H5(x) on the interval x∈[−1,1].
Recursion is trivial here since the formula gives it. Just a small trap: you compute Hn(x), not Hn+1(x) so substract 1 to all n occurrences:
def hermite(x,n):
if n==0:
return 1
elif n==1:
return 2*x
else:
return 2*x*hermite(x,n-1)-2*(n-1)*hermite(x,n-2)
small test:
for i in range(0,5):
print(hermite(1,i))
1
2
2
-4
-20
import math
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import hermite
def HERMITE(X,N):
HER = hermite(N)
sn = HER(X)
return sn
xvals = np.linspace(-1.0,1.0,1000)
for n in np.arange(0,7,1):
sol = HERMITE(xvals,n)
plt.plot(xvals,sol,"-.",label = "n = " + str(n),linewidth=2)
plt.xticks(fontsize=14,fontweight="bold")
plt.yticks(fontsize=14,fontweight="bold")
plt.grid()
plt.legend()
plt.show()
import math
import numpy as np
import matplotlib.pyplot as plt
def HER(x,n):
if n==0:
return 1.0 + 0.0*x
elif n==1:
return 2.0*x
else:
return 2.0*x*HER(x,n-1) -2.0*(n-1)*HER(x,n-2)
xvals = np.linspace(-np.pi,np.pi,1000)
for N in np.arange(0,7,1):
sol = HER(xvals,N)
plt.plot(xvals,sol,label = "n = " + str(N))
plt.xticks(fontsize=14,fontweight="bold")
plt.yticks(fontsize=14,fontweight="bold")
plt.grid()
plt.legend()
plt.show()
#Code is working perfectly fine
Feel free to ask any question...

Understanding of a logistic regression example

I am new to Logistic regression. The following is from package mypc example
project. It is still unclear to me for its purpose. More specifically,
variable n is [5, 5, 5, 5], which is used in the mode: pymc.Binomial.
I suppose it should have both 0 and 1 in binomial fitting. n is to represent
'1' cases?
Could you explain the idea of this example? Thanks,
The example is from:
www.map.ox.ac.uk/media/PDF/Patil_et_al_2010.pdf
.........
import pymc
import numpy as np
n = 5*np.ones(4,dtype=int)
x = np.array([-.86,-.3,-.05,.73])
alpha = pymc.Normal('alpha',mu=0,tau=.01)
beta = pymc.Normal('beta',mu=0,tau=.01)
#pymc.deterministic
def theta(a=alpha, b=beta):
"""theta = logit^{-1}(a+b)"""
return pymc.invlogit(a+b*x)
d = pymc.Binomial('d', n=n, p=theta, value=np.array([0.,1.,3.,5.]),\
observed=True)
.......
import pymc
import pymc.Matplot
import mymodel
S = pymc.MCMC(mymodel, db='pickle')
S.sample(iter=10000, burn=5000, thin=2)
pymc.Matplot.plot(S)
import matplotlib.pyplot as plt
plt.show()

Python how to plot graph sine wave

I have this signal :
from math import*
Fs=8000
f=500
sample=16
a=[0]*sample
for n in range(sample):
a[n]=sin(2*pi*f*n/Fs)
How can I plot a graph (this sine wave)?
and create name of xlabel as 'voltage(V)' and ylabel as 'sample(n)'
What code to do this?
I am so thanksful for help ^_^
Setting the x-axis with np.arange(0, 1, 0.001) gives an array from 0 to 1 in 0.001 increments.
x = np.arange(0, 1, 0.001) returns an array of 1000 points from 0 to 1, and y = np.sin(2*np.pi*x) you will get the sin wave from 0 to 1 sampled 1000 times
I hope this will help:
import matplotlib.pyplot as plt
import numpy as np
Fs = 8000
f = 5
sample = 8000
x = np.arange(sample)
y = np.sin(2 * np.pi * f * x / Fs)
plt.plot(x, y)
plt.xlabel('sample(n)')
plt.ylabel('voltage(V)')
plt.show()
P.S.: For comfortable work you can use The Jupyter Notebook.
import matplotlib.pyplot as plt # For ploting
import numpy as np # to work with numerical data efficiently
fs = 100 # sample rate
f = 2 # the frequency of the signal
x = np.arange(fs) # the points on the x axis for plotting
# compute the value (amplitude) of the sin wave at the for each sample
y = np.sin(2*np.pi*f * (x/fs))
#this instruction can only be used with IPython Notbook.
% matplotlib inline
# showing the exact location of the smaples
plt.stem(x,y, 'r', )
plt.plot(x,y)
import numpy as np
import matplotlib.pyplot as plt
F = 5.e2 # No. of cycles per second, F = 500 Hz
T = 2.e-3 # Time period, T = 2 ms
Fs = 50.e3 # No. of samples per second, Fs = 50 kHz
Ts = 1./Fs # Sampling interval, Ts = 20 us
N = int(T/Ts) # No. of samples for 2 ms, N = 100
t = np.linspace(0, T, N)
signal = np.sin(2*np.pi*F*t)
plt.plot(t, signal)
plt.xlabel('Time (s)')
plt.ylabel('Voltage (V)')
plt.show()
import math
import turtle
ws = turtle.Screen()
ws.bgcolor("lightblue")
fred = turtle.Turtle()
for angle in range(360):
y = math.sin(math.radians(angle))
fred.goto(angle, y * 80)
ws.exitonclick()
The window of usefulness has likely come and gone, but I was working at a similar problem. Here is my attempt at plotting sine using the turtle module.
from turtle import *
from math import *
#init turtle
T=Turtle()
#sample size
T.screen.setworldcoordinates(-1,-1,1,1)
#speed up the turtle
T.speed(-1)
#range of hundredths from -1 to 1
xcoords=map(lambda x: x/100.0,xrange(-100,101))
#setup the origin
T.pu();T.goto(-1,0);T.pd()
#move turtle
for x in xcoords:
T.goto(x,sin(xcoords.index(x)))
A simple way to plot sine wave in python using matplotlib.
import numpy as np
import matplotlib.pyplot as plt
x=np.arange(0,3*np.pi,0.1)
y=np.sin(x)
plt.plot(x,y)
plt.title("SINE WAVE")
plt.show()
import matplotlib.pyplot as plt
import numpy as np
#%matplotlib inline
x=list(range(10))
def fun(k):
return np.sin(k)
y=list(map(fun,x))
plt.plot(x,y,'-.')
#print(x)
#print(y)
plt.show()
This is another option
#!/usr/bin/env python
import numpy as np
import matplotlib
matplotlib.use('TKAgg') #use matplotlib backend TkAgg (optional)
import matplotlib.pyplot as plt
sample_rate = 200 # sampling frequency in Hz (atleast 2 times f)
t = np.linspace(0,5,sample_rate) #time axis
f = 100 #Signal frequency in Hz
sig = np.sin(2*np.pi*f*(t/sample_rate))
plt.plot(t,sig)
plt.xlabel("Time")
plt.ylabel("Amplitude")
plt.tight_layout()
plt.show()
Yet another way to plot the sine wave.
import numpy as np
import matplotlib
matplotlib.use('TKAgg') #use matplotlib backend TKAgg (optional)
import matplotlib.pyplot as plt
t = np.linspace(0.0, 5.0, 50000) # time axis
sig = np.sin(t)
plt.plot(t,sig)
from math import *
Fs = 8000
f = 500
sample = 16
a = [0] * sample
for n in range(sample):
a[n] = sin(2*pi*f*n/Fs)
creating the x coordinates
Sample = [i for i in range(sample)]
importing matplotlib for plotting
import matplotlib.pyplot as plt
adding labels and plotting
plt.xlabel('Voltage(V)')
plt.ylabel('Sample(n)')
plt.plot(Sample, a)
plt.show()