Elementwise updates of shared matrix in Theano - theano

I am trying to calculate the gradient of the energy function, E( phi, theta, psi), where phi, theta, psi are Euler angles around Z, Y and X axis respectively.
R is a rotation matrix converted from Euler angles.
Where the columns are rotation vectors.
For a point cloud of a indoor room, I have normals N for each point in the point cloud.
N has shape of (numPoints x 3)
Now E = sum(1-max(N.dot(R))
I would like to find the gradient of E with respect to Euler angles.
To begin with the problem I am trying to calculate rotation matrix R from Euler angles using Theano.
Please find the code below.
import theano
import theano.tensor as T
import numpy as np
phi = theano.shared(value=np.pi/3, name='phi')
theta = theano.shared(value=np.pi/3, name='theta')
psi = theano.shared(value=np.pi/3, name='psi')
# phi = T.dscalar(name='phi')
# theta = T.dscalar(name='theta')
# psi = T.dscalar(name='psi')
R = theano.shared(value=np.zeros([3, 3]), name='R')
R00 = T.set_subtensor(R[0, 0], T.cos(theta)*T.cos(phi))
R10 = T.set_subtensor(R[1, 0], T.cos(theta)*T.sin(phi))
R20 = T.set_subtensor(R[2, 0], -T.sin(theta))
R01 = T.set_subtensor(R[0, 1], T.sin(psi)*T.sin(theta)*T.cos(phi) - T.cos(psi)*T.sin(phi))
R11 = T.set_subtensor(R[1, 1], T.sin(psi)*T.sin(theta)*T.sin(phi) + T.cos(psi)*T.cos(phi))
R21 = T.set_subtensor(R[2, 1], T.sin(psi)*T.cos(theta))
R02 = T.set_subtensor(R[0, 2], T.cos(psi)*T.sin(theta)*T.cos(phi) + T.sin(psi)*T.sin(phi))
R12 = T.set_subtensor(R[1, 2], T.cos(psi)*T.sin(theta)*T.sin(phi) - T.sin(psi)*T.cos(phi))
R22 = T.set_subtensor(R[2, 2], T.cos(psi)*T.cos(theta))
f = theano.function([phi, theta, psi], updates=[(R, R00, R10, R20, R01, R11, R21, R02, R12, R22)])
theano.printing.pydotprint(f, outfile="./test.png", var_with_name_simple=True)
But this gives me error at two different stage,
Traceback (most recent call last):
File "/theanotest.py", line 38, in <module>
f = theano.function([phi, theta, psi], updates=[(R, R00, R10, R20, R01, R11, R21, R02, R12, R22)])
File "/usr/local/lib/python2.7/dist-packages/theano/compile/function.py", line 266, in function
profile=profile)
File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line 489, in pfunc
no_default_updates=no_default_updates)
File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line 186, in rebuild_collect_shared
' variable via the `givens` parameter') % v)
TypeError: Cannot use a shared variable (phi) as explicit input. Consider substituting a non-shared variable via the `givens` parameter
If I chage the Eurler angles to scalar values I get error as below
Traceback (most recent call last):
File "/theanotest.py", line 38, in <module>
f = theano.function([phi, theta, psi], updates=[(R, R00, R10, R20, R01, R11, R21, R02, R12, R22)])
File "/usr/local/lib/python2.7/dist-packages/theano/compile/function.py", line 266, in function
profile=profile)
File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line 489, in pfunc
no_default_updates=no_default_updates)
File "/usr/local/lib/python2.7/dist-packages/theano/compile/pfunc.py", line 191, in rebuild_collect_shared
for (store_into, update_val) in iter_over_pairs(updates):
ValueError: too many values to unpack
Can anyone please help me with this problem?

