I want to measure the time through numpy but I am not sure if I have the right arguments.
import numpy as np
import timeit
def svdsolve(a,b):
u,s,v = np.linalg.svd(a)
c = np.dot(u.T,b)
w = np.linalg.solve(np.diag(s),c)
x = np.dot(v.T,w)
return x
A_=np.fromfile('dataA.bin',count=-1,dtype=np.float32)
B_=np.fromfile('dataB.bin',count=-1,dtype=np.float32)
s='svdsolve({0},{1})'.format(A,B)
mytime= timeit.Timer(stmt=s,setup='import numpy').timeit(100)
print mytime
Right now it gives me :
File "/usr/lib64/python2.7/timeit.py", line 136, in init
code = compile(src, dummy_src_name, "exec") File "", line 6
svdsolve([[ 1.86248358e+09 1.54404045e+09]
^ SyntaxError: invalid syntax
Also , I didn' understand (neither have I found a reference) on what arguments to pass at timer.
And I am not sure how to use the repetition timeit(100)
Neither the str nor repr of a NumPy array is guaranteed to produce an output that can be used to reconstruct the original array. (format uses str, but repr wouldn't help.) Instead, import the arrays into the timed code's namespace. Assuming this code is being run as a script, that would be
mytime = timeit.Timer(stmt='svdsolve(A, B)',
setup='from __main__ import A, B, svdsolve'
).timeit(100)
Related
I'm trying out numba, the python package that is said to make my nparray super fast. I want to run my function in nonpython mode. What it essentially does is that it takes in an 20x20 array, assigns random numbers to each of its elements, calculate its inverse matrix, then return it.
But here's the problem, when I initialize the array result with np.zeros(), my script crashes and gives me an error message 'overload of function zeros'.
Could someone kindly tell me what is going on? Much appreciated.
from numba import njit
import time
import numpy as np
import random
arr = np.zeros((20,20),dtype = float)
#njit
def aFunctionWithNumba (incomingArray):
result = np.zeros(np.shape(incomingArray), dtype = float)
for i in range(len(incomingArray[0])):
for j in range(len(incomingArray[1])):
incomingArray[i,j] = random.randrange(105150,1541586)
result = np.linalg.inv(incomingArray)
return result
t0 = time.time()
fastArray = aFunctionWithNumba(arr)
t1 = time.time()
s1 = t1 - t0
Here's the full error message:
Exception has occurred: TypingError Failed in nopython mode pipeline (step: nopython frontend) No implementation of function Function(<built-in function zeros>) found for signature:
>>> zeros(UniTuple(int64 x 2), dtype=Function(<class 'float'>)) There are 2 candidate implementations:
- Of which 2 did not match due to: Overload of function 'zeros': File: numba\core\typing\npydecl.py: Line 511.
With argument(s): '(UniTuple(int64 x 2), dtype=Function(<class 'float'>))': No match.
During: resolving callee type: Function(<built-in function zeros>) During: typing of call at c:\Users\Eric\Desktop\testNumba.py (9)
File "testNumba.py", line 9: def aFunctionWithNumba (incomingArray):
result = np.zeros(np.shape(incomingArray), dtype = float)
^ File "C:\Users\Eric\Desktop\testNumba.py", line 25, in <module>
fastArray = aFunctionWithNumba(arr)
The error
You should use Numpy or Numba types inside JITted functions.
Changing the following line your code works:
result = np.zeros(np.shape(incomingArray), dtype=np.float64)
But your code will be more generic using:
result = np.zeros(incomingArray.shape, dtype=incomingArray.dtype)
Or, even better:
result = np.zeros_like(incomingArray)
The timing
The first time you call a JITted function it will take some time to compile it, much longer than the time it will take to execute it. So you should call the function with the same parameter types once before you make any timings.
Additional optimization
If you are interested in comparing the execution time of nested loops with or without Numba, your code is fine. Otherwise you can replace the loops with something like:
incomingArray[:] = np.random.random(incomingArray.shape) * (1541586 - 105150) + 105150
Im trying to execute scipy broyden1 function with extra parameters (called "data" in the example), here is the code:
data = [radar_wavelen, satpos, satvel, ellipsoid_semimajor_axis, ellipsoid_semiminor_axis, srange]
target_xyz = broyden1(Pixlinexyx_2Bsolved, start_xyz, args=data)
def Pixlinexyx_2Bsolved(target, *data):
radar_wavelen, satpos, satvel, ellipsoid_semimajor_axis, ellipsoid_semiminor_axis, srange = data
print target
print radar_wavelen, satpos, satvel, ellipsoid_semimajor_axis, ellipsoid_semiminor_axis, srange
Pixlinexyx_2Bsolved is the function whose root I want to find.
start_xyz is initial guess of the solution:
start_xyz = [4543557.208584103, 1097477.4119051248, 4176990.636060918]
And data is this list containing a lot of numbers, that will be used inside the Pixlinexyx_2Bsolved function:
data = [0.056666, [5147114.2523595653, 1584731.770061729, 4715875.3525346108], [5162.8213179936156, -365.24378919717839, -5497.6237250296626], 6378144.0430000005, 6356758.789000001, 850681.12442702544]
When I call the function broyden1 (as in the second line of example code) I get the next error:
target_xyz = broyden1(Pixlinexyx_2Bsolved, start_xyz, args=data)
File "<string>", line 5, in broyden1
TypeError: __init__() got an unexpected keyword argument 'args'
What I'm doing wrong?
Now, seeing the documentation of fsolve, it seems to be able to get extra args in the callable func... Here is a similar question as mine.
There is a similar question at scipy's issue-tracker including a solution using python's functools-module (here: PEP 309 -- Partial Function Application
).
Small example based on the above link and the original problem from the docs:
import numpy as np
import scipy.optimize
""" No external data """
def F(x):
return np.cos(x) + x[::-1] - [1, 2, 3, 4]
x = scipy.optimize.broyden1(F, [1,1,1,1], f_tol=1e-14)
print(x)
""" External data """
from functools import partial
def G(data, x):
return np.cos(x) + x[::-1] - data
data = [1,2,3,4]
G_partial = partial(G, data)
x = scipy.optimize.broyden1(G_partial, [1,1,1,1], f_tol=1e-14)
print(x)
Out
[ 4.04674914 3.91158389 2.71791677 1.61756251]
[ 4.04674914 3.91158389 2.71791677 1.61756251]
I'm trying to speed up some numeric code generated by lambdify using numexpr. Unfortunately, the numexpr-based function breaks when using the sqrt function, even though it's one of the supported functions.
This reproduces the issue for me:
import sympy
import numpy as np
import numexpr
from sympy.utilities.lambdify import lambdify
expr = sympy.S('b*sqrt(a) - a**2')
a, b = sorted(expr.free_symbols, key=lambda s: s.name)
func_numpy = lambdify((a,b), expr, modules=[np], dummify=False)
func_numexpr = lambdify((a,b), expr, modules=[numexpr], dummify=False)
foo, bar = np.random.random((2, 4))
print sympy.__version__
print func_numpy(foo, bar)
print func_numexpr(foo, bar)
When I run this, the output is:
0.7.6
[-0.02062061 0.08648306 -0.57868128 0.27598245]
Traceback (most recent call last):
File "sympy_test.py", line 17, in <module>
print func_numexpr(foo, bar)
File "<string>", line 1, in <lambda>
NameError: global name 'sqrt' is not defined
As a sanity check, I also tried calling numexpr directly:
numexpr.evaluate('b*sqrt(a) - a**2', local_dict=dict(a=foo, b=bar))
which works as expected, producing the same result as func_numpy.
EDIT: It works when I use the line:
func_numexpr = lambdify((a,b), expr, modules=['numexpr'], dummify=False)
Is this a sympy bug?
you can change np.sqrt(9) to numexpr.evaluate('9**0.5')
How can I import factorial function from numpy and scipy separately in order to see which one is faster?
I already imported factorial from python itself by import math. But, it does not work for numpy and scipy.
You can import them like this:
In [7]: import scipy, numpy, math
In [8]: scipy.math.factorial, numpy.math.factorial, math.factorial
Out[8]:
(<function math.factorial>,
<function math.factorial>,
<function math.factorial>)
scipy.math.factorial and numpy.math.factorial seem to simply be aliases/references for/to math.factorial, that is scipy.math.factorial is math.factorial and numpy.math.factorial is math.factorial should both give True.
The answer for Ashwini is great, in pointing out that scipy.math.factorial, numpy.math.factorial, math.factorial are the same functions. However, I'd recommend use the one that Janne mentioned, that scipy.special.factorial is different. The one from scipy can take np.ndarray as an input, while the others can't.
In [12]: import scipy.special
In [13]: temp = np.arange(10) # temp is an np.ndarray
In [14]: math.factorial(temp) # This won't work
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-14-039ec0734458> in <module>()
----> 1 math.factorial(temp)
TypeError: only length-1 arrays can be converted to Python scalars
In [15]: scipy.special.factorial(temp) # This works!
Out[15]:
array([ 1.00000000e+00, 1.00000000e+00, 2.00000000e+00,
6.00000000e+00, 2.40000000e+01, 1.20000000e+02,
7.20000000e+02, 5.04000000e+03, 4.03200000e+04,
3.62880000e+05])
So, if you are doing factorial to a np.ndarray, the one from scipy will be easier to code and faster than doing the for-loops.
SciPy has the function scipy.special.factorial (formerly scipy.misc.factorial)
>>> import math
>>> import scipy.special
>>> math.factorial(6)
720
>>> scipy.special.factorial(6)
array(720.0)
from numpy import prod
def factorial(n):
print prod(range(1,n+1))
or with mul from operator:
from operator import mul
def factorial(n):
print reduce(mul,range(1,n+1))
or completely without help:
def factorial(n):
print reduce((lambda x,y: x*y),range(1,n+1))
after running different aforementioned functions for factorial, by different people, turns out that math.factorial is the fastest to calculate the factorial.
find running times for different functions in the attached image
You can save some homemade factorial functions on a separate module, utils.py, and then import them and compare the performance with the predefinite one, in scipy, numpy and math using timeit.
In this case I used as external method the last proposed by Stefan Gruenwald:
import numpy as np
def factorial(n):
return reduce((lambda x,y: x*y),range(1,n+1))
Main code (I used a framework proposed by JoshAdel in another post, look for how-can-i-get-an-array-of-alternating-values-in-python):
from timeit import Timer
from utils import factorial
import scipy
n = 100
# test the time for the factorial function obtained in different ways:
if __name__ == '__main__':
setupstr="""
import scipy, numpy, math
from utils import factorial
n = 100
"""
method1="""
factorial(n)
"""
method2="""
scipy.math.factorial(n) # same algo as numpy.math.factorial, math.factorial
"""
nl = 1000
t1 = Timer(method1, setupstr).timeit(nl)
t2 = Timer(method2, setupstr).timeit(nl)
print 'method1', t1
print 'method2', t2
print factorial(n)
print scipy.math.factorial(n)
Which provides:
method1 0.0195569992065
method2 0.00638914108276
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
Process finished with exit code 0
I want to calculate the sumproduct of two arrays in Theano. Both arrays are declared as shared variables and are the result of prior computations. Reading the tutorial, I found out how to use scan to compute what I want using 'normal' tensor arrays, but when I tried to adapt the code to shared arrays I got the error message TypeError: function() takes at least 1 argument (1 given). (See minimal running code example below)
Where is the mistake in my code? Where is my misconception? I am also open to a different approach for solving my problem.
Generally I would prefer a version which takes the shared variables directly, because in my understanding, converting the arrays first back to Numpy arrays and than again passing them to Theano, would be wasteful.
Error message producing sumproduct code using shared variables:
import theano
import theano.tensor as T
import numpy
a1 = [1,2,4]
a2 = [3,4,5]
Ta1_shared = theano.shared(numpy.array(a1))
Ta2_shared = theano.shared(numpy.array(a2))
outputs_info = T.as_tensor_variable(numpy.asarray(0, 'float64'))
Tsumprod_result, updates = theano.scan(fn=lambda Ta1_shared, Ta2_shared, prior_value:
prior_value + Ta1_shared * Ta2_shared,
outputs_info=outputs_info,
sequences=[Ta1_shared, Ta2_shared])
Tsumprod_result = Tsumprod_result[-1]
Tsumprod = theano.function(outputs=Tsumprod_result)
print Tsumprod()
Error message:
TypeError: function() takes at least 1 argument (1 given)
Working sumproduct code using non-shared variables:
import theano
import theano.tensor as T
import numpy
a1 = [1, 2, 4]
a2 = [3, 4, 5]
Ta1 = theano.tensor.vector("a1")
Ta2 = theano.tensor.vector("coefficients")
outputs_info = T.as_tensor_variable(numpy.asarray(0, 'float64'))
Tsumprod_result, updates = theano.scan(fn=lambda Ta1, Ta2, prior_value:
prior_value + Ta1 * Ta2,
outputs_info=outputs_info,
sequences=[Ta1, Ta2])
Tsumprod_result = Tsumprod_result[-1]
Tsumprod = theano.function(inputs=[Ta1, Ta2], outputs=Tsumprod_result)
print Tsumprod(a1, a2)
You need to change the compilation line to this one:
Tsumprod = theano.function([], outputs=Tsumprod_result)
theano.function() always need a list of inputs. If the function take 0 input, like in this case, you need to give an empty list for the inputs.