numpy vs pytorch precision - python

I've a numpy matrix a defined as:
>>> a
>>> array([[ 1.920941165 , 0.9518795607, 1.5358781432],
[-0.2418292026, 0.0851087409, -0.2760766872],
[-0.4161812806, 0.7409229185, -0.3248560283],
[-0.3439163186, 1.4052927665, -1.612850871 ],
[ 1.5810794171, 1.1820622504, 1.8063415367]])
If I typecast it to float32, it gives:
>>> a.astype(np.float32)
>>> array([[ 1.9209411 , 0.95187956, 1.5358782 ],
[-0.2418292 , 0.08510874, -0.27607667],
[-0.41618127, 0.7409229 , -0.32485604],
[-0.34391633, 1.4052927 , -1.6128509 ],
[ 1.5810794 , 1.1820623 , 1.8063415 ]], dtype=float32)
When I convert original a matrix to a tensor, I get:
>>> torch.tensor(a)
>>> tensor([[ 1.9209411650, 0.9518795607, 1.5358781432],
[-0.2418292026, 0.0851087409, -0.2760766872],
[-0.4161812806, 0.7409229185, -0.3248560283],
[-0.3439163186, 1.4052927665, -1.6128508710],
[ 1.5810794171, 1.1820622504, 1.8063415367]], dtype=torch.float64)
which looks correct as it retains original values from matrix a.
But when I convert float32-typecasted matrix to a tensor, I get different floating point numbers.
>>> torch.tensor(a.astype(np.float32))
>>> tensor([[ 1.9209411144, 0.9518795609, 1.5358781815],
[-0.2418292016, 0.0851087421, -0.2760766745],
[-0.4161812663, 0.7409229279, -0.3248560429],
[-0.3439163268, 1.4052927494, -1.6128509045],
[ 1.5810793638, 1.1820622683, 1.8063415289]])
Why can't the second tensor(tensor of type-casted matrix) be equal to the second matrix(type-casted one) provided above.

float32 has 24fraction bit (7.2 decimal point in decimal), what you see after that is not meaningful. ex: 1.920941165 (9 point).
this means if you want to retain all points you shoult represent as 64 float. however when you convert to 32, either in numpy or torch they should be same values, it is only printing is different. torch print till the number of floating that you have set, while numpy truncate only till valid points.
for example:
import numpy as np
np.set_printoptions(precision=10)
a = np.array([1.920941165],dtype=np.float32)
array([1.9209411], dtype=float32)**
t = torch.tensor(a , dtype=torch.float32)
tensor([1.9209411144])
however if you look into underlying memory of both (one uint32) are the same:
np.ndarray(1, dtype=np.uint32,buffer=a )
array([1073078630], dtype=uint32)
import ctypes
ptr = ctypes.cast(t.data_ptr(), ctypes.POINTER(ctypes.c_uint32))
ptr[0]
1073078630

Related

unexpected results with np.hstack and np.c_ with regard to decimal points

I have a matrix (3x3) of
matrix = [[-8.51871377e-01 -5.22712676e-01 3.29641828e-02]
[ 5.22321761e-01 -8.52508933e-01 -2.02118648e-02]
[ 3.86672578e-02 -6.20947349e-10 9.99252295e-01]]
and I have a vector (3x1) of
vector = [[0.28407955]
[0.681005 ]
[4.12974119]]
When I concatenate the matrix with the vector via np.hstack or np.c_ then I get the following concatenation:
concat = [[-8.51871377e-01 -5.22712676e-01 3.29641828e-02 2.84079552e-01]
[ 5.22321761e-01 -8.52508933e-01 -2.02118648e-02 6.81005001e-01]
[ 3.86672578e-02 -6.20947349e-10 9.99252295e-01 4.12974119e+00]]
and not as expected:
concat = [[-8.51871377e-01 -5.22712676e-01 3.29641828e-02 0.28407955...]
[ 5.22321761e-01 -8.52508933e-01 -2.02118648e-02 0.681005...]
[ 3.86672578e-02 -6.20947349e-10 9.99252295e-01 4.12974119e+00]]
On the very right side of the concatenation it seems that the 0.'s are ignored in 0.28407955 and 0.681005 which means that the decimal point is shifted one place to the right and this leads to 2.84079552e-01 and 6.81005001e-01. Why is this happening and how can I get my expected results?

