Resize the screen image

I am confused about the results of the numpy changes operated on while viewing. The following q.flags shows that it does not own the data, but q.base is neither x nor y, so what is it? I am surprised to see that q.strides is 8, which means that it gets the next item every time, moving 8 bytes to memory (if I understand correctly). However, if none of the arrays, except x, owns the data, the only data buffer is from x, which does not allow us to get the next element q, moving 8 bytes.

In [99]: x = np.random.rand(4, 4) In [100]: y = xT In [101]: q = y.reshape(16) In [102]: q.base is y Out[102]: False In [103]: q.base is x Out[103]: False In [104]: y.flags Out[104]: C_CONTIGUOUS : False F_CONTIGUOUS : True OWNDATA : False WRITEABLE : True ALIGNED : True UPDATEIFCOPY : False In [105]: q.flags Out[105]: C_CONTIGUOUS : True F_CONTIGUOUS : True OWNDATA : False WRITEABLE : True ALIGNED : True UPDATEIFCOPY : False In [106]: q.strides Out[106]: (8,) In [107]: x Out[107]: array([[ 0.62529694, 0.20813211, 0.73932923, 0.43183722], [ 0.09755023, 0.67082005, 0.78412615, 0.40307291], [ 0.2138691 , 0.35191283, 0.57455781, 0.2449898 ], [ 0.36476299, 0.36590522, 0.24371933, 0.24837697]]) In [108]: q Out[108]: array([ 0.62529694, 0.09755023, 0.2138691 , 0.36476299, 0.20813211, 0.67082005, 0.35191283, 0.36590522, 0.73932923, 0.78412615, 0.57455781, 0.24371933, 0.43183722, 0.40307291, 0.2449898 , 0.24837697]) 

UPDATE:

It turns out this question was asked in the numpy discussion forum: http://numpy-discussion.10968.n7.nabble.com/OWNDATA-flag-and-reshape-views-vs-copies-td10363.html

+5
python numpy reshape
Mar 05 '15 at 20:06
source share
2 answers

In short: you cannot always rely on ndarray.flags['OWNDATA'] .

 >>> import numpy as np >>> x = np.random.rand(2,2) >>> y = xT >>> q = y.reshape(4) >>> y[0,0] 0.86751629121019136 >>> y[0,0] = 1 >>> q array([ 0.86751629, 0.87671107, 0.65239976, 0.41761267]) >>> x array([[ 1. , 0.65239976], [ 0.87671107, 0.41761267]]) >>> y array([[ 1. , 0.87671107], [ 0.65239976, 0.41761267]]) >>> y.flags['OWNDATA'] False >>> x.flags['OWNDATA'] True >>> q.flags['OWNDATA'] False >>> np.may_share_memory(x,y) True >>> np.may_share_memory(x,q) False 

Since q does not reflect changes in the first element, for example x or y , it must somehow be the owner of the data (somehow explained below).

See the numpy-discussion mailing list . Q How can I find out if NumPy is creating a view or instance? , it is briefly said that just checking flags.owndata ndarray sometimes seems and, as you say, seems unreliable. This is because every ndarray also has a base attribute:

the ndarray base is a reference to another array if the memory occurred in another place (otherwise, the None base). Operation y.reshape(4) creates a copy, not a view, because step y is (8,16) . To convert it (C-adjacent) to (4,) , the memory pointer would have to jump 0->16->8->24 , which cannot be done in one step. Thus, q.base points to the memory cell generated by the forced copy-operation y.reshape , which has the same shape as y , but copied the elements and thus again has normal steps: (16, 8) . q.base is therefore not bound by any other name, as it was the result of a forced copy operation of y.reshape(4) . Only now the q.base object can be seen in the form (4,) , since this allows a step. q is really a representation on q.base .

For most people, it would be strange to see that q.flags.owndata is False because, as shown above, this is not a representation on y . However, this is a view of copy y . However, this copy of q.base is the data owner. So the flags are actually correct if you look carefully.

+5
Mar 05 '15 at 20:50
source share

I like to use .__array_interface__ .

 In [811]: x.__array_interface__ Out[811]: {'data': (149194496, False), 'descr': [('', '<f8')], 'shape': (4, 4), 'strides': None, 'typestr': '<f8', 'version': 3} In [813]: y.__array_interface__ Out[813]: {'data': (149194496, False), 'descr': [('', '<f8')], 'shape': (4, 4), 'strides': (8, 32), 'typestr': '<f8', 'version': 3} In [814]: x.strides Out[814]: (32, 8) In [815]: y.strides Out[815]: (8, 32) 

Transposition was performed by changing the course. The reference data pointer is the same.

 In [817]: q.__array_interface__ Out[817]: {'data': (165219304, False), 'descr': [('', '<f8')], 'shape': (16,), 'strides': None, 'typestr': '<f8', 'version': 3} 

So the q data is a copy (another pointer). Strides (8,) means that its elements are accessed by moving from one f8 to another. But a x.reshape(16) is a representation of x - because its data can be obtained with a simple step 8 .

To access the source data in q order, he will need a 32 byte step 3 times (down x rows), then go back to the beginning and step 8 in the second column x , then in increments of 3 rows, etc. Since striding does not work this way, it should work from a copy.

Note that y[0,0] modifies x[0,0] , but q[0] is independent of both.

While OWNDATA for q is false, it is True for y.ravel() and y.flatten() . I suspect that reshape() in this case makes a copy and then reformatts, and this is an intermediate copy that "owns" the data, q.base .

+2
Mar 05 '15 at 23:42
source share



All Articles