The first error is exactly as the message indicates: you can't supply shared variables as inputs to Theano functions. Either use shared variables with no input parameters or regular tensors as input parameters.
The second error is due to incorrect updates. Updates should be a list of pairs. Each pair should consist of the shared variable to be updated and a symbolic expression describing how the update should be computed.
In this case the update might be computed like this (untested):
Rnew = T.set_subtensor(R[0, 0], T.cos(theta)*T.cos(phi))
Rnew = T.set_subtensor(Rnew[1, 0], T.cos(theta)*T.sin(phi))
Rnew = T.set_subtensor(Rnew[2, 0], -T.sin(theta))
Rnew = T.set_subtensor(Rnew[0, 1], T.sin(psi)*T.sin(theta)*T.cos(phi) - T.cos(psi)*T.sin(phi))
Rnew = T.set_subtensor(Rnew[1, 1], T.sin(psi)*T.sin(theta)*T.sin(phi) + T.cos(psi)*T.cos(phi))
Rnew = T.set_subtensor(Rnew[2, 1], T.sin(psi)*T.cos(theta))
Rnew = T.set_subtensor(Rnew[0, 2], T.cos(psi)*T.sin(theta)*T.cos(phi) + T.sin(psi)*T.sin(phi))
Rnew = T.set_subtensor(Rnew[1, 2], T.cos(psi)*T.sin(theta)*T.sin(phi) - T.sin(psi)*T.cos(phi))
Rnew = T.set_subtensor(Rnew[2, 2], T.cos(psi)*T.cos(theta))
f = theano.function([phi, theta, psi], updates=[(R, Rnew)])

Related

Adapting initial-value problem to boundary-value problem using scipy.integrate.solve_bvp?

I would like to adapt an initial-value-problem (IVP) to a boundary-value-problem (BVP) using scipy.integrate.solve_bvp. A similar question was asked here, but I do not follow everything explained in the answer. The example below regarding the SIR model was taken from this website. Here, the initial condition y0 is taken to be the initial value of S, I, and R at time x0[0]. This system of ODEs is given by the function SIR below, which returns [dS/dt, dI/dt, dR/dt] over the interval from x[0] to x[-1].
import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import solve_ivp, solve_bvp
def SIR(t, y, prms):
S = y[0]
I = y[1]
R = y[2]
beta, gamma = prms
# return [dS/dt, dI/dt, dR/dt]
return np.array([-beta * S * I, beta * S * I - gamma * I, gamma * I])
infected = np.array([1, 3, 6, 25, 73, 222, 294, 258, 237, 191, 125, 69, 27, 11, 4])
xt = np.arange(infected.size).astype(int)
xw = 0.2 # spacing between points on x-axis (elapsed time)
t_eval = np.arange(xt[0], xt[-1]+xw, xw)
x0 = [xt[0], xt[-1]]
y0 = [762, 1, 0] # S0, I0, R0, beginning of outbreak
N = sum(y0) # population total
prms = [0.01,0.1] # beta, gamma
sol = solve_ivp(SIR, x0, y0, method='LSODA', t_eval=t_eval, args=(prms,))
fig, ax = plt.subplots()
ax.plot(sol.t, sol.y[0], label='S')
ax.plot(sol.t, sol.y[1], label='I')
ax.plot(sol.t, sol.y[2], label='R')
ax.plot(xt, infected, label='OG data')
ax.grid(color='k', linestyle=':', alpha=0.3)
fig.legend(loc='lower center', ncol=4, mode='expand')
plt.show()
plt.close(fig)
As a sanity-check, running the code above produces the figure below:
Now, suppose I would like to add another boundary condition - say x1 and y1 - to be evaluated at x0[-1].
y0 = [0, 200, N-200] # S1, I1, R1, end of graph of outbreak; values from eye-ing the graph # N-200 \approx 550
From the documentation of solve_bvp, it appears that bc must be callable boundary conditions. The other parameters of solve_ivp and solve_bvp also appear different. How can I use this toy-example to solve a BVP in this way?

How to identify if the centroid point touches a line or not?