Dot product for correlation with complex numbers

OK, this question probably has a very simple answer, but I've been searching for quite a while with no luck...
I want to get the dot product of 2 complex numbers in complex-plane-space. However, np.dot and np.vdot both give the wrong result.
Example of what I WANT to do:
a = 1+1j
b = 1-1j
dot(a,b) == 0
What I actually get:
np.dot(a,b) == 2+0j
np.vdot(a,b) == 0-2j
np.conj(a)*b == 0-2j
I am able to get what I want using this rather clumsy expression (edit for readability):
a.real*b.real + a.imag*b.imag
But I am very surprised not to find a nice ufunc to do this. Does it not exist? I was not expecting to have to write my own ufunc to vectorize such a common operation.
Part of my concern here, is that it seems like my expression is doing a lot of extra work extracting out the real/imaginary parts when they should be already in adjacent memory locations (considering a,b are actually already combined in a data type like complex64). This has the potential to cause a pretty severe slowdown.
** EDIT
Using Numba I ended up defining a ufunc:
#vectorize
def cdot(a, b):
return (a.real*b.real + a.imag*b.imag)
This allowed me to correlate complex data properly. Here's a correlation image for the guys who helped me!
For arrays and np.complex scalars but not plain python complex numbers you can viewcast to float. For example:
a = np.exp(1j*np.arange(4))
b = np.exp(-1j*np.arange(4))
a
# array([ 1. +0.j , 0.54030231+0.84147098j,
# -0.41614684+0.90929743j, -0.9899925 +0.14112001j])
b
# array([ 1. -0.j , 0.54030231-0.84147098j,
# -0.41614684-0.90929743j, -0.9899925 -0.14112001j])
ar = a[...,None].view(float)
br = b[...,None].view(float)
ar
# array([[ 1. , 0. ],
# [ 0.54030231, 0.84147098],
# [-0.41614684, 0.90929743],
# [-0.9899925 , 0.14112001]])
br
# array([[ 1. , -0. ],
# [ 0.54030231, -0.84147098],
# [-0.41614684, -0.90929743],
# [-0.9899925 , -0.14112001]])
Now, for example, all pairwise dot products:
np.inner(ar,br)
# array([[ 1. , 0.54030231, -0.41614684, -0.9899925 ],
# [ 0.54030231, -0.41614684, -0.9899925 , -0.65364362],
# [-0.41614684, -0.9899925 , -0.65364362, 0.28366219],
# [-0.9899925 , -0.65364362, 0.28366219, 0.96017029]])

trying to seperate real and imaginary but it gets add up

I have given a set of array where it contains real and imaginary values . I need to separate them and print it out . but its not working out . the output gives
[3. +0.j 4.5+0.j 0. +0.j]
import numpy as np
array = np.array([3,4.5,3+5j,0])
real = np.isreal(array)
print(array[real])
img = np.iscomplex(array)
print(array[img])
Referring to numpy documentation you should do the following:
print(array.real)
print(array.imag)
I guess what you are looking is to print the real numbers if it does not have any imaginary number. If it has imaginary part, then just print the imaginary part.
import numpy as np
array = np.array([3,4.5,3+5j,0])
real = np.isreal(array)
print(array[real].real)
img = np.iscomplex(array)
print(array[img].imag)
# output
[ 3. 4.5 0. ]
[5.]
is this right?
import numpy as np
array = np.array([3,4.5,3+5j,0, 12.5])
real = np.isreal(array)
#here I check to prevent round number and just cast number like 12.0 1.0 to int
print([int(i) if str(i).rsplit(".", 1)[-1] == '0' else i for i in array[real].real ])
img = np.iscomplex(array)
print([complex(int(i.real),i.imag) for i in array[img]])
output:
[3, 4.5, 0, 12.5]
[(3+5j)]
I just append 12.5 for test to see how it's working!

Numpy ifft error

