2011-06-03 9 views
5

Estoy trabajando en un algoritmo que usa bloques diagonales y primeros bloques fuera de la diagonal de una matriz dispersa diagonal de bloques grande (será e06 x e06).Cómo crear una referencia de vista/pitón en una matriz escasa scipy?

Ahora creo un dict que almacena los bloques de tal manera que pueda acceder a los bloques de forma similar a la matriz. Por ejemplo B [0,0] (5x5) da el primer bloque de la matriz A (20x20), asumiendo bloques de 5x5 y esa matriz A es del tipo sparse.lil.

Esto funciona bien, pero lleva demasiado tiempo correr también. Es ineficiente porque copia los datos, ya que esta referencia reveló para mi asombro: GetItem Method

¿Hay alguna forma de almacenar una vista en una matriz dispersa en un dict? Me gustaría cambiar el contenido y aún así poder usar los mismos identificadores. Está bien si lleva un poco más de tiempo, ya que solo debería hacerse una vez. Los bloques tendrán muchas dimensiones y formas diferentes.

Respuesta

4

Hasta donde yo sé, todas las diversas matrices dispersas en scipy.sparse devuelven copias en lugar de una vista de algún tipo. (¡Sin embargo, algunos de los otros pueden ser mucho más rápidos al hacerlo que lil_matrix!)

Una forma de hacer lo que usted desea es simplemente trabajar con objetos de corte. Por ejemplo:

import scipy.sparse 

class SparseBlocks(object): 
    def __init__(self, data, chunksize=5): 
     self.data = data 
     self.chunksize = chunksize 
    def _convert_slices(self, slices): 
     newslices = [] 
     for axslice in slices: 
      if isinstance(axslice, slice): 
       start, stop = axslice.start, axslice.stop 
       if axslice.start is not None: 
        start *= self.chunksize 
       if axslice.stop is not None: 
        stop *= self.chunksize 
       axslice = slice(start, stop, None) 
      elif axslice is not None: 
       axslice = slice(axslice, axslice+self.chunksize) 
      newslices.append(axslice) 
     return tuple(newslices) 

    def __getitem__(self, item): 
     item = self._convert_slices(item) 
     return self.data.__getitem__(item) 
    def __setitem__(self, item, value): 
     item = self._convert_slices(item) 
     return self.data.__setitem__(item, value) 

data = scipy.sparse.lil_matrix((20,20)) 
s = SparseBlocks(data) 
s[0,0] = 1 
print s.data 

Ahora, cada vez que modificamos s[whatever] modificará s.data del trozo apropiado. En otras palabras, s[0,0] devolverá o establecerá s.data[:5, :5], y así sucesivamente.

+1

Bonito, parece justo lo que necesitaba, lo siento por el retraso en responder estoy tratando de modificar el código para aceptar múltiples bloques de diferentes tamaños para una matriz. No me ayudes todavía, quiero resolverlo por mi cuenta :). Si me encuentro con más problemas, volveré. Gracias – Jonas

+0

Tenga en cuenta que desde la versión 0.11.0, SciPy tiene una (función diagonal de bloques) [docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.block_diag.html#scipy.sparse.block_diag] que se ve para ser útil aquí. – drevicko

Cuestiones relacionadas