Đảo ngược các kích thước của ma trận thưa thớt.
Tham sốersaxesnone, tùy chọnaxesNone, optionalLập luận này chỉ trong chữ ký chỉ vì lý do tương thích numpy. Không vượt qua bất cứ điều gì ngoại trừ giá trị mặc định.
Copybool, tùy chọnbool, optionalCho biết liệu các thuộc tính của bản thân có nên được sao chép bất cứ khi nào có thể. Mức độ mà các thuộc tính được sao chép khác nhau tùy thuộc vào loại ma trận thưa thớt đang được sử dụng.
ReturnSel với kích thước đảo ngược.pself with the dimensions reversed.Tạo mảng của bạn [với các kích thước khác nhau để làm nổi bật sự mơ hồ chuyển đổi]:
In [859]: X=[sparse.lil_matrix[[3,4]] for i in range[2]]
In [860]: X
Out[860]:
[,
]
In [861]: X[0][0,0]=1
In [862]: X[1][0,0]=1
In [864]: X[1][0,1]=1
Bây giờ dữ liệu thô cho danh sách ma trận này là:
In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
Nếu tôi tạo một mảng 3D từ X
:
In [870]: elem = np.array[[a.A for a in X]]
In [871]: elem
Out[871]:
array[[[[ 1., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]],
[[ 1., 1., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]]]]
Sự chuyển đổi thích hợp của 3D này là một mảng [4,3,2]:
In [872]: elem.T
Out[872]:
array[[[[ 1., 1.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 1.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]]]]
Có thể định hình lại có thể được thực hiện, nhưng có xu hướng xáo trộn các giá trị xung quanh:
In [873]: elem.reshape[3,4,2]
Out[873]:
array[[[[ 1., 0.],
[ 0., 0.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 1., 1.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.],
[ 0., 0.]]]]
Trong mọi trường hợp, nếu X
lớn đến mức
In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
0 gây ra lỗi bộ nhớ, tôi nghĩ sự thay thế duy nhất của bạn là tạo danh sách In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
1 mới [ví dụ: 4 ma trận hình dạng [3,2]] và sao chép các giá trị từ ma trận ban đầu. Để bắt đầu, tôi đã cố gắng sử dụng các thuộc tính In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
2 mà tôi liệt kê ở trên, nhưng có thể một trong các định dạng khác thuận tiện hơn. Mã In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
3 thường sử dụng định dạng In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
4 Xây dựng một ma trận mới từ mã nhỏ hơn [ví dụ như nhìn vào mã In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
5].Đối với một cái gì đó không chuẩn như thế này, tôi nghi ngờ nếu có bất kỳ giải pháp chứng khoán dễ dàng nào. Chúng tôi thường không trộn lẫn và kết hợp các yếu tố của một danh sách các ma trận thưa thớt.
Trong bài viết này, chúng tôi sẽ xem xét cấu trúc dữ liệu được sử dụng để thực hiện ma trận thưa thớt trong Python. Bắt đầu nào.
Ma trận thưa thớt là gì?
Một ma trận thưa thớt là một loại ma trận có nhiều phần tử bằng không. Đó là, hầu hết các mục trong ma trận thưa thớt là số 0, do đó tên và vì vậy hầu hết bộ nhớ bị chiếm bởi một ma trận thưa thớt tạo thành số 0. Ví dụ: ma trận sau đây là ma trận thưa thớt:
A = [ [0, 4, 0, 0], [2, 0, 0, 5], [0, 0, 0, 0], [0, 0, 0, 1] ]
Như bạn có thể thấy, ngoại trừ bốn mục, phần còn lại là số 0 và những số 0 dự phòng này chiếm rất nhiều không gian trong bộ nhớ.
Một ma trận thưa thớt là một cách tối ưu hóa để lưu trữ các ma trận như vậy. Nó thực chất là một danh sách các mục không phải là số không. Mỗi hàng trong ma trận thưa thớt lưu trữ hàng và cột của phần tử khác không, cũng như chính phần tử khác không.
Vì vậy, đối với ma trận A trên, đối tác thưa thớt sẽ trông như thế này:
A = [ [0, 1, 4], [1, 0, 2], [1, 3, 5], [3, 3, 1] ]
Trong hàng đầu tiên, các phần tử là 0, 1 và 4, vì vậy mục 4 là ở chỉ mục 0, 1. Tương tự, 2 là tại chỉ số 1, 0; vân vân.
Rõ ràng là phiên bản này chiếm ít không gian hơn phiên bản bình thường và trong trường hợp ma trận là rất lớn, một ma trận thưa thớt sẽ mất ít không gian hơn đáng kể.
Để sử dụng ma trận này như một ma trận thưa thớt, chúng ta cần thực hiện nó trong một lớp và xác định các phương thức để đầu vào, in, bổ sung, trừ, nhân, v.v.
Chúng ta hãy nhìn vào định nghĩa lớp của một ma trận thưa thớt trong Python.
class Sparse: def __init__[self, rows, columns]: self._matrix = [] self._num = 0 self._rows = rows self._columns = columns def __repr__[self]: prnt = f"Shape: {self._rows} x {self._columns}\n" for lst in self._matrix: prnt += lst.__repr__[] + '\n' prnt += f"Total: {self._num}" return prnt def insert[self, row, column, value]: if row < 0 | column < 0 | row >= self._rows | column >= self._columns: raise ValueError["Invalid row or column"] if[value == 0]: raise ValueError["Zeroes are not included in a sparse matrix"] filled = False for i in range[self._num]: if[self._matrix[i][0] < row]: continue elif[self._matrix[i][0] > row]: self._matrix.insert[i, [row, column, value]] self._num += 1 filled = True break elif[self._matrix[i][1] < column]: continue elif[self._matrix[i][1] > column]: self._matrix.insert[i, [row, column, value]] self._num += 1 filled = True break else: raise ValueError["The position is already filled"] if[filled == False]: self._matrix.append[[row, column, value]] self._num += 1 return def remove[self, row, column]: if row < 0 | column < 0 | row >= self._rows | column >= self._columns: raise ValueError["Invalid row or column"] for i in range[num]: if[self._matrix[i][0] == row | self._matrix[i][1] == column]: return pop[i] return None def size[self]: return self._num def shape[self]: return tuple[[self._rows, self._columns]] def display[self]: print[self] def add[self, obj]: if[isinstance[obj, Sparse] != True]: raise TypeError["add[] method needs an object of type Sparse"] if[self.shape[] == obj.shape[]]: result = Sparse[self._rows, self._columns] else: raise ValueError["Invalid row or columns"] i = 0 j = 0 k = 0 while[[i < self._num] & [j < obj._num]]: if[self._matrix[i][0] < obj._matrix[j][0]]: result._matrix.insert[k, self._matrix[i]] k += 1 i += 1 elif[self._matrix[i][0] > obj._matrix[j][0]]: result._matrix.insert[k, obj._matrix[j]] k += 1 j += 1 elif[self._matrix[i][1] < obj._matrix[j][1]]: result._matrix.insert[k, self._matrix[i]] k += 1 i += 1 elif[self._matrix[i][1] > obj._matrix[j][1]]: result._matrix.insert[k, obj._matrix[j]] k += 1 j += 1 else: result._matrix.insert[k, list[[self._matrix[i][0], self._matrix[i][1], self._matrix[i][2] + obj._matrix[j][2]]]] k += 1 i += 1 j += 1 while[i < self._num]: result._matrix.insert[k, self._matrix[i]] k += 1 i += 1 while[j < obj._num]: result._matrix.insert[k, obj._matrix[j]] k += 1 j += 1 result._num = k return result def fast_transpose[self]: occurrence = [] index = [] for i in range[self._columns]: occurrence.append[0] for i in range[self._num]: occurrence[self._matrix[i][1]] += 1 index.append[0] for i in range[1, self._columns]: index.append[index[i-1] + occurrence[i-1]] result = Sparse[self._columns, self._rows] result._num = self._num for i in range[self._num]: result._matrix.append[list[]] for i in range[self._num]: result._matrix[index[self._matrix[i][1]]] = list[[self._matrix[i][1], self._matrix[i][0], self._matrix[i][2]]] index[self._matrix[i][1]] += 1 return result
Định nghĩa trên là khá lớn, vì vậy chúng tôi sẽ xem từng hàm một:
1. Phương pháp In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
6
In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
Đối với mỗi ma trận thưa thớt, chúng tôi yêu cầu số lượng hàng và cột ban đầu, được truyền cho hàm tạo, tạo ra một ma trận thưa thớt trống rỗng.
2. Phương pháp In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
7
In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
Điều này sẽ trả về một chuỗi sẽ được in trên chuỗi khi
In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
8 được gọi trên đối tượng. Trong trường hợp của chúng tôi, chúng tôi đang in hình dạng và kích thước của ma trận, cũng như ma trận thưa thớt thực tế.3. Chèn và loại bỏ vào ma trận thưa thớt
Để chèn một mục khác không ở một vị trí nhất định, chúng tôi chỉ cần đi qua ma trận để tìm vị trí mới của mục chính và chèn nó ở đó. Chúng tôi so sánh hàng trước, và sau đó nếu chúng tôi thấy rằng các hàng khớp, chúng tôi so sánh cột. Một trong số này phải khác nhau, nếu không, chúng tôi nêu ra một ngoại lệ.
Trước khi thực hiện tất cả những điều này, chúng ta cần xác nhận đầu vào, mục đã cho không phải bằng không và các vị trí phải nằm trong ma trận.
Để loại bỏ một mục tại một vị trí nhất định, quy trình cũng đơn giản như tìm vị trí trong ma trận và bật toàn bộ hàng.
4. Bổ sung hai ma trận thưa thớt
Thêm hai ma trận thưa thớt rất giống với việc hợp nhất hai danh sách được sắp xếp.
Hai ma trận về cơ bản là danh sách có chứa các danh sách khác đại diện cho các hàng. Và các danh sách bên trong này được sắp xếp theo nghĩa là các mục thứ nhất và thứ hai của mỗi danh sách [chỉ số hàng và cột của mỗi giá trị] được sắp xếp theo thứ tự tăng dần.
Chúng tôi tạo ba chỉ mục:
9, In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
0 và In [870]: elem = np.array[[a.A for a in X]]
In [871]: elem
Out[871]:
array[[[[ 1., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]],
[[ 1., 1., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]]]]
1.In [870]: elem = np.array[[a.A for a in X]]
In [871]: elem
Out[871]:
array[[[[ 1., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]],
[[ 1., 1., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]]]]
9 là chỉ mục của mục tiếp theo trong ma trận đầu tiên.In [866]: X[0].rows Out[866]: array[[[0], [], []], dtype=object] In [867]: X[0].data Out[867]: array[[[1.0], [], []], dtype=object] In [868]: X[1].rows Out[868]: array[[[0, 1], [], []], dtype=object] In [869]: X[1].data Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
0 là chỉ mục của mục tiếp theo trong ma trận thứ hai.In [870]: elem = np.array[[a.A for a in X]] In [871]: elem Out[871]: array[[[[ 1., 0., 0., 0.], [ 0., 0., 0., 0.], [ 0., 0., 0., 0.]], [[ 1., 1., 0., 0.], [ 0., 0., 0., 0.], [ 0., 0., 0., 0.]]]]
1 là chỉ mục của mục tiếp theo trong ma trận kết quả.In [870]: elem = np.array[[a.A for a in X]] In [871]: elem Out[871]: array[[[[ 1., 0., 0., 0.], [ 0., 0., 0., 0.], [ 0., 0., 0., 0.]], [[ 1., 1., 0., 0.], [ 0., 0., 0., 0.], [ 0., 0., 0., 0.]]]]
Sau đó, chúng tôi so sánh mục ____ 19 trong ma trận đầu tiên và mục ____ 20 trong ma trận thứ hai. Bất cứ mục nào được cho là xuất hiện đầu tiên dựa trên chỉ mục hàng và cột của nó được chèn vào ma trận kết quả và chúng tôi tăng các chỉ mục tương ứng.
Nếu cả hai mục đều có cùng một hàng và chỉ mục cột, thì chắc chắn chúng cần được thêm vào với nhau và một khi chúng tôi làm điều đó, tổng của chúng được chèn vào ma trận kết quả.
Cuối cùng, một trong các ma trận đầu vào sẽ được hoàn thành, tại thời điểm này, chúng tôi chỉ cần chèn tất cả các mục từ ma trận khác vào ma trận kết quả và chúng tôi sẽ có tổng của hai ma trận.
5. Chuyển đổi nhanh một ma trận thưa thớt
Việc chuyển một ma trận thưa thớt là đủ đơn giản, chúng ta chỉ cần trao đổi các giá trị hàng và cột và sau đó sắp xếp các hàng trong ma trận thưa thớt. Nhưng một hoạt động như vậy rất không hiệu quả và cách chế tạo một ma trận thưa thớt, chúng ta có một cách nhanh hơn nhiều để chuyển ma trận này.
Trước tiên chúng tôi sẽ tạo hai danh sách sẽ hỗ trợ trong thuật toán.
Danh sách đầu tiên được gọi là
In [870]: elem = np.array[[a.A for a in X]]
In [871]: elem
Out[871]:
array[[[[ 1., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]],
[[ 1., 1., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]]]]
7 và nó sẽ lưu trữ số lần mỗi chỉ mục cột xuất hiện trong ma trận thưa thớt. Vì vậy, kích thước của nó sẽ là kích thước cột của ma trận thưa thớt và mỗi chỉ mục sẽ đại diện cho cột đó. Ban đầu, nó sẽ được lấp đầy bằng các số 0, và sau đó, chúng tôi sẽ đi qua ma trận thưa thớt và tìm kiếm các giá trị cột của từng mục và chúng tôi sẽ tăng chỉ mục đó trong danh sách In [870]: elem = np.array[[a.A for a in X]]
In [871]: elem
Out[871]:
array[[[[ 1., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]],
[[ 1., 1., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]]]]
7.Danh sách thứ hai được gọi là danh sách
In [870]: elem = np.array[[a.A for a in X]]
In [871]: elem
Out[871]:
array[[[[ 1., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]],
[[ 1., 1., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]]]]
9. Trong danh sách này, chúng tôi sẽ lưu trữ chỉ số kết quả của từng mục trong ma trận thưa thớt ban đầu khi nó được chuyển đổi thành ma trận thưa thớt. Vì vậy, In [872]: elem.T
Out[872]:
array[[[[ 1., 1.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 1.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]]]]
0 sẽ có chỉ mục mới của mục đầu tiên với chỉ mục cột In [866]: X[0].rows
Out[866]: array[[[0], [], []], dtype=object]
In [867]: X[0].data
Out[867]: array[[[1.0], [], []], dtype=object]
In [868]: X[1].rows
Out[868]: array[[[0, 1], [], []], dtype=object]
In [869]: X[1].data
Out[869]: array[[[1.0, 1.0], [], []], dtype=object]
9 trong ma trận gốc. Để thực hiện việc này, trước tiên chúng tôi lưu trữ 0 tại Index [0], có nghĩa là mục đầu tiên có chỉ mục cột 0 trong ma trận gốc sẽ nằm trong chỉ số 0, trong ma trận chuyển vị. Sau đó để tính toán In [872]: elem.T
Out[872]:
array[[[[ 1., 1.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 1.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]]]]
0, chúng tôi thêm In [872]: elem.T
Out[872]:
array[[[[ 1., 1.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 1.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]]]]
3 và In [872]: elem.T
Out[872]:
array[[[[ 1., 1.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 1.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]],
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.]]]]
4.Sau đó, chúng tôi xem xét từng mục trong ma trận thưa thớt, chúng tôi tìm thấy chỉ mục cột của mục, chúng tôi tìm kiếm giá trị trong danh sách
In [870]: elem = np.array[[a.A for a in X]]
In [871]: elem
Out[871]:
array[[[[ 1., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]],
[[ 1., 1., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]]]]
9 tại chỉ mục đó và chúng tôi sử dụng giá trị đó làm chỉ mục mới trong ma trận chuyển tiếp. Chúng tôi tăng giá trị chỉ mục mà chúng tôi đã sử dụng để mục tiếp theo có cùng chỉ mục cột sẽ chuyển đến chỉ mục tiếp theo trong chuyển vị.After this, we increment the index value we used so that the next item with the same column index will go to the next index in the transpose.
Làm điều này, chúng ta có thể chuyển một ma trận thưa thớt rất hiệu quả.
Đầu ra
Đầu tiên, chúng tôi tạo ra hai ma trận thưa thớt:
Bây giờ chúng tôi thực hiện các hoạt động bổ sung và chuyển đổi nhanh:
Sự kết luận
Trong trường hợp ma trận chủ yếu chứa đầy số 0, ma trận thưa thớt sử dụng ít lưu trữ hơn nhiều và hiệu quả hơn nhiều. Chúng tôi đã thảo luận về những điều này là gì, làm thế nào để tạo ra chúng và sau đó thực hiện chúng, và cuối cùng, chúng tôi đã xác nhận rằng với đầu ra mà chúng tôi có được bằng cách chạy mã của chúng tôi.