I'm having a really frustrating problem using numpy's inverse fast fourier transform function. I know the fft function works well based on my other results. Error seems to be introduced after calling ifft. The following should be printing zeros for example:
temp = Eta[50:55]
print(temp)
print(temp-np.fft.fft(np.fft.ifft(temp)))
Output:
[ -4.70429130e+13 -3.15161484e+12j -2.45515846e+13 +5.43230842e+12j -2.96326088e+13 -4.55029496e+12j 2.99158889e+13 -3.00718375e+13j -3.87978563e+13 +9.98287428e+12j]
[ 0.00781250+0.00390625j -0.02734375+0.01757812j 0.05078125-0.02441406j 0.01171875-0.01171875j -0.01562500+0.015625j ]
Please help!
You are seeing normal floating point imprecision. Here's what I get with your data:
In [58]: temp = np.array([ -4.70429130e+13 -3.15161484e+12j, -2.45515846e+13 +5.43230842e+12j, -2.96326088e+13 -4.55029496e+12j, 2.99158889e+13 -3.00718375e+13j, -3.87978563e+13 +9.98287428e+12j])
In [59]: delta = temp - np.fft.fft(np.fft.ifft(temp))
In [60]: delta
Out[60]:
array([ 0.0000000+0.00390625j, -0.0312500+0.01953125j,
0.0390625-0.02539062j, 0.0078125-0.015625j , -0.0156250+0.015625j ])
Relative to the input, those values are, in fact, "small", and reasonable for 64 bit floating point calculations:
In [61]: np.abs(delta)/np.abs(temp)
Out[61]:
array([ 8.28501685e-17, 1.46553699e-15, 1.55401584e-15,
4.11837758e-16, 5.51577805e-16])

How to force a ndarray show in normal way instead of scientific notation?

I'm trying to print a ndarray on the screen. But python always shows it in scientific notation, which I don't like. For a scalar we can use
>>> print '%2.4f' %(7.47212470e-01)
0.7472
But how to do that for a numpy.ndarray like this :
[[ 7.47212470e-01 3.71730070e-01 1.16736538e-01 1.22172891e-02]
[ 2.79279640e+00 1.31147152e+00 7.43946656e-02 3.08162255e-02]
[ 6.93657970e+00 3.14008688e+00 1.02851599e-01 3.96611266e-02]
[ 8.49295040e+00 3.94730094e+00 8.99398479e-02 7.60969188e-02]
[ 2.01849250e+01 8.62584092e+00 8.75722302e-02 6.17109672e-02]
[ 2.22570710e+01 1.00291292e+01 1.20918359e-01 1.07250131e-01]
[ 2.82496660e+01 1.27882133e+01 1.08438172e-01 1.58723714e-01]
[ 5.89170270e+01 2.55268510e+01 1.31990966e-01 1.61599514e-01]]
The method .astype(float) does not change the result, and .round(4) returns:
[[ 7.47200000e-01 3.71700000e-01 1.16700000e-01 1.22000000e-02]
[ 2.79280000e+00 1.31150000e+00 7.44000000e-02 3.08000000e-02]
[ 6.93660000e+00 3.14010000e+00 1.02900000e-01 3.97000000e-02]
[ 8.49300000e+00 3.94730000e+00 8.99000000e-02 7.61000000e-02]
[ 2.01849000e+01 8.62580000e+00 8.76000000e-02 6.17000000e-02]
[ 2.22571000e+01 1.00291000e+01 1.20900000e-01 1.07300000e-01]
[ 2.82497000e+01 1.27882000e+01 1.08400000e-01 1.58700000e-01]
[ 5.89170000e+01 2.55269000e+01 1.32000000e-01 1.61600000e-01]]
I just simply want the 0.7472 0.3717 etc.
The numpy.set_string_function function can be used to change the string representation of arrays.
You can also use numpy.set_print_options to change the precision used by default and turn off reporting of small numbers in scientific notation.
From the examples for set_print_options:
>>> np.set_printoptions(precision=4)
>>> print np.array([1.123456789])
[ 1.1235]
I don't know about the numpy arrays but I was simply facing the same problem while doing a project in Python.
Take a look at the Decimal class provided http://docs.python.org/library/decimal.html .
I don't know if it's provided in numpy though.

Categories

Resources