[PyTorch] Sparce한 Matrix를 효과적으로 표현하는 방법 - COO, CSR, CSC, LIL

1 minute read

torch.Tensor

가장 기본적으로 우리가 알고 있는 PyTorch에서 제공하는 Tensor은 NumPy의 ndarrays와 유사하다. Tensor은 ndarray와 다르게 GPU를 이용해 연산 가속을 할 수 있다.

torch.Tensor()

>>> x = torch.Tensor(3,5)
>>> x

ouput:

tensor([[ 4.4587e-04,  2.3181e-01,  1.0615e+21,  4.5569e-41,  1.7318e+16],
        [ 4.5569e-41,  3.2613e+34, -6.2364e+35,  0.0000e+00,  0.0000e+00],
        [ 0.0000e+00,  0.0000e+00,  7.4376e-38,  0.0000e+00,  0.0000e+00]])

torch.rand()

x = torch.rand(3,5)
x

ouput

tensor([[0.9336, 0.8689, 0.9331, 0.4252, 0.2126],
        [0.4610, 0.4314, 0.6466, 0.8054, 0.1349],
        [0.7099, 0.3162, 0.1428, 0.3309, 0.3732]])

torch.Tensor을 사용하다보면 sparce matrix를 해결하기 위한 방법이 필요한 경우가 있다. 예를 들면 MovieLens와 같이 User-Item Marix를 만들어서 모델을 돌릴 때, user, item이 몇백만개, 단위로 가게 되면 2차원 텐서를 만들려고 하면 메모리 문제가 필연적으로 발생한다.

(sparce한 matrix 형태)

대부분의 값이 비어있는데 메모리를 낭비하게 된다. 이러한 문제를 해결하기 위해 non-zero entries들만 저장할 수 있도록 하는 다양한 방법들이 존재한다.

Sparce한 데이터를 표현하는 방법들

1. COO

Coordinate list(COO)는 (row, columnn, value)의 리스트 형태로 저장한다.


2. CSR / CSC

CSR

행의 데이터를 줄이면 Compressed sparce row(CSR) 또는 Compressed row storage(CRS)라고 불린다. CSR format으로 표현하면 아래와 같다.

V = [ 5 8 3 6 ]
COL_INDEX = [ 0 1 2 1 ]
ROW_INDEX = [ 0 1 2 3 4 ] 

V = [ 10 20 30 40 50 60 70 80 ]
COL_INDEX = [  0  1  1  3  2  3  4  5 ]   
ROW_INDEX = [  0  2  4  7  8 ]

CSC

위에서 언급한 CSR과 동일한 방법으로 열을 줄인 것이다.

3. LIL

List of List

PyTorch에 적용

공식문서에 나와있는 대로 PyTorch는 이러한

torch.sparse_coo_tensor, .to_dense()

  • torch.sparse_coo_tensor() : 2차원의 indicies 벡터, values 벡터, 텐서 차원 이렇게 3개의 인자를 건내주면 됨
    >>> i = [[0, 1, 1],
           [2, 0, 2]]
    >>> v =  [3, 4, 5]
    >>> s = torch.sparse_coo_tensor(i, v, (2,3))
    >>> s
    tensor(indices=tensor([[0, 1, 1],
                         [2, 0, 2]]),
         values=tensor([3, 4, 5]),
         size=(2, 3), nnz=3, layout=torch.sparse_coo)
    
  • s.to_dense()
    >>> s.to_dense()
    tensor([[0, 0, 3],
          [4, 0, 5]])
    
from scipy.sparse import coo_matrix

coo = coo_matrix(([3,4,5],[0,1,1],[2,0,2]))

values = coo.data
indices = np.vstack((coo.row, coo.col))

i = torch.LongTensor(indicies)
v = torch.FloatTensor(values)
shape = coo.shape

output

0 0 3
4 0 5
[torch.FloatTensor of size 2x3]

CSR

  • pytorch로 csr을 하기는

Comments