Sympy - Float has no attribute sqrt - python-3.x

I am working on a code snippet, where I am unable to debug the issue, any suggestions would be appreciated.
The error is attribute error: Float object has no attribute sqrt
from sympy import *
import numpy as np
rho_l = 1000;
rho_g= 1.225;
sigma = 0.072
nu = 0.001;
Q = rho_g/ rho_l;
u = 14.8;
k = Symbol('k', real=True)
w1 = -2*nu*k**2
w2 = 4* (nu**2) * (k**4);
w3 = - Q* (u**2) * (k**2);
w4 = - sigma * (k**3)/ rho_l;
w = w1 + sqrt(w2+w3+w4);
print (w)
wprime = w.diff(k)
print (wprime)
ko = solve(wprime, k) # solve fprime = 0 with respect to x
ko = ko[0]
print (ko)
ws = lambdify (k, w, 'numpy');
print (type(ko))
print (ws(ko))

You're getting that error because numpy apparently doesn't know how to handle sympy.core.numbers.Float types (https://docs.sympy.org/latest/modules/core.html#sympy.core.numbers.Float). Therefore, the numpy sqrt raises the exception when you call ws. To fix, pass sympy to lambdify instead of numpy.
ws = lambdify (k, w, 'sympy');
print (type(ko)) # >> <class 'sympy.core.numbers.Float'>
print (ws(ko)) # >> -82.5885350883393

Alternatively you could convert the sympy.Float to a regular float using float() and replace k0 by float(k0) .
ws = lambdify(k, w, 'numpy');
print(type(float(ko))) # >> <class 'float'>
print(ws(float(ko))) # >> -82.58853508833931

Related

Optimizing asymmetrically reweighted penalized least squares smoothing (from matlab to python)

I'm trying to apply the method for baselinining vibrational spectra, which is announced as an improvement over asymmetric and iterative re-weighted least-squares algorithms in the 2015 paper (doi:10.1039/c4an01061b), where the following matlab code was provided:
function z = baseline(y, lambda, ratio)
% Estimate baseline with arPLS in Matlab
N = length(y);
D = diff(speye(N), 2);
H = lambda*D'*D;
w = ones(N, 1);
while true
W = spdiags(w, 0, N, N);
% Cholesky decomposition
C = chol(W + H);
z = C \ (C' \ (w.*y) );
d = y - z;
% make d-, and get w^t with m and s
dn = d(d<0);
m = mean(d);
s = std(d);
wt = 1./ (1 + exp( 2* (d-(2*s-m))/s ) );
% check exit condition and backup
if norm(w-wt)/norm(w) < ratio, break; end
end
that I rewrote into python:
def baseline_arPLS(y, lam, ratio):
# Estimate baseline with arPLS
N = len(y)
k = [numpy.ones(N), -2*numpy.ones(N-1), numpy.ones(N-2)]
offset = [0, 1, 2]
D = diags(k, offset).toarray()
H = lam * numpy.matmul(D.T, D)
w_ = numpy.ones(N)
while True:
W = spdiags(w_, 0, N, N, format='csr')
# Cholesky decomposition
C = cholesky(W + H)
z_ = spsolve(C.T, w_ * y)
z = spsolve(C, z_)
d = y - z
# make d- and get w^t with m and s
dn = d[d<0]
m = numpy.mean(dn)
s = numpy.std(dn)
wt = 1. / (1 + numpy.exp(2 * (d - (2*s-m)) / s))
# check exit condition and backup
norm_wt, norm_w = norm(w_-wt), norm(w_)
if (norm_wt / norm_w) < ratio:
break
w_ = wt
return(z)
Except for the input vector y the method requires parameters lam and ratio and it runs ok for values lam<1.e+07 and ratio>1.e-01, but outputs poor results. When values are changed outside this range, for example lam=1e+07, ratio=1e-02 the CPU starts heating up and job never finishes (I interrupted it after 1min). Also in both cases the following warning shows up:
/usr/local/lib/python3.9/site-packages/scipy/sparse/linalg/dsolve/linsolve.py: 144: SparseEfficencyWarning: spsolve requires A to be CSC or CSR matrix format warn('spsolve requires A to be CSC or CSR format',
although I added the recommended format='csr' option to the spdiags call.
And here's some synthetic data (similar to one in the paper) for testing purposes. The noise was added along with a 3rd degree polynomial baseline The method works well for parameters bl_1 and fails to converge for bl_2:
import numpy
from matplotlib import pyplot
from scipy.sparse import spdiags, diags, identity
from scipy.sparse.linalg import spsolve
from numpy.linalg import cholesky, norm
import sys
x = numpy.arange(0, 1000)
noise = numpy.random.uniform(low=0, high = 10, size=len(x))
poly_3rd_degree = numpy.poly1d([1.2e-06, -1.23e-03, .36, -4.e-04])
poly_baseline = poly_3rd_degree(x)
y = 100 * numpy.exp(-((x-300)/15)**2)+\
200 * numpy.exp(-((x-750)/30)**2)+ \
100 * numpy.exp(-((x-800)/15)**2) + noise + poly_baseline
bl_1 = baseline_arPLS(y, 1e+07, 1e-01)
bl_2 = baseline_arPLS(y, 1e+07, 1e-02)
pyplot.figure(1)
pyplot.plot(x, y, 'C0')
pyplot.plot(x, poly_baseline, 'C1')
pyplot.plot(x, bl_1, 'k')
pyplot.show()
sys.exit(0)
All this is telling me that I'm doing something very non-optimal in my python implementation. Since I'm not knowledgeable enough about the intricacies of scipy computations I'm kindly asking for suggestions on how to achieve convergence in this calculations.
(I encountered an issue in running the "straight" matlab version of the code because the line D = diff(speye(N), 2); truncates the last two rows of the matrix, creating dimension mismatch later in the function. Following the description of matrix D's appearance I substituted this line by directly creating a tridiagonal matrix using the diags function.)
Guided by the comment #hpaulj made, and suspecting that the loop exit wasn't coded properly, I re-visited the paper and found out that the authors actually implemented an exit condition that was not featured in their matlab script. Changing the while loop condition provides an exit for any set of parameters; my understanding is that algorithm is not guaranteed to converge in all cases, which is why this condition is necessary but was omitted by error. Here's the edited version of my python code:
def baseline_arPLS(y, lam, ratio):
# Estimate baseline with arPLS
N = len(y)
k = [numpy.ones(N), -2*numpy.ones(N-1), numpy.ones(N-2)]
offset = [0, 1, 2]
D = diags(k, offset).toarray()
H = lam * numpy.matmul(D.T, D)
w_ = numpy.ones(N)
i = 0
N_iterations = 100
while i < N_iterations:
W = spdiags(w_, 0, N, N, format='csr')
# Cholesky decomposition
C = cholesky(W + H)
z_ = spsolve(C.T, w_ * y)
z = spsolve(C, z_)
d = y - z
# make d- and get w^t with m and s
dn = d[d<0]
m = numpy.mean(dn)
s = numpy.std(dn)
wt = 1. / (1 + numpy.exp(2 * (d - (2*s-m)) / s))
# check exit condition and backup
norm_wt, norm_w = norm(w_-wt), norm(w_)
if (norm_wt / norm_w) < ratio:
break
w_ = wt
i += 1
return(z)

unsupported operand type error while evaluating gradient using sympy

I am trying to minimize this function -(y+47)sin(sqrt(abs((x/2)+y+47))) - xsin(sqrt(abs(x-(y+47)))) which is the eggholder function by using gradient descent method and inbuilt sympy library to evaluate the gradients but i am getting error.
Error message:
import matplotlib.pyplot as plt
import numpy as np
import math
import sympy as sym
x,y = sym.symbols('x y')
#objective function
def objective(p):
x = p[0]
y = p[1]
return -(y+47)*sym.sin(sym.sqrt(abs((x/2)+y+47))) - x*sym.sin(sym.sqrt(abs(x-(y+47))))
#gradient wrt x
def gradient_1(p):
g0 = sym.diff(objective([x,y]),x)
return g0.subs(x,p[0]).subs(y,p[1])
#gradient wrt y
def gradient_2(p):
g1 = sym.diff(objective([x,y]),y)
return g1.subs(x,p[0]).subs(y,p[1])
#initial guess
x = [-450,-450]
#learning rate
alpha = 0.135
#initialization
iter = 0
e = 1000
grad = np.array([])
error = np.array([])
#gradient descent
while e > 0.000000001:
t = objective(x)
grad = [gradient_1(x),gradient_2(x)]
change = np.dot(-alpha,grad)
x = np.add(x,change)
e = abs(objective(x)-t)
error = np.append(error,e)
iter = iter+1
print("ITERATION NUMBER = ",iter)
#printing optimized values
print(x)
#plotting error v/s iteration
i = np.arange(1,iter+1)
plt.plot(i,error)
plt.xlabel("Iterations")
plt.ylabel("Error")
In the second iteration of the while, the variable x is not a of type int but of type list. You can see it if you print the type of the variables x and y inside the function objective().
def objective(p):
x = p[0]
y = p[1]
#print(type(p))
print("Iteration")
print("x:", type(x))
print("y:", type(y))
return -(y+47)*sym.sin(sym.sqrt(abs((x/2)+y+47))) - x*sym.sin(sym.sqrt(abs(x-(y+47))))
Output:
Iteration
x: <class 'int'>
y: <class 'int'>
Iteration
x: <class 'list'>
y: <class 'sympy.core.symbol.Symbol'>

How to resolve value error in Scipy function fmintnc?

I am trying to implement coursera assignments in python, while doing Scipy optimise for logistic regression. However, I am getting the error below.
Can any one help!
Note: cost, gradient functions are working fine.
#Sigmoid function
def sigmoid(z):
h_of_z = np.zeros([z.shape[0]])
h_of_z = np.divide(1,(1+(np.exp(-z))))
return h_of_z
def cost(x,y,theta):
m = y.shape[0]
h_of_x = sigmoid(np.matmul(x,theta))
term1 = sum(-1 * y.T # np.log(h_of_x) - (1-y.T) # np.log(1-h_of_x))
J = 1/m * term1
return J
def grad(x,y,theta):
grad = np.zeros_like(theta)
m = y.shape[0]
h_of_x = sigmoid(x#theta)
grad = (x.T # (h_of_x - y)) * (1/m)
return grad
#add intercept term for X
x = np.hstack([np.ones_like(y),X[:,0:2]])
#initialise theta
[m,n] = np.shape(x)
initial_theta = np.zeros([n,1])
#optimising theta from given theta and gradient
result = opt.fmin_tnc(func=cost, x0=initial_theta, args=(x, y))
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 99 is different from 3)
I got it !
so the problem is fmin_tnc function programmed in a way we should parse the the parameter 'theta' before calling arguments x and y .
Since in my function 'cost' I have passed x and y first, it interpreted values differently so thrown ValueError .
Below are the corrected code..
def sigmoid(x):
return 1/(1+np.exp(-x))
def cost(theta,x,y):
J = (-1/m) * np.sum(np.multiply(y, np.log(sigmoid(x # theta)))
+ np.multiply((1-y), np.log(1 - sigmoid(x # theta))))
return J
def gradient(theta,x,y):
h_of_x = sigmoid(x#theta)
grad = 1 / m * (x.T # (h_of_x - y))
return grad
#initialise theta
init_theta = np.zeros([n+1,1])
#optimise theta
from scipy import optimize as op
result = op.fmin_tnc(func=cost,
x0=init_theta.flatten(),
fprime=gradient,
args=(x,y.flatten()))

TypeError when accessing RNN results

I am trying to extract the decisions of an RNN for all tokens in a sequence but receive the error mentioned at the end of the post.
Any help will be appreciated!
Code:
# gated recurrent unit
def gru_step(x, h_prev, W_xm, W_hm, W_xh, W_hh):
m = theano.tensor.nnet.sigmoid(theano.tensor.dot(x, W_xm) + theano.tensor.dot(h_prev, W_hm))
r = _slice(m, 0, 2)
z = _slice(m, 1, 2)
_h = theano.tensor.tanh(theano.tensor.dot(x, W_xh) + theano.tensor.dot(r * h_prev, W_hh))
h = z * h_prev + (1.0 - z) * _h
return h
# return h, theano.scan_module.until(previous_power*2 > max_value)
W_xm = self.create_parameter_matrix('W_xm', (word_embedding_size, recurrent_size*2))
W_hm = self.create_parameter_matrix('W_hm', (recurrent_size, recurrent_size*2))
W_xh = self.create_parameter_matrix('W_xh', (word_embedding_size, recurrent_size))
W_hh = self.create_parameter_matrix('W_hh', (recurrent_size, recurrent_size))
initial_hidden_vector = theano.tensor.alloc(numpy.array(0, dtype=floatX), recurrent_size)
initial_process_vector = theano.tensor.alloc(recurrent_size, n_classes)
hidden_vector, _ = theano.scan(
gru_step,
sequences = input_vectors,
outputs_info = initial_hidden_vector,
non_sequences = [W_xm, W_hm, W_xh, W_hh]
)
W_output = self.create_parameter_matrix('W_output', (n_classes,recurrent_size))
rnn_output = theano.tensor.nnet.softmax([theano.tensor.dot(W_output, hidden_vector[-1])])[0]
rnn+predicted_class = theano.tensor.argmax(output)
# Process hidden_vector to decision vectors
def process_hidden_vector(x, W_dot):
return theano.tensor.dot(W_dot, x)
all_tokens_output_vector = theano.scan(process_hidden_vector, sequences=hidden_vector, non_sequences=W_output)
The results should be the "all_tokens_output_vector", but I get the following error when trying to output it:
TypeError: Outputs must be theano Variable or Out instances. Received (for{cpu,scan_fn}.0, OrderedUpdates()) of type <type 'tuple'>
What are you doing with "all_tokens_output_vector" after that? Your print it directly?
There should be a theano.function to compile the graph

Theano subtraction when you can't tile

Say we have a theano matrix X that is nxm, and another one u that is nx1. We want to do X-u, but if we do that we'll get an input dimension mismatch. We could try tiling u, but tile only accepts constants and not variables. How do we do this?
import theano
import theano.tensor as T
X, u = T.dmatrices("X", "u")
T.addbroadcast(u, 1)
r = X - u
f = theano.function([X, u], r)
f([[1], [0]], [[1]])
I then get the error ('Bad input argument to theano function with name "<stdin>:1" at index 0(0-based)', 'Wrong number of dimensions: expected 2, got 1 with shape (2,).')
X - u should work exactly as you write it by broadcasting:
import theano
import theano.tensor as T
n = 10
m = 20
X = T.arange(n * m).reshape((n, m))
u = T.arange(0, n * m, m).reshape((n, 1))
r = X - u
r.eval()
Similar to your updated question, you can do
import theano
import theano.tensor as T
X = T.dmatrix()
u = T.addbroadcast(T.dmatrix(), 1)
r = X - u
f = theano.function([X, u], r)
XX = np.arange(20.).reshape(2, 10)
uu = np.array([1., 100.]).reshape(2, 1)
f(XX, uu)

Resources