Solving simple chemical network odes in pymc3 with theano - python-3.x

Im trying to solve a simple chemical network A->B(reaction rate k1) and A1->B(reaction rate k2) with Bayesian inference. My hopes are to get sensitivity analysis of k1 and k2. If A, A1 and B are my constant variables only logical thing would be that if for example k1 decreases k2 should increase for some proportional amount and vice versa. But I am having some troubles with ODE's in pymc3. So here is my attempt:
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint, solve_ivp
import seaborn
import pymc3 as pm
import theano.tensor as T
from theano.compile.ops import as_op
from sys import exit
time = 10
Nt = 11
tt = np.linspace(0,time, Nt)
y0 = [1,2,0]
k1, k2 = 1, 1
#Actual Solution of the Differential Equation(Used to generate data)
def real(t,c):
da_dt = -k1*c[0]
da1_dt = -k2*c[1]
db_dt = k1*c[0] + k2*c[1]
return da_dt, da1_dt, db_dt
c_est = solve_ivp(real, t_span = [0,time], t_eval = tt, y0 = y0)
#Method For Solving the ODE
def lv(xdata, k1=1, k2=1):
def equat(c,t):
da_dt = -k1*c[0]
da1_dt = -k2*c[1]
db_dt = k1*c[0] + k2*c[1]
return da_dt, da1_dt, db_dt
Y, dict = odeint(equat,y0,xdata,full_output=True)
return Y
#Generating Data for Bayesian Inference
k1, k2 = 1, 1
ydata = c_est.y
# Adding some error to the ydata points
yerror = 10*np.random.rand(Nt)
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(tt, k1=al, k2=be)
return np.ravel(Q)
# Number of Samples and Initial Conditions
nsample = 5000
y0 = 1.0
sd = 0.2
# Model for Bayesian Inference
model = pm.Model()
with model:
# Priors for unknown model parameters
k1 = pm.HalfNormal('k1', sd = sd)
k2 = pm.HalfNormal('k2', sd = sd)
# Expected value of outcome
mu = func(k1,k2)
# Likelihood (sampling distribution) of observations
Y_obs = pm.Normal('Y_obs', mu=mu, sd=yerror, observed=y_data)
trace = pm.sample(nsample, nchains=1)
pm.traceplot(trace)
plt.show()
But it doesn't "loop" through equat function. Output error:
Traceback (most recent call last):
File "<ipython-input-16-14ca425a8735>", line 1, in <module>
runfile('/folder/code.py', wdir='/folder')
File "/anaconda3/lib/python3.7/site-packages/spyder_kernels/customize/spydercustomize.py", line 786, in runfile
execfile(filename, namespace)
File "/anaconda3/lib/python3.7/site-packages/spyder_kernels/customize/spydercustomize.py", line 110, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "/code.py", line 77, in <module>
mu = func(k1,k2)
File "/anaconda3/lib/python3.7/site-packages/theano/gof/op.py", line 674, in __call__
required = thunk()
File "/anaconda3/lib/python3.7/site-packages/theano/gof/op.py", line 892, in rval
r = p(n, [x[0] for x in i], o)
File "/anaconda3/lib/python3.7/site-packages/theano/compile/ops.py", line 555, in perform
outs = self.__fn(*inputs)
File "/code.py", line 60, in func
Q = lv(tt, k1=al, k2=be)
File "/code.py", line 42, in lv
Y, dict = odeint(equat,y0,xdata,full_output=True)
File "/anaconda3/lib/python3.7/site-packages/scipy/integrate/odepack.py", line 233, in odeint
int(bool(tfirst)))
File "/code.py", line 39, in equat
da1_dt = -k2*c[1]
IndexError: index 1 is out of bounds for axis 0 with size 1
I'm going nuts here. :( I don't even know if I am on the right path.
Edit, corrected that but now it shows another error.

