Scipy seyrek matrisi bir sympy seyrek matrise verimli bir şekilde nasıl dönüştürebilirim?

Aug 19 2020

Aşağıdaki özelliklere sahip bir A matrisim var.

<1047x1047 sparse matrix of type '<class 'numpy.float64'>'
    with 888344 stored elements in Compressed Sparse Column format>

A bu içeriğe sahiptir.

array([[ 1.00000000e+00, -5.85786642e-17, -3.97082034e-17, ...,
         0.00000000e+00,  0.00000000e+00,  0.00000000e+00],
       [ 6.82195979e-17,  1.00000000e+00, -4.11166786e-17, ...,
         0.00000000e+00,  0.00000000e+00,  0.00000000e+00],
       [-4.98202332e-17,  1.13957868e-17,  1.00000000e+00, ...,
         0.00000000e+00,  0.00000000e+00,  0.00000000e+00],
       ...,
       [ 4.56847824e-15,  1.32261454e-14, -7.22890998e-15, ...,
         1.00000000e+00,  0.00000000e+00,  0.00000000e+00],
       [-9.11597396e-15, -2.28796167e-14,  1.26624823e-14, ...,
         0.00000000e+00,  1.00000000e+00,  0.00000000e+00],
       [ 1.80765584e-14,  1.93779820e-14, -1.36520100e-14, ...,
         0.00000000e+00,  0.00000000e+00,  1.00000000e+00]])

Şimdi bu scipy seyrek matristen bir sympy seyrek matris yaratmaya çalışıyorum .

from sympy.matrices import SparseMatrix
A = SparseMatrix(A)

Ama bu hata mesajını alıyorum.

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().

Kafam karıştı çünkü bu matrisin mantıksal girişi yok.

Herhangi bir yardım için teşekkürler!

Yanıtlar

3 hpaulj Aug 19 2020 at 02:26

Hata

Anlamadığınız bir hata aldığınızda, geri dönüşe bakmak için biraz zaman ayırın. Ya da en azından bize gösterin!

In [288]: M = sparse.random(5,5,.2, 'csr')                                                           

In [289]: M                                                                                          
Out[289]: 
<5x5 sparse matrix of type '<class 'numpy.float64'>'
    with 5 stored elements in Compressed Sparse Row format>

In [290]: print(M)                                                                                   
  (1, 1)    0.17737340878962138
  (2, 2)    0.12362174819457106
  (2, 3)    0.24324155883057885
  (3, 0)    0.7666429046432961
  (3, 4)    0.21848551209470246

In [291]: SparseMatrix(M)                                                                            
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-291-cca56ea35868> in <module>
----> 1 SparseMatrix(M)

/usr/local/lib/python3.6/dist-packages/sympy/matrices/sparse.py in __new__(cls, *args, **kwargs)
    206             else:
    207                 # handle full matrix forms with _handle_creation_inputs
--> 208                 r, c, _list = Matrix._handle_creation_inputs(*args)
    209                 self.rows = r
    210                 self.cols = c

/usr/local/lib/python3.6/dist-packages/sympy/matrices/matrices.py in _handle_creation_inputs(cls, *args, **kwargs)
   1070                             if 0 in row.shape:
   1071                                 continue
-> 1072                         elif not row:
   1073                             continue
   1074 

/usr/local/lib/python3.6/dist-packages/scipy/sparse/base.py in __bool__(self)
    281             return self.nnz != 0
    282         else:
--> 283             raise ValueError("The truth value of an array with more than one "
    284                              "element is ambiguous. Use a.any() or a.all().")
    285     __nonzero__ = __bool__

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().

Tam bir anlayış, sympykodu okumayı gerektirir , ancak üstünkörü bir bakış, onun girdinizi "tam matris" olarak işlemeye çalıştığını gösterir ve satırlara bakar. Hata, girişler üzerinde mantıksal işlemler yapmanın bir sonucu değildir, ancak bu sympyseyrek matrisiniz üzerinde mantıksal bir test yapmanızdır. Satırın boş olup olmadığını kontrol etmeye çalışıyor (böylece atlayabilir).

