Avoid implicit conversion to matrix in numpy operations

Is there a way to globally avoid the appearance of matrixnumpy in any of the results? For example, if you have xhow numpy.ndarrayand yhow scipy.sparse.csc_matrix, and you say x += y, xit will subsequently become matrix. Is there any way to prevent this, i.e. Save xa ndarrayand, in general, continue to use ndarrayin all places where it is created matrix?

+4
source share
2 answers

I added a tag scipy, this is a problem scipy.sparse, not np.matrix.

In [250]: y=sparse.csr_matrix([[0,1],[1,0]])
In [251]: x=np.arange(2)
In [252]: y+x
Out[252]: 
matrix([[0, 2],
        [1, 1]])

sparse matrix + array =>

( , np.matrix np.ndarray. sparse.csr_matrix . numpy, ).

In [255]: x += y
In [256]: x
Out[256]: 
matrix([[0, 2],
        [1, 1]])

; x = x+y x, x.

y matrix, . 1d- 2d.

In [258]: x += y.todense()
...
ValueError: non-broadcastable output operand with shape (2,) doesn't match the broadcast shape (2,2)

x 2d - :

In [259]: x=np.eye(2)
In [260]: x
Out[260]: 
array([[ 1.,  0.],
       [ 0.,  1.]])
In [261]: x += y.todense()
In [262]: x
Out[262]: 
array([[ 1.,  1.],
       [ 1.,  1.]])

/ . . , . y+1, , .

, , - x+=..., y .

In [265]: x += y.A
In [266]: x
Out[266]: 
array([[ 1.,  2.],
       [ 2.,  1.]])

, .

( scipy github ).


scipy/sparse/compress.py csr. x+y x.__add__(y), y.__add__(x). x+=y x.__iadd__(y). __iadd__ ndarray.

:

def __add__(self,other):
    # First check if argument is a scalar
    if isscalarlike(other):
        if other == 0:
            return self.copy()
        else:  # Now we would add this scalar to every element.
            raise NotImplementedError('adding a nonzero scalar to a '
                                      'sparse matrix is not supported')
    elif isspmatrix(other):
        if (other.shape != self.shape):
            raise ValueError("inconsistent shapes")

        return self._binopt(other,'_plus_')
    elif isdense(other):
        # Convert this matrix to a dense matrix and add them
        return self.todense() + other
    else:
        return NotImplemented

, y+x y.todense() + x. x+y .

+=, , (array np.matrix) . , .

, , . y+y , . y+=y NotImplmenentedError sparse.base.__iadd__.


, , y (2,2).

In [348]: x=np.eye(2)
In [349]: x+y
Out[349]: 
matrix([[ 1.,  1.],
        [ 1.,  1.]])
In [350]: x+y.todense()
Out[350]: 
matrix([[ 1.,  1.],
        [ 1.,  1.]])

, x x ( )

In [351]: x[:] = x+y
In [352]: x
Out[352]: 
array([[ 1.,  1.],
       [ 1.,  1.]])

+= :

In [353]: x += y.todense()
In [354]: x
Out[354]: 
array([[ 1.,  2.],
       [ 2.,  1.]])

- +=sparse x

In [355]: x += y
In [356]: x
Out[356]: 
matrix([[ 1.,  3.],
        [ 3.,  1.]])

id(x) x.__array_interface__ , x += y x. , x np.matrix. , += inplace. x += y.todense() - inplace.

+2

, ; https://github.com/scipy/scipy/issues/7826

.


X += c * Y todense.
inc( various array / matrix, various sparse ) , .
def inc( X, Y, c=1. ):
    """ X += c * Y, X Y sparse or dense """
    if (not hasattr( X, "indices" )  # dense += sparse
    and hasattr( Y, "indices" )):
        # inc an ndarray view, because ndarry += sparse -> matrix --
        X = getattr( X, "A", X ).squeeze()
        X[Y.indices] += c * Y.data
    else:
        X += c * Y  # sparse + different sparse: SparseEfficiencyWarning
    return X
0

Source: https://habr.com/ru/post/1629847/


All Articles