If anyone else has difficulty here I solved it!
from scipy.integrate import odeint, solve_ivp
import numpy as np
import matplotlib.pyplot as plt
from theano.compile.ops import as_op
import theano.tensor as T
import pymc3 as pm
import copy
from sys import exit
time = 10
Nt = 11
tt = np.linspace(0,time, Nt+1)
y0 = [1,2,0]
k1, k2 = 1, 1
def real_equat(t,c):
da_dt = -k1*c[0]
da1_dt = -k2*c[1]
db_dt = k1*c[0] + k2*c[1]
return da_dt, da1_dt, db_dt
z = solve_ivp(real_equat, t_span=[0,time], t_eval= tt, y0 = y0)
def lv(xdata, k1=k1, k2=k2):
def equat(c,t):
da_dt = -k1*c[0]
da1_dt = -k2*c[1]
db_dt = k1*c[0] + k2*c[1]
return da_dt, da1_dt, db_dt
Y, dict = odeint(equat,y0,tt,full_output=True)
return Y
a = z.y
ydata = copy.copy(a)
yerror = 10*np.random.rand(Nt+1)
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(tt, k1 = al, k2 = be)
return np.ravel(Q)
niter = 10
model = pm.Model()
with model:
# Priors for unknown model parameters
k1 = pm.Uniform('k1', upper = 1.2, lower = 0.8)
k2 = pm.Uniform('k2', upper = 1.2, lower = 0.8)
# Expected value of outcome
mu = func(k1,k2)
# Likelihood (sampling distribution) of observations
Y_obs = pm.Normal('Y_obs', mu=mu, sd=0.2, observed=ydata)
trace = pm.sample(niter = niter, nchains=4)

Related

How to computes the Jacobian of BertForMaskedLM using jacrev

I tried this plan blow to compute the Jacobian of BertForMaskedLM using jacrev:
import numpy as np
from transformers import BertTokenizer,BertForMaskedLM
import torch
import torch.nn as nn
from functorch import make_functional, make_functional_with_buffers, vmap, vjp, jvp, jacrev
device = 'cuda:2'
torch.cuda.empty_cache()
model_name = 'bert-base-chinese'
tokenizer = BertTokenizer.from_pretrained(model_name)
bert_model = BertForMaskedLM.from_pretrained(model_name)
net = bert_model.to(device)
fnet, params, buffers = make_functional_with_buffers(net)
def fnet_single(params,x,y):
result = fnet(params, buffers, x.unsqueeze(0).unsqueeze(0),y.unsqueeze(0).unsqueeze(0))['logits']
return result.squeeze(0).squeeze(0)
text = u'大肠杆菌是人和许多动物肠道中最主要的一种细菌'
inputs = tokenizer.encode_plus(text)
segment_ids = inputs['token_type_ids']
token_ids = inputs['input_ids']
length = len(token_ids) - 2
batch_token_ids = torch.tensor([token_ids] * (2 * length - 1),requires_grad=True).to(device)
batch_segment_ids = torch.zeros_like(batch_token_ids).to(device)
for i in range(length):
if i > 0:
batch_token_ids[2 * i - 1, i] = 103
batch_token_ids[2 * i - 1, i + 1] = 103
batch_token_ids[2 * i, i + 1] = 103
threshold = 100
word_token_ids = [[token_ids[1]]]
for i in range(1, length):
x,y = batch_token_ids[2 * i],batch_segment_ids[2*i]
jacobian1 = jacrev(fnet_single,argnums=1)(params,x,y)
x,y = batch_token_ids[2 * i - 1],batch_segment_ids[2*i-1]
jacobian2 = jacrev(fnet_single,argnums=1)(params,x,y)
Howerer,an error appeared:
'Traceback (most recent call last):
File "study_jacrev.py", line 49, in
batch_token_ids = torch.tensor([token_ids] * (2 * length - 1),requires_grad=True).to(device)
RuntimeError: Only Tensors of floating point and complex dtype can require gradients'
Is there anyone to help me?
It is because you are trying to get the jacobian with respect to data for whom the gradient scope is not set.
If you want to get the jacobian wrt parameters: jacrev(fnet_single, argnums=0)(params, x, y)
If you want to get the jacobian wrt data: x = x.to(torch.float32).requires_grad_(True) (note that converting x dtype to float is mandatory to set the scope on it)

3D plotting lorentz python