SparseMatrixbelgeler en net olmayabilir, ancak çoğu örnek ya bir nokta diktesi ya da TÜM değerler artı şekilden oluşan düz bir dizi ya da düzensiz bir liste listesi gösterir. Matrisinize sıra sıra bakarak bu şekilde davranmaya çalıştığından şüpheleniyorum.

Ancak satırının Mkendisi seyrek bir matristir:

In [295]: [row for row in M]                                                                         
Out[295]: 
[<1x5 sparse matrix of type '<class 'numpy.float64'>'
    with 0 stored elements in Compressed Sparse Row format>,
 <1x5 sparse matrix of type '<class 'numpy.float64'>'
    with 1 stored elements in Compressed Sparse Row format>,
...]

Ve bu satırın boş olup olmadığını kontrol etmeye çalışmak not rowşu hatayı üretir:

In [296]: not [row for row in M][0]                                                                  
...
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().

Yani açıkça SparseMatrixbir scipy.sparsematrisi olduğu gibi işleyemez (en azından csrveya cscbiçiminde ve muhtemelen diğerlerinde değil. Ayrıca scipy.sparse, SparseMatrixbelgelerin hiçbir yerinde bahsedilmez !

yoğun diziden

Seyrek matrisi yoğun eşdeğerine dönüştürmek işe yarar:

In [297]: M.A                                                                                        
Out[297]: 
array([[0.        , 0.        , 0.        , 0.        , 0.        ],
       [0.        , 0.17737341, 0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.12362175, 0.24324156, 0.        ],
       [0.7666429 , 0.        , 0.        , 0.        , 0.21848551],
       [0.        , 0.        , 0.        , 0.        , 0.        ]])

In [298]: SparseMatrix(M.A)                                                                          
Out[298]: 
⎡        0                  0                  0                  0                  0        ⎤
...⎦

Veya bir liste listesi:

 SparseMatrix(M.A.tolist()) 

dikteden

dokBiçimi olarak seyrek bir matris saklar dict, sonra olabilen

In [305]: dict(M.todok())                                                                            
Out[305]: 
{(3, 0): 0.7666429046432961,
 (1, 1): 0.17737340878962138,
 (2, 2): 0.12362174819457106,
 (2, 3): 0.24324155883057885,
 (3, 4): 0.21848551209470246}

Girdi olarak iyi çalışan:

SparseMatrix(5,5,dict(M.todok()))

En verimli olanı bilmiyorum. Genel olarak sympybiz (veya en azından ben) çalışırken verimlilik konusunda endişelenmeyin. Sadece çalıştırmanız yeterli. Verimlilik, numpy/scipydizilerin büyük olabileceği yerlerde daha önemlidir ve hızlı derlenen numpy yöntemlerinin kullanılması hızda büyük bir fark yaratır.

Son olarak - numpyve sympyentegre edilmemiştir. Bu aynı zamanda seyrek versiyonlar için de geçerlidir. sympyPython üzerine inşa edilmiştir, değil numpy. Dolayısıyla liste ve dikteler şeklindeki girdiler en mantıklıdır.

1 CJR Aug 19 2020 at 01:24
from sympy.matrices import SparseMatrix
import scipy.sparse as sps

A = sps.random(100, 10, format="dok")
B = SparseMatrix(100, 10, dict(A.items()))

Verimli hafıza yapılarını seven birinin bakış açısından bu, uçuruma bakmak gibidir. Ama işe yarayacak.

1 mathfux Aug 19 2020 at 02:12

Bu, hatanızın basitleştirilmiş bir sürümüdür.

from scipy import sparse
row = np.array([0, 0, 1, 2, 2, 2])
col = np.array([0, 2, 2, 0, 1, 2])
data = np.array([1, 2, 3, 4, 5, 6])
A = sparse.csc_matrix((data, (row, col)), shape=(3, 3))

Yani A6 elemanlı seyrek matristir:

<3x3 sparse matrix of type '<class 'numpy.intc'>'
    with 6 stored elements in Compressed Sparse Column format>

SparseMatrix()Onu çağırmak , sahip olduğunuz aynı tür hatayı döndürür. Önce Anumpy dizisine dönüştürmek isteyebilirsiniz :

>>> SparseMatrix(A.todense())
Matrix([
[1, 0, 2],
[0, 0, 3],
[4, 5, 6]])