I am working with an intrusion detection algorithm which works on the basis of line crossing detection. I have developed a basic algorithm using the equation y = mx+c, but it is showing some wrong detection when the person reaches nearer to the line. I need some suggestion for making it a perfect line touching algorithm.
If your line has starting and ending points [x1, y1] and [x2, y2], then the line equation is:
y - y1 = m * (x - x1), where m = (y2 - y1)/(x2-x1)
Then you can check if a point belongs to the line or not, substituting either x or y, and checking if the other matches the line equation.
In Pyhton:
# the two points that define the line
p1 = [1, 6]
p2 = [3, 2]
# extract x's and y's, just for an easy code reading
x1, y1 = p1
x2, y2 = p2
m = (y2-y1)/(x2-x1)
# your centroid
centroid = [2,4]
x3, y3 = centroid
# check if centroid belongs to the line
if (m * (x3-x1) + y1) == y3:
print("Centroid belongs to line")
But probably...
...you'll have better results calculating the distance between red dot and the line (distance from a point to a line), and then checking if it is near enough (i.e. distance less than some value).
In Python:
# points that define the line
p1 = [1, 6]
p2 = [3, 2]
x1, y1 = p1
x2, y2 = p2
centroid = [2,4]
x3, y3 = centroid
# distance from centroid to line
import math # to calculate square root
dist = abs((y2-y1)*x3 - (x2-x1)*y3 + x2*y1 - y2*x1)/math.sqrt((y2-y1)**2 + (x2-x1)**2)
if dist < some_value:
print("Near enough")
Let the line go from point l0 to point l1. Then let the centroid be point p1. Let the vector l be the vector from l0 to l1 and p from l0 to p1. Then you can find the distance from the point p1 to the line using dot product as described here.
You probably want to find the distance from your point to the line segment and then evaluate if the point is on the line segment based on that distance. This can be done in a similar fashion but with more logic around it, as described here.
An implementation in python using numpy is given below. It can easily be extended to handle N centroids, enabling you to track different objects in parallel. It works by projecting the point onto the line segment and finding the distance from this point to the centroid.
import numpy as np
def distance_from_line_segment_points_to_point(l0, l1, p1):
l0 = np.array(l0)
l1 = np.array(l1)
p1 = np.array(p1)
l_vec = l1 - l0
p_vec = p1 - l0
if (l0 == l1).all():
return np.linalg.norm(p_vec)
l_norm = np.linalg.norm(l_vec)
l_unit = l_vec / l_norm
t = np.dot(l_unit, p_vec)
if t >= l_norm:
p_proj = l1
elif t <= 0:
p_proj = l0
else:
p_proj = l0 + t * l_unit
return np.linalg.norm(p1 - p_proj)
print(distance_from_line_segment_points_to_point([0, 0], [0, 0], [1, 1])) # sqrt(2), 1.4
print(distance_from_line_segment_points_to_point([0, 0], [1, 0], [1, 1])) # 1
print(distance_from_line_segment_points_to_point([0, 0], [1, 1], [0, 1])) # sqrt(2)/2, 0.707

Issue when trying to plot after applying PCA on a dataset