I'm pretty new to python, but I've been working on this program to graph the solutions to the Lorenz differential equation in 3D, but
I keep getting this error:
Traceback (most recent call last):
File "lorenz_attractor3D.py", line 3, in <module>
from mpl_toolkits.mplot3d.axes3d import Axes3D
ImportError: No module named mpl_toolkits.mplot3d.axes3d]
Not clear why. I don't know if it's because I don't have matlib installed correctly.
Code:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D
from matplotlib import cm
def lorenz(x, y, z, s=10, r=28, b=2.667):
"""
Given:
x, y, z: a point of interest in three dimensional space
s, r, b: parameters defining the lorenz attractor
Returns:
x_dot, y_dot, z_dot: values of the lorenz attractor's
derivatives at the point x, y, z
"""
x_dot = s*(y - x)
y_dot = r*x - y - x*z
z_dot = x*y - b*z
return x_dot, y_dot, z_dot
dt = 0.01
num_steps = 10000
# Need one more for the initial values
xs = np.empty(num_steps + 1)
ys = np.empty(num_steps + 1)
zs = np.empty(num_steps + 1)
# Set initial values
xs[0], ys[0], zs[0] = (0., 1., 1.05)
# Step through "time", calculating the partial derivatives at the current point
# and using them to estimate the next point
for i in range(num_steps):
x_dot, y_dot, z_dot = lorenz(xs[i], ys[i], zs[i])
xs[i + 1] = xs[i] + (x_dot * dt)
ys[i + 1] = ys[i] + (y_dot * dt)
zs[i + 1] = zs[i] + (z_dot * dt)
# Plot
fig = plt/figure()
ax = plt.figure().add_subplot(projection='3d')
ax.plot_wireframe(xs, ys, zs, lw=0.5)
ax.set_xlabel("X Axis")
ax.set_ylabel("Y Axis")
ax.set_zlabel("Z Axis")
ax.set_title("Lorenz Attractor")
plt.plot(xs,ys)
plt.show()

How to get fitted curve for errorbar graph for several text files

I have written a code for getting errorbar and curve fitted line. But I am getting an error. I have tried this curve fitted line code from see the answer from this webpage but it is not working for me. Can you help me with it?
My Code:
#!/home/zahid/anaconda3/bin/python
import numpy as np
import matplotlib.pyplot as plt
import numpy
from scipy.optimize import curve_fit
x1, y1, y2,y3,y4,y5,y6 = [], [], [],[],[], [], [],[],[], [], [],[]
with open("1_peak.txt") as f:
for line in f:
cols = line.split()
x1.append(float(cols[0]))
y1.append(float(cols[2]))
with open("2_peak.txt") as f:
for line in f:
cols = line.split()
x2.append(float(cols[0]))
y2.append(float(cols[2]))
.
.
.
with open("6_peak.txt") as f:
for line in f:
cols = line.split()
x6.append(float(cols[0]))
y6.append(float(cols[2]))
for item_a, item_b, item_d, item_e, item_f, item_g, item_c in zip(y1, y2,y3,y4,y5,y6, x1):
B = (item_a + item_b + item_d + item_e + item_f + item_g)/6
arr = numpy.array([item_a, item_b, item_d, item_e, item_f, item_g])
C = numpy.mean(arr, axis=0)
D = numpy.std(arr, axis=0)
print (item_c, C , D)
x = np.array(item_c)
y = np.array(C)
e = np.array(D)
def line(x, a, b):
return a * x + b
popt, pcov = curve_fit(line, x, y)
plt.errorbar(x, y, e, linestyle='None', marker='^')
xfine = np.linspace(0., 100., 100)
plt.plot(xfine, line(xfine, popt[0], popt[1]), 'r-')
plt.xlabel('PKA_energy in keV')
plt.ylabel('intersitial')
plt.savefig("1.jpeg", dpi=500)
I am getting below error:
Traceback (most recent call last):
File "./value_analysis_peak_SIA_energy.py", line 70, in <module>
popt, pcov = curve_fit(line, x, y)
File "/home/zahid/anaconda3/lib/python3.6/site-packages/scipy/optimize/minpack.py", line 736, in curve_fit
res = leastsq(func, p0, Dfun=jac, full_output=1, **kwargs)
File "/home/zahid/anaconda3/lib/python3.6/site-packages/scipy/optimize/minpack.py", line 380, in leastsq
raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m))
TypeError: Improper input: N=2 must not exceed M=1
I think this is similar to what you want to do, please try it and modify as needed for your work. Here I use a quadratic curve to fit the data, the polynomial order is set at the top of the code.
#!/home/zahid/anaconda3/bin/python
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
polynomialOrder = 2 # example quadratic
x1 = []
x2 = []
x6 = []
y1 = []
y2 = []
y6 = []
# load the raw data
with open("1_peak.txt") as f:
for line in f:
cols = line.split()
x1.append(float(cols[0]))
y1.append(float(cols[2]))
with open("2_peak.txt") as f:
for line in f:
cols = line.split()
x2.append(float(cols[0]))
y2.append(float(cols[2]))
with open("6_peak.txt") as f:
for line in f:
cols = line.split()
x6.append(float(cols[0]))
y6.append(float(cols[2]))
# fit each data set to individual polynomials
parms1 = np.polyfit(x1, y1, polynomialOrder)
parms2 = np.polyfit(x2, y2, polynomialOrder)
parms6 = np.polyfit(x6, y6, polynomialOrder)
# calculate errors for each fit
err1 = np.polyval(parms1, x1) - y1
err2 = np.polyval(parms2, x2) - y2
err6 = np.polyval(parms6, x6) - y6
# graph size is set before calling plot commands
graphWidth = 800 # pixels
graphHeight = 600 # pixels
plt.figure(figsize=(graphWidth/100.0, graphHeight/100.0), dpi=100)
# plot the raw data as error-bar scatter plots
plt.errorbar(x1, y1, err1, linestyle='None', marker='^')
plt.errorbar(x2, y2, err2, linestyle='None', marker='^')
plt.errorbar(x6, y6, err6, linestyle='None', marker='^')
# plot the fitted polynomials
xmodel1 = np.linspace(min(x1), max(x1))
ymodel1 = np.polyval(parms1, xmodel1)
xmodel2 = np.linspace(min(x2), max(x2))
ymodel2 = np.polyval(parms2, xmodel2)
xmodel6 = np.linspace(min(x6), max(x6))
ymodel6 = np.polyval(parms6, xmodel6)
plt.plot(xmodel1, ymodel1)
plt.plot(xmodel2, ymodel2)
plt.plot(xmodel6, ymodel6)
# final code here
plt.xlabel('PKA_energy in keV')
plt.ylabel('intersitial')
plt.show()
'''
popt, pcov = curve_fit(line, x, y)
plt.errorbar(x, y, e, linestyle='None', marker='^')
xfine = np.linspace(0., 100., 100)
plt.plot(xfine, line(xfine, popt[0], popt[1]), 'r-')
plt.xlabel('PKA_energy in keV')
plt.ylabel('intersitial')
#plt.savefig("1.jpeg", dpi=500)
plt.show()
'''

