2015-11-04 7 views
45

Alla ricerca di un modo per identificare in modo affidabile se un oggetto numpy è una vista.numpy: indicatore affidabile (non conservativo) se la matrice numpy è vista

Domande correlate sono venuto molte volte in passato (here, here, here), e la gente ha offerto alcune soluzioni, ma tutti sembrano avere problemi:

  • Il test utilizzato in pandas ora è quello di chiamare qualcosa una vista se my_array.base is not None. Questo sembra sempre prendere punti di vista, ma offre anche molti falsi positivi (situazioni in cui segnala qualcosa è una vista anche se non lo è).
  • numpy.may_share_memory() verificherà la presenza di due array specifici, ma non risponderò genericamente
    • (@RobertKurn dice era migliore strumento a partire dal 2012 -? Eventuali modifiche)
  • flags['OWNDATA']) è reported (third comment first answer) a fallire nel alcuni casi.

(Il motivo del mio interesse è che sto lavorando per l'attuazione copy-on-write per i panda, e un indicatore conservatore sta portando a un eccesso di copiatura.)

+4

discussione pertinente sul tracker github numpy: https://github.com/numpy/numpy/issues/5604 –

+3

Le situazioni descritte come falsi positivi sembrano essere quando un'operazione che "crea una copia" restituisce effettivamente una vista di una copia. Se questo è da considerarsi "non una vista", si potrebbe provare a controllare il refcount della 'base' dell'array per vedere se ci sono altri riferimenti ad esso, ma ciò non sarà perfetto. Non penso sia possibile rilevare in modo affidabile questo tipo di cose. – user2357112

+6

Vedi anche questa recente domanda SO, http://stackoverflow.com/questions/33467477/how-to-find-all-variables-with-identical-id. Menziona una nuova funzione, 'np.shares_memory'. Ma ho notato che una cosa è confrontare 2 variabili conosciute, un'altra è chiedere un array condivide il buffer di dati con qualsiasi altro array. – hpaulj

risposta

1

A seconda delle vostre usanze, flags['OWNDATA'] farebbe il lavoro In effetti, non ci sono problemi con il tuo link. Non fallisce in alcuni casi. Farà sempre ciò che dovrebbe fare.

Secondo http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.require.html: il flag "garantisce un array che possiede i propri dati".

Nel vostro "controesempio", usano il codice:

print (b.flags['OWNDATA']) #False -- apparently this is a view 
e = np.ravel(b[:, 2]) 
print (e.flags['OWNDATA']) #True -- Apparently this is a new numpy object. 

Ma, è il comportamento normale per essere vero nel secondo caso.

Viene dalla definizione di ravel (da http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.ravel.html).

Restituisce un array appiattito contiguo. Viene restituito un array 1-D contenente gli elementi dell'input. Una copia viene effettuata solo se necessario.

Qui è necessaria una copia, quindi viene eseguita una copia. Quindi, la variabile e possiede davvero i propri dati. Non è una "vista di b", "un riferimento a b", "un alias a una parte di b". È un vero nuovo array che contiene una copia di alcuni elementi di b.

Quindi, Penso che sia impossibile senza tracciare l'intera origine dei dati per rilevare quel tipo di comportamento. Credo che dovresti essere in grado di costruire il tuo programma con quella bandiera.