I am trying to plot the results of PCA of the dataset pima-indians-diabetes.csv. My code shows a problem only in the plotting piece:
import numpy
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import pandas as pd
# Dataset Description:
# 1. Number of times pregnant
# 2. Plasma glucose concentration a 2 hours in an oral glucose tolerance test
# 3. Diastolic blood pressure (mm Hg)
# 4. Triceps skin fold thickness (mm)
# 5. 2-Hour serum insulin (mu U/ml)
# 6. Body mass index (weight in kg/(height in m)^2)
# 7. Diabetes pedigree function
# 8. Age (years)
# 9. Class variable (0 or 1)
path = 'pima-indians-diabetes.data.csv'
dataset = numpy.loadtxt(path, delimiter=",")
X = dataset[:,0:8]
Y = dataset[:,8]
features = ['1','2','3','4','5','6','7','8','9']
df = pd.read_csv(path, names=features)
x = df.loc[:, features].values # Separating out the values
y = df.loc[:,['9']].values # Separating out the target
x = StandardScaler().fit_transform(x) # Standardizing the features
pca = PCA(n_components=2)
principalComponents = pca.fit_transform(x)
# principalDf = pd.DataFrame(data=principalComponents, columns=['pca1', 'pca2'])
# finalDf = pd.concat([principalDf, df[['9']]], axis = 1)
plt.figure()
colors = ['navy', 'turquoise', 'darkorange']
lw = 2
for color, i, target_name in zip(colors, [0, 1, 2], ['Negative', 'Positive']):
plt.scatter(principalComponents[y == i, 0], principalComponents[y == i, 1], color=color, alpha=.8, lw=lw,
label=target_name)
plt.legend(loc='best', shadow=False, scatterpoints=1)
plt.title('PCA of pima-indians-diabetes Dataset')
The error is located at the following line:
Traceback (most recent call last):
File "test.py", line 53, in <module>
plt.scatter(principalComponents[y == i, 0], principalComponents[y == i, 1], color=color, alpha=.8, lw=lw,
IndexError: too many indices for array
Kindly, how to fix this?
As the error indicates some kind of shape/dimension mismatch, a good starting point is to check the shapes of the arrays involved in the operation:
principalComponents.shape
yields
(768, 2)
while
(y==i).shape
(768, 1)
Which leads to a shape mismatch when trying to run
principalComponents[y==i, 0]
as the first array is already multidimensional, therefore the error is indicating that you used too many indices for the array.
You can fix this by forcing the shape of y==i to a 1D array ((768,)), e.g. by changing your call to scatter to
plt.scatter(principalComponents[(y == i).reshape(-1), 0],
principalComponents[(y == i).reshape(-1), 1],
color=color, alpha=.8, lw=lw, label=target_name)
which then creates the plot for me
For more information on the difference between arrays of the shape (R, 1)and (R,) this question on StackOverflow provides a nice starting point.

Constructing a multivariate Normal distribution with probabilistic parameters in PyMC3

I want to construct a multivariate Normal model in PyMC3 in which the mean value and precision matrix involve probabilistic variables. h is meant to act as a latent variable in an larger project to which this code snippet belongs.
When I run the code provided below, I get the error message shown, and I'm not sure exactly how to interpret it. As far as I can see, the dimension of the mean value of the MvNormal (2-row column vector) match the dimension of the precision matrix B (2 x 2 matrix), so I don't expect it's the dimensions of these objects that are causing the problem. I don't know what other variables could be causing some error related to dimensions to be thrown up though. Can anyone shed some light on this please?
Here is the code:
import pymc3 as pm
import theano.tensor as tt
with pm.Model() as model:
# A matrix
a1 = pm.Uniform('a1', 0., 1.)
a2 = pm.Uniform('a2', 0., 1.)
ix = ([0, 0, 1, 1], [0, 1, 0, 1])
A = tt.eye(2)
A = tt.set_subtensor(A[ix], [a1, a2, 1, 0])
# B matrix
b1 = pm.Uniform('b1', 0., 1.)
b2 = pm.Uniform('b2', 0., 1.)
ix = ([0, 1], [0, 1])
B = tt.eye(2)
B = tt.set_subtensor(B[ix], [b1 ** 2, b2 ** 2])
# Model
y0 = pm.Normal('y0', mu=0., sd=1., observed=0)
y1 = pm.Normal('y1', mu=1., sd=1., observed=1)
s_v = tt.stack([y1, y0]).T
h = pm.MvNormal("h", mu=pm.math.dot(A, s_v), tau=B)
Error message:
h = pm.MvNormal("h", mu=pm.math.dot(A, s_v), tau=B)
File "/Users/Joel/PycharmProjects/AR(2)/venv/lib/python3.6/site-packages/pymc3/distributions/distribution.py", line 42, in __new__
return model.Var(name, dist, data, total_size)
File "/Users/Joel/PycharmProjects/AR(2)/venv/lib/python3.6/site-packages/pymc3/model.py", line 809, in Var
total_size=total_size, model=self)
File "/Users/Joel/PycharmProjects/AR(2)/venv/lib/python3.6/site-packages/pymc3/model.py", line 1209, in __init__
self.logp_elemwiset = distribution.logp(self)
File "/Users/Joel/PycharmProjects/AR(2)/venv/lib/python3.6/site-packages/pymc3/distributions/multivariate.py", line 274, in logp
quaddist, logdet, ok = self._quaddist(value)
File "/Users/Joel/PycharmProjects/AR(2)/venv/lib/python3.6/site-packages/pymc3/distributions/multivariate.py", line 85, in _quaddist
raise ValueError('Invalid dimension for value: %s' % value.ndim)
ValueError: Invalid dimension for value: 0```
I believe that you are missing the "shape" argument in the pm.MvNormal call, which lets it handle the right size of values. For example, if you have 7 variables, set shape=7.

ValueError: Number of features of the model must match the input. Model n_features is 45 and input n_features is 2

I'm trying to plot a Random Forest visualization for classification purposes with python 3.
Firstly, I read a CSV file where all necesary data is located. Here, Read_CSV() is a method who run correctly, giving three variables, features (vector with all feature names, specifically 45), data (only the data without label column. There are 148000 rows and 45 columns), labels (column of labels in integer format. There are 3 classes to classify as integers 0, 1 or 2. There are also 148000 rows in this vector).
features,data,labels = Read_CSV()
X_train,X_test,Y_train,Y_test = train_test_split(data,labels,test_size=0.35,random_state=0)
X = np.array(X).astype(np.float)
y = np.array(y).astype(np.float)
ax = ax or plt.gca()
ax.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=cmap,
clim=(y.min(), y.max()), zorder=3)
ax.axis('tight')
ax.axis('off')
xlim = ax.get_xlim()
ylim = ax.get_ylim()
# fit the estimator
model.fit(X, y)
xx, yy = np.meshgrid(np.linspace(*xlim, num=200),
np.linspace(*ylim, num=200))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
# Create a color plot with the results
n_classes = len(np.unique(y))
contours = ax.contourf(xx, yy, Z, alpha=0.3,
levels=np.arange(n_classes + 1) - 0.5,
cmap=cmap, clim=(y.min(), y.max()),
zorder=1)
ax.set(xlim=xlim, ylim=ylim)
This part of the code showed here is completely dedicated to obtain a plot like this:
enter image description here
When I run this code I obtain the following:
Traceback (most recent call last):
File "C:/Users/Carles/PycharmProjects/Article/main.py", line 441, in <module>
main()
File "C:/Users/Carles/PycharmProjects/Article/main.py", line 388, in main
visualize_classifier(RandomForestClassifier(),X_train, Y_train)
File "C:/Users/Carles/PycharmProjects/Article/main.py", line 353, in visualize_classifier
Z = model.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
File "C:\Users\Carles\PycharmProjects\Article\venv\lib\site-packages\sklearn\ensemble\forest.py", line 538, in predict
proba = self.predict_proba(X)
File "C:\Users\Carles\PycharmProjects\Article\venv\lib\site-packages\sklearn\ensemble\forest.py", line 578, in predict_proba
X = self._validate_X_predict(X)
File "C:\Users\Carles\PycharmProjects\Article\venv\lib\site-packages\sklearn\ensemble\forest.py", line 357, in _validate_X_predict
return self.estimators_[0]._validate_X_predict(X, check_input=True)
File "C:\Users\Carles\PycharmProjects\Article\venv\lib\site-packages\sklearn\tree\tree.py", line 384, in _validate_X_predict
% (self.n_features_, n_features))
ValueError: Number of features of the model must match the input. Model n_features is 45 and input n_features is 2

Resources