TypeError: 'Line3DCollection' object is not iterable

I'm trying to create animation about how the value of a quantum bit would be changed by computation called X-gate, in form of an arrow.
Here are the codes that I wrote.
#Import libraries
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np
#Accept input (theta, phi) from a user
print("Put angle theta and phi, 0≤ theta ≤180, 0≤ phi ≤360")
theta = input("theta:")
phi = input("phi:")
theta = np.radians(float(theta))
phi = np.radians(float(phi))
#Calculate x,y,z coordinates
X = np.sin(theta) * np.cos(phi)
Y = np.sin(theta) * np.sin(phi)
Z = np.cos(theta)
#Adjusting the length of an arrow
length = np.sqrt(X**2 + Y**2 + Z**2)
if length > 1:
X = X/length
Y = Y/length
Z = Z/length
# Figure of the animation
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect("equal")
u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j]
x = np.cos(u)*np.sin(v)
y = np.sin(u)*np.sin(v)
z = np.cos(v)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.plot_wireframe(x,y,z, color="black")
# Calculate x,y,z coordinates in the process of the change
length = 9
xgate_theta = np.linspace(theta,theta+np.pi,length)
xgate_phi = np.linspace(phi,phi,length)
#Array of x,y,z coordinates
xgate= []
# Only x coordinates
xgate_x = []
# Only y coordinates
xgate_y = []
# Only z coordinates
xgate_z = []
for i in range(length):
xgate_x.append(X)
xgate_z.append(np.cos(xgate_theta[i]))
xgate_y.append(np.sqrt(1-np.sqrt(xgate_x[i]**2+xgate_z[i]**2))*(-1))
for j in range(length):
xgate.append(plt.quiver(0,0,0,xgate_x[j],xgate_y[j],xgate_z[j],color="red"))
ani = animation.ArtistAnimation(fig,xgate,interval=1000)
plt.show()
Then, I got the following error.
Traceback (most recent call last):
File "/Users/makotonakai/anaconda3/lib/python3.6/site- packages/matplotlib/cbook/__init__.py", line 388, in process
proxy(*args, **kwargs)
File "/Users/makotonakai/anaconda3/lib/python3.6/site-packages/matplotlib/cbook/__init__.py", line 228, in __call__
return mtd(*args, **kwargs)
File "/Users/makotonakai/anaconda3/lib/python3.6/site-packages/matplotlib/animation.py", line 1026, in _start
self._init_draw()
File "/Users/makotonakai/anaconda3/lib/python3.6/site-packages/matplotlib/animation.py", line 1556, in _init_draw
for artist in f:
TypeError: 'Line3DCollection' object is not iterable
I cannot tell what line causes this error by just looking this error message. Can anybody tell me how I can fix this error?

