Bagaimana cara mengonversi matriks renggang scipy secara efisien menjadi matriks renggang sympy?
Saya memiliki matriks A dengan properti berikut.
<1047x1047 sparse matrix of type '<class 'numpy.float64'>'
with 888344 stored elements in Compressed Sparse Column format>
A memiliki konten ini.
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]])
Sekarang saya mencoba untuk membuat matriks renggang dari matriks renggang scipy.
from sympy.matrices import SparseMatrix
A = SparseMatrix(A)
Tapi saya mendapatkan pesan kesalahan ini.
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().
Saya bingung karena matriks ini tidak memiliki entri logis.
Terima kasih atas bantuannya!
Jawaban
Kesalahan
Jika Anda mendapatkan kesalahan yang tidak Anda mengerti, luangkan sedikit waktu untuk melihat traceback. Atau setidaknya tunjukkan pada kami!
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().
Pemahaman penuh memerlukan pembacaan sympy
kode, tetapi tampilan sepintas menunjukkan bahwa ia mencoba menangani masukan Anda sebagai "matriks penuh", dan melihat baris. Kesalahan ini bukan akibat Anda melakukan operasi logika pada entri, tetapi itu sympy
adalah melakukan uji logika pada matriks renggang Anda. Ini mencoba untuk memeriksa apakah baris tersebut kosong (sehingga dapat melewatinya).
SparseMatrix
docs mungkin bukan yang paling jelas, tetapi sebagian besar contoh menampilkan dikt poin, atau larik datar dari SEMUA nilai plus bentuk, atau daftar daftar yang tidak rata. Saya menduga itu mencoba memperlakukan matriks Anda seperti itu, melihatnya baris demi baris.
Tetapi baris M
itu sendiri merupakan matriks renggang:
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>,
...]
Dan mencoba untuk memeriksa apakah baris itu kosong not row
menghasilkan kesalahan ini:
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().
Jadi jelas SparseMatrix
tidak dapat menangani scipy.sparse
matriks sebagaimana adanya (setidaknya tidak dalam format csr
atau csc
, dan mungkin bukan yang lain. Plus scipy.sparse
tidak disebutkan di mana pun di SparseMatrix
dokumen!
dari larik padat
Mengonversi matriks renggang ke padanan padatnya dapat dilakukan:
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 ⎤
...⎦
Atau daftar daftar:
SparseMatrix(M.A.tolist())
dari dict
The dok
Format menyimpan matriks jarang sebagai dict
, yang kemudian dapat
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}
Yang berfungsi dengan baik sebagai masukan:
SparseMatrix(5,5,dict(M.todok()))
Saya tidak tahu mana yang paling efisien. Umumnya saat bekerja dengan sympy
kami (atau setidaknya saya) tidak khawatir tentang efisiensi. Cukup membuatnya bekerja sudah cukup. Efisiensi lebih relevan di numpy/scipy
mana array bisa berukuran besar, dan menggunakan metode numpy yang dikompilasi cepat membuat perbedaan besar dalam kecepatan.
Akhirnya - numpy
dan sympy
tidak terintegrasi. Itu berlaku juga untuk versi renggang. sympy
dibangun di atas Python, bukan numpy
. Jadi masukan dalam bentuk daftar dan dicts paling masuk akal.
from sympy.matrices import SparseMatrix
import scipy.sparse as sps
A = sps.random(100, 10, format="dok")
B = SparseMatrix(100, 10, dict(A.items()))
Dari perspektif seseorang yang menyukai struktur memori yang efisien, ini seperti menatap ke dalam jurang. Tapi itu akan berhasil.
Ini adalah versi sederhana dari kesalahan Anda.
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))
Begitu A
juga matriks renggang dengan 6 elemen:
<3x3 sparse matrix of type '<class 'numpy.intc'>'
with 6 stored elements in Compressed Sparse Column format>
Memanggilnya SparseMatrix()
mengembalikan jenis kesalahan yang sama yang Anda miliki. Anda mungkin ingin mengonversi A
ke array numpy terlebih dahulu:
>>> SparseMatrix(A.todense())
Matrix([
[1, 0, 2],
[0, 0, 3],
[4, 5, 6]])