I am learning Kalman Filters and tried to implement the following problem in Python
( problem statement description)
My approach :
I modeled it as a system with no control input and x, theta as the state vector. Then I followed the formulation (truck example) here, but I am getting bizarre results in my code. I feel like my choice of state vector might be incorrect but I am unsure.
Can someone please help me with the state vectors and other matrices required for evaluation?
from numpy import identity
from numpy.linalg import inv
import numpy as np
import matplotlib.pyplot as plt
class KalmanFilter:
def __init__(self, state_estimate, error_cov, transition_model,
control_model, obser_model, process_cov, obser_cov):
self.state_estimate = state_estimate
self.error_cov = error_cov
self.transition_model = transition_model
self.control_model = control_model
self.obser_model = obser_model
self.process_cov = process_cov
self.obser_cov = obser_cov
def predict(self, control_input):
self.state_estimate = self.transition_model * self.state_estimate \
+ self.control_model * control_input
self.error_cov = self.process_cov \
+ self.transition_model * self.error_cov * self.transition_model.T
return self.state_estimate
def update(self, obser):
innovation = obser - self.obser_model * self.state_estimate
innovation_cov = self.obser_cov \
+ self.obser_model * self.error_cov * self.obser_model.T
kalman_gain = self.error_cov * self.obser_model.T * inv(innovation_cov)
self.state_estimate = self.state_estimate + kalman_gain * innovation
n = self.error_cov.shape[0]
self.error_cov = (identity(n) - kalman_gain * self.obser_model) \
* self.error_cov
return self.state_estimate
class Process:
acc_std_dev = 1
obs_std_dev = (0.010)*(0.010)
def __init__(self, initial_state, transition_model):
self.state = initial_state
self.transition_model = transition_model
def update(self):
rand_acc = np.random.normal(0, Process.acc_std_dev)
G = np.array([[0.25, 1]]).T
self.state = self.transition_model * self.state + G * rand_acc
return self.state
def observe(self):
return self.state[0, 0] + np.random.normal(0, Process.obs_std_dev)
if __name__ == '__main__':
# delta time
dt = 1
initial_state = np.array([[0, 0]]).T
# Assuming perfect initial state estimate
error_cov = np.matrix([[0, 0],
[0, 0]])
transition_model = np.matrix([[1, 0],
[0, (1/200)]])
# Assuming no input control
control_model = np.array([[0, 0]]).T
# Making observations of the position
obser_model = np.matrix([[1, 0]])
G = np.array([[1, 0]]).T
process_cov = G * G.T * Process.acc_std_dev
kf = KalmanFilter(initial_state, error_cov, transition_model,
control_model, obser_model, process_cov,
Process.obs_std_dev**2)
p = Process(initial_state, transition_model)
positions = list()
velocities = list()
observations = list()
positionEstimates = list()
velocityEstimates = list()
for i in range(0, 100):
state = p.update()
positions.append(state[0, 0])
velocities.append(state[1, 0])
obs = p.observe()
observations.append(obs)
kf.predict(np.array([[0, 0]]))
estimate = kf.update(obs)
positionEstimates.append(kf.update(obs)[0, 0])
velocityEstimates.append(kf.update(obs)[1, 0])
xs = np.arange(len(observations))
# Position - State, Observations, Estimate
pStates, = plt.plot(xs, positions, color='k')
pObs, = plt.plot(xs, observations, color='r')
pEstimates, = plt.plot(xs, positionEstimates, color='g')
plt.legend((pObs, pStates, pEstimates),
('observations', 'true state', 'estimates'))
plt.title("Kalman Filter - Position Observations vs Estimates")
plt.ylabel('x', rotation=90)
plt.xlabel('t')
plt.show()
# Velocity - State, Estimate
pStates, = plt.plot(xs, velocities, color='k')
pEstimates, = plt.plot(xs, velocityEstimates, color='g')
plt.legend((pStates, pEstimates),
('true state', 'estimates'))
plt.title("Kalman Filter - Velocity")
plt.ylabel('ẋ', rotation=90)
plt.xlabel('t')
plt.show()
Related
Im trying to solve 3d regression of inverse kinematics using ML I keep getting the following error:
This is my code:
import math
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neural_network import MLPRegressor
from mpl_toolkits.mplot3d import Axes3D
def direct_kin_(joints, links, origin = [0, 0, 0]):
### implement the forward kinematics for a three joints planar manipulator
X = np.zeros(3)
Y = np.zeros(3)
Z = np.zeros(3)
X[0] = origin[0]
Y[0] = origin[0]
Z[0] = origin[0]
X[1] = X[0] + links[0] * np.cos(joints[1])*np.cos(joints[0])
Y[1] = Y[0] + links[0] * np.cos(joints[1])*np.sin(joints[0])
Z[1] = Z[0] + links[0] * np.sin(joints[1])
X[2] = X[1] + links[1] * np.cos(joints[1] + joints[2])*np.cos(joints[0])
Y[2] = Y[1] + links[1] * np.cos(joints[1] + joints[2])*np.sin(joints[0])
Z[2] = Z[1] + links[1] * np.sin(joints[1] + joints[2])
return [X, Y, Z] # return the coordinates of all link endpoints
class arm():
### the arm class contains all the methods for defining a three joints planar manipulator,
### and implement a neural network inverse kinematics solver for it
def __init__(self, links = [10, 10], origin = [0, 0, 0], init = [0, 0, 0]):
# class contructor, defining the basic attributes of the arm and initial configuration
self.link1 = links[0]
self.link2 = links[1]
self.x0 = origin[0]
self.y0 = origin[0]
self.z0 = origin[1]
self.joint0 = init[0]
self.joint1 = init[0]
self.joint2 = init[1]
self.direct_kin()
def direct_kin(self):
# this forward kinematic function calculate the Cartesian coordinates for the current joint configuration
[self.X, self.Y, self.Z] = direct_kin_([self.joint0, self.joint1, self.joint2], [self.link1, self.link2], [self.x0, self.y0, self.z0])
def plot_arm(self):
# 2D plot of the current arm configuration
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.set_xlim3d(-300, 300)
ax.set_ylim3d(-300, 300)
ax.set_zlim3d(-300, 300)
ax.set_xlabel("X-axis")
ax.set_ylabel("Y-axis")
ax.set_zlabel("Z-axis")
plt.plot(self.X, self.Y, self.Z, linewidth=2.0)
plt.plot(self.X, self.Y, self.Z, 'ro', linewidth=2.0)
sum_links = (self.link1 + self.link2) * 1.1
plt.axis([-sum_links, sum_links, -1, sum_links])
plt.axis('equal')
plt.show()
def create_data(self, ann, n_train, n_test):
# prepare the training and test sets for the neural network solver
self.inv_solver = ann
n_data = n_train + n_test
joint_space = np.hstack((np.random.uniform(low=0, high=np.pi/2, size=(n_data, 1)), np.random.uniform(low=0, high=np.pi, size=(n_data,1))))
cartesian_space = np.zeros(np.shape(joint_space))
for i in range(len(joint_space)):
ax, ay, az = direct_kin_(joint_space[i], [self.link1, self.link2])
cartesian_space[i] = [ax[2], ay[2], az[2]]
self.X_train = np.asarray(cartesian_space[:n_train,:])
self.Y_train = np.asarray(joint_space[:n_train,:])
self.Z_train = np.asarray(joint_space[:n_train,:])
self.X_test = np.asarray(cartesian_space[n_train:,:])
self.Y_test = np.asarray(joint_space[n_train:,:])
self.Z_test = np.asarray(joint_space[n_train:,:])
def train_inv_kin(self):
# train the kinematic solver
self.inv_solver.fit(self.X_train, self.Y_train, self.Z_train)
score = self.inv_solver.score(self.X_train, self.Y_train, self.Z_train)
print('average training accuracy: ', np.mean(score))
def test_inv_kin(self):
# test the kinematic solver
score = self.inv_solver.score(self.X_test, self.Y_test, self.Z_test)
print('average test accuracy: ', np.mean(score))
def inv_kin(self, Cartesian):
# query the trained inverse kinematic solver on a single Cartesian target
#c_array = np.array(Cartesian).reshape(1,-1)
joints = self.inv_solver.predict([Cartesian])
[self.joint0, self.joint1, self.joint2] = joints[0]
self.direct_kin()
err = np.sqrt((Cartesian[0]-self.X[2])**2+(Cartesian[1]-self.Y[2])**2+(Cartesian[0]-self.Z[2])**2)
return(err, [self.X[2], self.Y[2], self.Z[2]])
def deg2rad(degrees):
return degrees*np.pi/180
a = arm(init = [deg2rad(45), deg2rad(90)])
a.plot_arm()
print(a.X)
print(a.Y)
print(a.Z)
[0.0000000e+00 5.0000000e+00 8.8817842e-16]
[0.0000000e+00 5.0000000e+00 8.8817842e-16]
[ 0. 7.07106781 14.14213562]
a = arm()
ann = MLPRegressor(max_iter = 1000, hidden_layer_sizes=(20,20))
n_train = 1000
n_test = 100
# How do create pairs of inputs and output to feed to the network for training?
# What value ranges should the inputs and outputs take?
a.create_data(ann, n_train, n_test)
a.train_inv_kin()
a.test_inv_kin()
THIS IS THE ERROR :
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
in ()
8 # What value ranges should the inputs and outputs take?
9
---> 10 a.create_data(ann, n_train, n_test)
11 a.train_inv_kin()
12 a.test_inv_kin()
<ipython-input-3-7eed1297591a> in create_data(self, ann, n_train, n_test)
47 cartesian_space = np.zeros(np.shape(joint_space))
48 for i in range(len(joint_space)):
---> 49 ax, ay, az = direct_kin_(joint_space[i], [self.link1, self.link2])
50 cartesian_space[i] = [ax[2], ay[2], az[2]]
51 self.X_train = np.asarray(cartesian_space[:n_train,:])
<ipython-input-2-b6a7e266108e> in direct_kin_(joints, links, origin)
13 Y[1] = Y[0] + links[0] * np.cos(joints[1])*np.sin(joints[0])
14 Z[1] = Z[0] + links[0] * np.sin(joints[1])
---> 15 X[2] = X[1] + links[1] * np.cos(joints[1] + joints[2])*np.cos(joints[0])
16 Y[2] = Y[1] + links[1] * np.cos(joints[1] + joints[2])*np.sin(joints[0])
17 Z[2] = Z[1] + links[1] * np.sin(joints[1] + joints[2])
IndexError: index 2 is out of bounds for axis 0 with size 2
ann.get_params()
tot_err = 0
for t in a.X_test:
print('\ntarget: ',t)
[inv_error, config] = a.inv_kin(t)
print('solution: ', config)
tot_err += inv_error
print('error: ', inv_error)
a.plot_arm()
plt.pause(2)
tot_err = tot_err/n_test
print('Average error: ',tot_err)
Here is my code. In the calculateOptimalLambda() function, I am attempting to declare a copy of n and
store it as m, remove one point from m, and make some calculations and a graph. Then, the loop should
restart, make a fresh copy of m, remove the next point, and so on.
However, when in the next iteration
of the loop, a point has been removed. Eventually, I run out of points to remove, and I get an error.
How do I declare a fresh copy of m so I can remove the next point?
import numpy as np
from matplotlib import pyplot as plt
class Data:
def __init__(self, points, sigma, lamda):
self.points = points
self.sigma = sigma
self.sample = np.random.uniform(-1,1, (points, 2))
self.transformedData = np.ones((points, 5))
self.weight = np.zeros((5,1))
self.lamda = lamda
def changeLamda(self,x):
self.lamda = x
def removePoint(self, x):
self.points = self.points - 1
self.sample = np.delete(self.sample, x, 0)
self.transformedData = np.delete(self.transformedData, x, 0)
def transformedFunction(self, x):
transformedData = np.ones((1, 5))
transformedData[0,1] = x
transformedData[0,2] = 0.5 * (3*x**2 -1)
transformedData[0,3]= 0.5 * (5*x**3 - 3*x)
transformedData[0,4] = 0.125 * (35*x**4 -30*x**2 + 3)
return np.dot(transformedData, self.weight)
def setY(self):
for i in range(len(self.sample[0:,0])):
self.sample[i,1] = np.random.normal(0, self.sigma) + self.sample[i,0]**2
def transform(self):
for i in range(len(self.sample[0:,0])):
self.transformedData[i,1] = self.sample[i,0]
self.transformedData[i,2] = 0.5 * (3*self.sample[i,0]**2 -1)
self.transformedData[i,3]= 0.5 * (5*self.sample[i,0]**3 - 3*self.sample[i,0])
self.transformedData[i,4] = 0.125 * (35*self.sample[i,0]**4 -30*self.sample[i,0]**2 + 3)
def calculateWeight(self):
z = n.transformedData
zProd = np.linalg.inv(np.matmul(np.transpose(z), z) + np.identity(5)*self.lamda)
next1 = np.matmul(zProd,np.transpose(z))
a = self.sample[0:,1]
a = a.reshape((-1, 1))
print(a)
self.weight = np.matmul(next1,a)
def calculateError(self):
error= (np.matmul(self.transformedData, self.weight) - self.sample[1,0:])
return error/self.points
def calculateOptimalLambda(n, L):
a = 0
for i in range(len(L)):
n.changeLamda(L[i])
for x in range(n.getPoints()):
a+=1
plt.subplot(4,5,a)
m = n
m.removePoint(x)
m.calculateWeight()
weight = m.getWeight()
error = m.calculateError()
twoD_plot(m)
print(error)
def twoD_plot(n):
t = np.linspace(-1, 1, 400)
x = np.square(t)
plt.plot(t,x,'b')
error = 0
y = x
for i in range(len(t)):
y[i] = n.transformedFunction(t[i])
error += (y[i] - t[i]**2)**2
"""print(error/len(t))"""
plt.plot(t,y,'r')
plt.scatter(n.getSample()[0:,0],n.getSample()[0:,1], c = 'g', marker = 'o')
n = Data(5,0.1,0)
n.setY()
n.transform()
n.calculateWeight()
L = [1, 0.01, 0.00001, 0]
calculateOptimalLambda(n, L)
plt.show()
I am trying to build a logistic regression model for a dataset consisting of two parameters
x1 and x2, but instead of analyzing just the two of them, I have added their squares as well - x12, x22 and x1· x2.
At the first glance everything looks fine and the error function is decreasing, but whilist drawing the plot of the decision boundary I have noticed, that after circa 500 iterations something strange happens to it.
Here is an animation of the error function as a function of iterations and a respective plot of the decision boundary:
Now,I interpret the decision boundary as a quadratic function
x2=f(x1), where
the relation between both parameters is given like this:
0.5 = θ0 + θ1x1 + θ2x2 + θ3x12 + θ4x1x2
+ θ5x22
Here is the python code I use to do everything:
#!/usr/bin/python3
import numpy as np
import matplotlib.pyplot as plt
from math import log
from matplotlib.animation import FuncAnimation
def sigmoid(x):
return 1.0 / (1.0 + np.exp(-x))
def loadData(filepath):
source=""
try:
f = open(filepath, "r")
source = f.read()
f.close()
except IOError:
print("Error while reading file (" + filepath + ")")
return ""
raw_data = source.split("\n")
raw_data = [x.split(",") for x in raw_data if x !=""]
raw_data = np.matrix(raw_data).astype(float)
return (raw_data[:,:np.size(raw_data,1)-1], raw_data[:,np.size(raw_data, 1)-1:])
def standardize(dataset, skipfirst=True):
means = np.amin(dataset, 0)
deviation = np.std(dataset, 0)
if skipfirst:
dataset[:,1:] -= means[:,1:]
dataset[:,1:] /= deviation[:,1:]
return dataset
else:
dataset -= means
dataset /= deviation
return dataset
def error(X, Y, Theta):
"Calculates error values"
v_sigm = np.vectorize(sigmoid)
h_x = X # Theta
sigmo = v_sigm(h_x)
partial_vect = (Y-1).T # np.log(1-sigmo) - Y.T # np.log(sigmo)
return 1/(2*np.size(Y, axis=0))*np.sum(partial_vect)
def gradientStep(X, Y, Theta, LR):
"Returns new theta Values"
v_sigm = np.vectorize(sigmoid)
h_x = X # Theta
modif = -1*LR/np.size(Y, 0)*(h_x-Y)
sums = np.sum(modif.T # X, axis = 0)
return Theta + sums.T
X, Y = loadData("ex2data1.txt")
#add bias to X
X = np.append(np.ones((np.size(X, 0), 1)), X, axis=1)
added_params = [[x[1]**2, x[1]*x[2], x[2]**2] for x in np.array(X)]
X = np.append(X, np.matrix(added_params), axis=1)
#standardize X
X = standardize(X)
#create vector of parameters
Theta=np.zeros((np.size(X, 1), 1))
iterations = 3000
Theta_vals = []
Error_vals = []
for i in range(0, iterations):
Theta_vals.append(np.asarray(Theta).flatten())
Error_vals.append(error(X, Y, Theta))
Theta = gradientStep(X, Y, Theta, 0.07)
#CALCULATING FINISHES HERE
#plot data:
fig = plt.figure()
def_ax = fig.add_subplot(211)
def_ax.set_xlim(np.amin(X[:,1:2]), np.amax(X[:,1:2]))
def_ax.set_ylim(np.amin(X[:,2:3]), np.amax(X[:,2:3]))
err_ax = fig.add_subplot(212)
err_ax.set_ylim(0, error(X, Y, Theta))
err_ax.set_xlim(0, iterations)
positive_X1 = []
positive_X2 = []
negative_X1 = []
negative_X2 = []
for i in range(0, np.size(Y, 0)):
if(Y[i, 0] == 1):
positive_X1.append(X[i, 1])
positive_X2.append(X[i, 2])
else:
negative_X1.append(X[i, 1])
negative_X2.append(X[i, 2])
err_ax.set_ylim(np.amin(Error_vals), np.amax(Error_vals))
def animation(frame):
global Theta_vals, Error_vals, def_ax, err_ax, positive_X1, positive_X2, negative_X1, negative_X2
def_limX = def_ax.get_xlim()
def_limY = def_ax.get_ylim()
err_limX = err_ax.get_xlim()
err_limY = err_ax.get_ylim()
def_ax.clear()
err_ax.clear()
def_ax.set_xlim(def_limX)
def_ax.set_ylim(def_limY)
err_ax.set_xlim(err_limX)
err_ax.set_ylim(err_limY)
def_ax.scatter(positive_X1, positive_X2, marker="^")
def_ax.scatter(negative_X1, negative_X2, marker="o")
Theta = Theta_vals[frame]
res_x = np.linspace(*def_ax.get_xlim(), num=5)
delta_x = [(Theta[4]*x+Theta[2])**2-4*Theta[5]*(Theta[3]*x**2+Theta[1]*x+Theta[0]-0.5) for x in res_x]
delta_x = [np.sqrt(x) if x >= 0 else 0 for x in delta_x]
minb = [-(Theta[4]*x+Theta[2]) for x in res_x]
res_1 = []
res_2 = []
for i in range(0, len(res_x)):
if Theta[5] == 0:
res_1.append(0)
res_2.append(0)
else:
res_1.append((minb[i]+delta_x[i])/(2*Theta[5]))
res_2.append((minb[i]-+delta_x[i])/(2*Theta[5]))
def_ax.plot(res_x, res_1)
def_ax.plot(res_x, res_2)
err_x = np.linspace(0, frame, frame)
err_y = Error_vals[0:frame]
err_ax.plot(err_x, err_y)
anim = FuncAnimation(fig, animation, frames=iterations, interval=3, repeat_delay=2000)
print(error(X, Y, Theta))
anim.save("anim.mp4")
What could be the reason of such a strange behaviour?
So the purpose of my code is to use inputted data points to give a gaussian plot distribution. I figured out how to make it work with a double gaussian but I'm having a lot of trouble adding a third. Im not quite sure what I'm doing wrong. 1 of the errors I keep getting is an Index Error saying that the list index is out of range. I would appreciate any help with this.
Heres my code:
from pylab import *
import numpy as np
from numpy import loadtxt
from scipy.optimize import leastsq
from scipy.optimize import least_squares
from scipy.stats import iqr
import math
import matplotlib.pyplot as plt
import sys
matplotlib.rcParams['mathtext.default'] = 'regular'
fitfunc_triple = lambda p, x: np.abs(p[0]) * exp(-0.5 * ((x - p[1]) / p[2]) ** 2) + np.abs(p[3]) * exp(
-0.5 * ((x - p[4]) / p[5]) ** 2) + np.abs(p[6]) * exp(-0.5 * ((x - p[7])/ p[8] **2 ))
fitfunc_double = lambda p, x: np.abs(p[0]) * exp(-0.5 * ((x - p[1]) / p[2]) ** 2) + np.abs(p[3]) * exp(
-0.5 * ((x - p[4]) / p[5]) ** 2)
fitfunc_single = lambda p, x: np.abs(p[0]) * exp(-0.5 * ((x - p[1]) / p[2]) ** 2)
errfunc = lambda p, x, y: (y - fitfunc(p, x))
dataR = np.loadtxt("/Users/Safi/Library/Preferences/PyCharmCE2018.1/scratches/rspecial1385.a2261.dat5", skiprows=0)
RA = dataR[:, 0]
DEC = dataR[:, 1]
VELR = dataR[:, 2]
REDSH = dataR[:, 3]
RADD = dataR[:, 4]
sl = 3E5
zbar = np.mean(REDSH)
vc = zbar * sl
VEL = vc + sl * ((REDSH - zbar) / (1 + zbar))
wdith = 200
iters = 10
sig2 = 500
binN = int(math.ceil((np.max(VEL) - np.min(VEL)) / wdith))
sys.stdout = open(str(wdith) + "_1sigma_" + str(iters) + "_sig2_" + str(sig2) + ".txt", "w")
plt.figure(1)
y, x, _ = plt.hist(VEL, binN, alpha=0.5, label='data')
x = (x[1:] + x[:-1]) / 2 # for len(x)==len(y)
data = np.vstack((x, y)).T
xdata = data[:, 0]
ydata = data[:, 1]
yerr = ydata ** 0.5
init = [10, 69500, 1200, 5, 68000, sig2]
bds = ([0, 66000, 800, 0, 66000, sig2], [50, 70000, 1750, 20, 70000, sig2 + 0.01])
def index_outlier(data):
inter_quart = iqr(data) * 1.5
bd2 = np.percentile(data, 75) + inter_quart
bd1 = np.percentile(data, 25) - inter_quart
index = []
for i in [i for i, x in enumerate(data) if x < bd1 or x > bd2]:
index.append(i)
return (index)
#### Bootstrapping Estimation Function ####
def fit_bootstrap(fitfunc, datax, datay, init, bds, sigma, iterations=iters):
errfunc = lambda p, x, y: (y - fitfunc(p, x))
# Fit first time
pfit = least_squares(errfunc, init, bounds=bds, args=(datax, datay), max_nfev=10000)
model = fitfunc(pfit.x, datax)
residuals = pfit.fun
# Random data sets are generated and fitted
ps = []
for i in range(iterations):
randomdataY = []
for k in range(len(sigma)):
randomDelta = np.random.normal(0., sigma[k], 1)
randomdataY.append(datay[k] + randomDelta)
out = np.concatenate(randomdataY)
randomfit = least_squares(errfunc, init, bounds=bds, args=(datax, out))
ps.append(randomfit.x)
# Removing outliers
# Finding outliers and indexing them
master_list = []
indexed = []
for k in range(len(ps[0])): # 0-6
it = []
for i in range(len(ps)): # 0-1000
it.append(ps[i][k])
master_list.append(it)
# indexed.append(index_outlier(master_list[k]))
# # List of outlier indicies
# flat_list=[item for sublist in indexed for item in sublist]
# no_dups= list(set(flat_list))
# # Removing bad fits
# for k in range(len(master_list)):
# for i in sorted(no_dups,reverse=True):
# del master_list[k][i]
pfit_bootstrap = []
perr_bootstrap = []
for i in master_list:
pfit_bootstrap.append(np.median(i))
perr_pos = np.round(np.percentile(i, 84) - np.median(i), 4)
perr_neg = np.round(np.median(i) - np.percentile(i, 16), 4)
perr_bootstrap.append(str('[+') + str(perr_pos) + str(',-') + str(perr_neg) + str(']'))
return (pfit_bootstrap, perr_bootstrap, residuals, pfit.nfev, master_list)
pfit, perr, residuals, nfev, master_list = fit_bootstrap(fitfunc_double, xdata, ydata, init, bds, yerr)
pfit1, perr1, residuals1, nfev1, master_list1 = fit_bootstrap(fitfunc_single, xdata, ydata, init, bds, yerr)
more_data = np.linspace(np.min(xdata), np.max(xdata), 1000)
real_func = fitfunc_double(pfit, more_data)
real_func1 = fitfunc_single(pfit1, more_data)
######## Saving Coefficients #########
A1 = pfit[0]
m1 = pfit[1]
s1 = pfit[2]
A2 = pfit[3]
m2 = pfit[4]
s2 = pfit[5]
A3 = pfit[6]
m3 = pfit[7]
s3 = pfit[8]
pecp = VEL - vc
m1p = m1 - vc
m2p = m2 - vc
m3p = m3 - vc
xdatap = xdata - vc
plt.figure(6)
plt.hist(pecp, binN, alpha=.5, label='data', color='skyblue')
xhmax = np.amax(pecp + 1500)
xhmin = np.amin(pecp - 1500)
xh = np.linspace(xhmin, xhmax, 50)
# yh1=(mlab.normpdf(xh, c[1], c[2]))
yh1 = np.abs(A1) * exp(-0.5 * (((xh - m1p) / (s1)) ** 2))
yh2 = np.abs(A2) * exp(-0.5 * (((xh - m2p) / (s2)) ** 2))
yh3 = np.abs(A3) * exp(-0.5 * (((xh - m3p) / (s3)) ** 2))
plt.plot(xh, yh1, color='b', linewidth=2)
plt.plot(xh, yh2, color='r', linewidth=2)
plt.plot(xh, yh3, color='g', linewidth=2)
plt.plot(xh, yh1 + yh2 + yh3, color='purple', linewidth=3)
# plt.errorbar(xdatap,y,xerr=wdith/2,ls='none', yerr=yerr,color='k',linewidth=2)
# plt.plot(xdatap, ydata,'.',color='k')
plt.ylim(0, np.max(ydata) + 2)
plt.xlabel('Peculiar Velocity (km/s)')
plt.ylabel('N$_{gal}$')
plt.text(-4800, 15, '$\mu_{2}$-$\mu_{1}$ = ' + str(int(m2 - m1)) + ' km/s')
plt.savefig(str(wdith) + "_1sigma_" + str(iters) + "_sig2_" + str(sig2) + "_hist.ps")
divi = -1800
memlow = np.array([[0 for x in range(2)] for y in range(1)])
memhigh = np.array([[0 for x in range(2)] for y in range(1)])
j = 0
k = 0
plt.show()
With the code below, I'm attempting to implement the Levy-Khintchine formula (https://en.wikipedia.org/wiki/L%C3%A9vy_process#L.C3.A9vy.E2.80.93Khintchine_representation). In the limit of no jumps, the Levy-Khitchine formula reduces to the multivariate normal distribution. My code uses the (multi-dimensional) trapeziodal integration rule (http://mathfaculty.fullerton.edu/mathews/n2003/SimpsonsRule2DMod.html) to approximate the Fourier transform of the characteristic function as a discrete Fourier transform. For the 1-dimensional case, the code works perfectly. For the 2-D case, I can't find what I'm doing wrong.
Does anyone have example numpy.fftn code that correctly implements multivariate_normal pdf?
class LevyKhintchine:
def __init__(self, mean, cov, jump_measure):
self.mean = mean
self.cov = cov
self.jump_measure = jump_measure
self.factors = mean.shape[0]
def logCF(self, k):
rolled = Roll(k)
out = np.empty(Shape(k))
return (self.jump_measure(k) -
Dot(rolled, self.cov, rolled, out)*0.5 +
np.sum(np.multiply(Roll(k), self.mean), axis=-1)*1j)
def pdf_grid(self, J):
diag = np.diagonal(self.cov)
tmp = np.pi*2/J
dk = np.sqrt(tmp/diag)
dx = np.sqrt(tmp*diag)
k = Grid(np.zeros(self.factors), dk, J)
x0 = self.mean - dx*J*0.5
f = np.exp(self.logCF(k) - Coef(dk, x0, J)*1j)
for n in range(self.factors):
f[ 0] *= 0.5
f[-1] *= 0.5
f = np.rollaxis(f, 0, factors)
pdf = np.fft.fftn(f)
return Grid(x0, dx, J), pdf.real*(np.product(dk)/np.pi)
def Grid(left, width, J):
def Slice(slices, j):
slices.append(slice(left[j], left[j] + width[j]*(J-1), 1j*J))
return slices
slices = reduce(Slice, range(len(left)), [])
return np.mgrid[slices]
def Shape(grid):
return np.asarray(grid).shape[1:]
def Roll(grid):
grid = np.asarray(grid)
try:
rolled = np.rollaxis(grid, 0, len(grid)+1)
except ValueError:
rolled = grid
return rolled
def Dot(x, cov, y, out): #x & y are "rolled"
for j in np.ndindex(out.shape):
out[j] = np.dot(x[j].T, np.dot(cov, y[j]))
return out
def Coef(dks, x0s, J):
factors = len(dks)
coef = np.zeros((J,)*factors)
for n, (dk, x0) in enumerate(zip(dks, x0s)):
shape = np.ones(factors, dtype=int)
shape[n] = J
coef += np.arange(J).reshape(shape)*(dk*x0)
return coef
Here's the tests:
from scipy.stats import multivariate_normal
J = 64
factors = 1
mean = np.full((factors,), -1)
cov = np.identity(factors)
rv = LevyKhintchine(mean, cov, lambda k: 0)
rv0 = multivariate_normal(mean, cov)
x, pdf = rv.pdf_grid(J)
plt.plot(x[0], pdf, x[0], rv0.pdf(Roll(x)))
factors = 2
mean = np.full((factors,), 5)
cov = np.identity(factors)
rv = LevyKhintchine(mean, cov, lambda k: 0)
x, pdf = rv.pdf_grid(J)
rv0 = multivariate_normal(mean, cov)
fig2 = plt.figure()
ax2 = fig2.add_subplot(111)
ax2.contourf(x[0], x[1], pdf)
fig3 = plt.figure()
ax3 = fig3.add_subplot(111)
ax3.contourf(x[0], x[1], rv0.pdf(Roll(x)))
I figured it out: in 1-d I can get away with integrating over only positive wave numbers k, in higher dimensions I cannot.
Here's the corrected code:
class LevyKhintchine:
def __init__(self, mean, cov, jump_measure):
self.mean = mean
self.cov = cov
self.jump_measure = jump_measure
self.factors = mean.shape[0]
def logCF(self, k):
rolled = Roll(k)
out = np.empty(Shape(k))
return (self.jump_measure(k) -
Dot(rolled, self.cov, rolled, out)*0.5 +
np.sum(np.multiply(Roll(k), self.mean), axis=-1)*1j)
def pdf_grid(self, J):
diag = np.diagonal(self.cov)
tmp = np.pi*2/J
dk = np.sqrt(tmp/diag)
dx = np.sqrt(tmp*diag)
k0 = -0.5*dk*J
x0 = -0.5*dx*J + self.mean
k = Grid(k0, dk, J)
x = Grid(x0, dx, J)
f = np.exp(-1j*Coef(dk, x0, J) + self.logCF(k))
for n in range(self.factors):
f[ 0] *= 0.5
f[-1] *= 0.5
f = np.rollaxis(f, 0, factors)
c = ((0.5/np.pi)**self.factors*np.product(dk)*np.exp(-1j*np.dot(k0, x0)))
pdf = np.fft.fftn(f)*np.exp(-1j*Coef(k0, dx, J))*c
return x, pdf.real
def Grid(left, width, J):
def Slice(slices, j):
slices.append(slice(left[j], left[j] + width[j]*(J-1), 1j*J))
return slices
slices = reduce(Slice, range(len(left)), [])
return np.mgrid[slices]
def Shape(grid):
return np.asarray(grid).shape[1:]
def Roll(grid):
grid = np.asarray(grid)
try:
rolled = np.rollaxis(grid, 0, len(grid)+1)
except ValueError:
rolled = grid
return rolled
def Dot(x, cov, y, out): #x & y are "rolled"
for j in np.ndindex(out.shape):
out[j] = np.dot(x[j].T, np.dot(cov, y[j]))
return out
def Coef(dks, x0s, J):
factors = len(dks)
coef = np.zeros((J,)*factors)
for n, (dk, x0) in enumerate(zip(dks, x0s)):
shape = np.ones(factors, dtype=int)
shape[n] = J
coef += np.arange(J).reshape(shape)*(dk*x0)
return coef
Here's the tests:
from scipy.stats import multivariate_normal
J = 32
for factors in range(1, 4):
mean = np.full((factors,), -1)
cov = np.identity(factors)
rv = LevyKhintchine(mean, cov, lambda k: 0)
rv0 = multivariate_normal(mean, cov)
x, pdf = rv.pdf_grid(J)
pdf0 = rv0.pdf(Roll(x))
print np.allclose(pdf, pdf0)
True
True
True