confusing error when using minimize of lmfit in python

my code is as following:
import numpy as np
from math import *
from scipy.optimize import *
import scipy.optimize as opt
from lmfit import Minimizer, Parameters, report_fit
import lmfit as lf
f = open('data.txt','r')
lines=f.readlines()
n1=[]
n2=[]
n=[]
h=[]
for x in lines:
x=x.strip() # remove \n before splitting the line
n1.append(x.split('\t')[0])
n2.append(x.split('\t')[1])
n.append(x.split('\t')[2])
h.append(x.split('\t')[3])
f.close()
n1 = [float(i) for i in n1]
n2 = [float(i) for i in n2]
n = [float(i) for i in n]
h = [float(i) for i in h]
# convert a list into an array
n1 = np.array(n1)
n2 = np.array(n2)
n = np.array(n)
h = np.array(h)
def fith(params,n1,n2,n,h):
a1 = params['p1']
b1 = params['p2']
a2 = params['p3']
b2 = params['p4']
model = (a1 + b1*n) * n1 + (a2 + b2*n) * n2
return model - h
params = Parameters()
params.add('p1',value=1.0)
params.add('p2',value=1.0)
params.add('p3',value=1.0)
params.add('p4',value=1.0)
out = minimize(fith,params,args=(n1,n2,n,h))
print(out)
after run, I got the error as following:
#
Traceback (most recent call last):
File "E:\new model\calculate_H_v2.py", line 50, in
out = minimize(fith,params,args=(n1,n2,n,h))
File "E:\softwares\python\lib\site-packages\scipy\optimize_minimize.py", line 481, in minimize
return _minimize_bfgs(fun, x0, args, jac, callback, **options)
File "E:\softwares\python\lib\site-packages\scipy\optimize\optimize.py", line 943, in _minimize_bfgs
gfk = myfprime(x0)
File "E:\softwares\python\lib\site-packages\scipy\optimize\optimize.py", line 292, in function_wrapper
return function((wrapper_args + args))
File "E:\softwares\python\lib\site-packages\scipy\optimize\optimize.py", line 703, in approx_fprime
return _approx_fprime_helper(xk, f, epsilon, args=args)
File "E:\softwares\python\lib\site-packages\scipy\optimize\optimize.py", line 637, in _approx_fprime_helper
f0 = f(((xk,) + args))
File "E:\softwares\python\lib\site-packages\scipy\optimize\optimize.py", line 292, in function_wrapper
return function(*(wrapper_args + args))
File "E:\new model\calculate_H_v2.py", line 35, in fith
a1 = params['p1']
IndexError: only integers, slices (:), ellipsis (...), numpy.newaxis (None) and integer or boolean arrays are valid indices
#
I could not figure it out why I got this kind of error after read through the questions. Can you help me out?
Thanks in advance.
Jing
I think the basic problem is that you are using scipy.optimize.minimize() instead of lmfit.minimize(). That is, you import * from scipy.optimize, then you import Minimizer from lmfit.
That is, using from lmfit import minimize, Parameters, report_fit, or use
mini = Minimizer(fith,params,args=(n1,n2,n,h))
out = mini.minimize()
should make your script use lmfit.minimize() which looks to me like it should then work.
This is why import * is painful: you have a hard time telling where symbols came from.
As a side comment, you can probably use numpy.loadtxt() to simplify the reading of your data to numpy arrays.

Resources