Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializing numpy array from np.empty

How are the sign bits determined when initializing an ndarray from empty memory?

>>> np.random.randn(3,3)
array([[-0.35557367, -0.0561576 , -1.84722985],
       [ 0.89342124, -0.50871646,  1.31368413],
       [ 0.0062188 ,  1.62968789,  0.72367089]])
>>> np.empty((3,3))
array([[0.35557367, 0.0561576 , 1.84722985],
       [0.89342124, 0.50871646, 1.31368413],
       [0.0062188 , 1.62968789, 0.72367089]])

These float values initialized from empty memory have lost their signs. Why is that?

Note: this result relies on implementation detail of memory re-use. The question asks what the implementation is doing.

like image 965
wim Avatar asked Jun 25 '18 16:06

wim


People also ask

What does NP empty () do?

In Python, the numpy. empty() function is used to return new array of a given shape and type. It has random values and uninitialized entries.

Why is NP empty not empty?

empty has nothing to do with creating an array that is "empty" in the sense of having no elements. It just means the array doesn't have its values initialized (i.e., they are unpredictable and depend on whatever happens to be in the memory allocated for the array).

How do you declare an empty array in Python?

The second way to declare an empty array in Python is by creating a list and multiplying it by the number(length of the array) to create an empty array. This will create an empty array of size 4. print(myarr) will result in the following output. Additionally, we can create an empty array using NumPy.


1 Answers

numpy.empty isn't clearing the sign bits manually or anything. The sign bits are just whatever garbage happens to be left in those bits of the malloc return value. The effect you're seeing is due to a numpy.absolute call somewhere else.

The thing is, numpy.empty isn't reusing the randn return value's buffer. After all, the randn return value is still alive when empty creates its array, due to the _ variable.

numpy.empty is reusing the buffer of an array created in the process of stringifying the first array. I believe it's this one:

def fillFormat(self, data):
    # only the finite values are used to compute the number of digits
    finite_vals = data[isfinite(data)]

    # choose exponential mode based on the non-zero finite values:
    abs_non_zero = absolute(finite_vals[finite_vals != 0])
    ...

See that absolute call? That's the one.

Here's some additional testing that supports that conclusion:

>>> a = numpy.random.randn(3, 3)
>>> b = numpy.arange(-5, 4, dtype=float)
>>> c = numpy.arange(-5, 13, 2, dtype=float)
>>> a
array([[-0.96810932,  0.86091026, -0.32675013],
       [-1.23458136,  0.56151178, -0.37409982],
       [-1.71348979,  0.64170792, -0.20679512]])
>>> numpy.empty((3, 3))
array([[ 0.96810932,  0.86091026,  0.32675013],
       [ 1.23458136,  0.56151178,  0.37409982],
       [ 1.71348979,  0.64170792,  0.20679512]])
>>> b
array([-5., -4., -3., -2., -1.,  0.,  1.,  2.,  3.])
>>> numpy.empty((3, 3))
array([[ 0.96810932,  0.86091026,  0.32675013],
       [ 1.23458136,  0.56151178,  0.37409982],
       [ 1.71348979,  0.64170792,  0.20679512]])
>>> c
array([ -5.,  -3.,  -1.,   1.,   3.,   5.,   7.,   9.,  11.])
>>> numpy.empty((3, 3))
array([[  5.,   3.,   1.],
       [  1.,   3.,   5.],
       [  7.,   9.,  11.]])
>>> numpy.array([1.0, 0, 2, 3, 4, 5, 6, 7, 8, 9])
array([ 1.,  0.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])
>>> numpy.empty((3, 3))
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.],
       [ 7.,  8.,  9.]])

The numpy.empty results are affected by printing a and c, rather than by the process of creating those arrays. b has no effect, because it has 8 nonzero elements. The final array([1.0, 0, 2, ...]) has an effect, because even though it has 10 elements, exactly 9 of them are nonzero.

like image 66
user2357112 supports Monica Avatar answered Nov 12 '22 05:11

user2357112 supports Monica