Python 및 NumPy를 사용하는 매우 큰 행렬


86

NumPy 는 매우 유용한 라이브러리이며, 그것을 사용함으로써 상당히 큰 (10000 x 10000) 행렬을 쉽게 처리 할 수 ​​있지만 훨씬 더 큰 행렬 (50000 x 50000의 행렬을 만들려고 시도)을 쉽게 처리 할 수 ​​있음을 발견했습니다. 실패). 분명히 이것은 엄청난 메모리 요구 사항 때문입니다.

몇 테라 바이트의 RAM없이 어떤 방식 으로든 NumPy (예 : 1 백만 x 1 백만)에서 기본적으로 거대한 행렬을 만드는 방법이 있습니까?

답변:


91

PyTables와 NumPy가 그 길입니다.

PyTables는 선택적 압축을 사용하여 데이터를 HDF 형식으로 디스크에 저장합니다. 내 데이터 세트는 종종 10 배 압축되어 수천 또는 수억 개의 행을 처리 할 때 편리합니다. 또한 매우 빠릅니다. 5 년된 노트북은 초당 1,000,000 행으로 SQL과 같은 GROUP BY 집계를 수행하는 데이터를 처리 할 수 ​​있습니다. Python 기반 솔루션에는 나쁘지 않습니다!

NumPy 재캐 레이로 데이터에 다시 액세스하는 것은 다음과 같이 간단합니다.

data = table[row_from:row_to]

HDF 라이브러리는 관련 데이터 청크를 읽고 NumPy로 변환합니다.


4
따라서 처리를 위해 데이터를 청크로 분할해야합니까? 디스크 파일과의 변환을 단순화하는 방법 일 뿐입니 까?
endolith 2010 년

좀 더 명확하고 몇 가지 예를 통해 답변을 확장 할 수 있습니까?
Adam B

56

numpy.arrays는 기억 속에 살기위한 것입니다. RAM보다 큰 행렬로 작업하려면 그 문제를 해결해야합니다. 따를 수있는 방법은 두 가지 이상입니다.

  1. 행렬에 있는 특수 구조를 활용 하는보다 효율적인 행렬 표현시도하십시오 . 예를 들어 다른 사람들이 이미 지적했듯이 희소 행렬 (0이 많은 행렬)에 대한 효율적인 데이터 구조가 scipy.sparse.csc_matrix있습니다.
  2. 알고리즘을 수정하여 부분 행렬에서 작동합니다 . 현재 계산에 사용중인 행렬 블록 만 디스크에서 읽을 수 있습니다. 클러스터에서 실행되도록 설계된 알고리즘은 데이터가 여러 컴퓨터에 분산되어 있고 필요할 때만 전달되기 때문에 일반적으로 블록 단위로 작동합니다. 예를 들어 행렬 곱셈을위한 Fox 알고리즘 (PDF 파일) .

4
3 맵리 듀스와 같은 빅 데이터 패러다임과 연구 솔루션 스텝에
메데이로스

2 번의 경우 청크를 얼마나 크게 만들지 어떻게 결정합니까? 여유 메모리 양을 측정하고이를 기반으로 청크 크기를 측정하는 방법이 있습니까?
endolith

30

numpy.memmap를 사용하여 디스크의 파일을 메모리 매핑 할 수 있어야합니다. 최신 Python 및 64 비트 시스템에서는 모든 것을 메모리에로드하지 않고도 필요한 주소 공간이 있어야합니다. OS는 파일의 일부만 메모리에 보관해야합니다.


18
메모리에 맞지 않는 작업을 수행하는 데 사용하는 방법의 예를 제공 할 수 있습니까?
endolith 2010 년

24

희소 행렬을 처리하려면 scipy맨 위에 있는 패키지가 필요 합니다. 제공 되는 희소 행렬 옵션에 대한 자세한 내용 numpy여기 를 참조 하세요scipy .


11

스테파노 보리 니의 포스트 를 통해 이런 일이 벌써 얼마나 진행되고 있는지 살펴 보게되었습니다.

이거 야. 기본적으로 원하는 것을하는 것 같습니다. HDF5를 사용하면 매우 큰 데이터 세트를 저장 한 다음 NumPy와 동일한 방식으로 액세스하고 사용할 수 있습니다.


9
더 나은 선택은 PyTables 일 수 있습니다. 핵심 HDF5 기능보다 더 높은 수준입니다 (H5Py는 Python에서 액세스 할 수있는 하위 수준 API보다 약간 높음). 또한 지난주 2.2 베타에는이 문제에 대한 도구가 있습니다. pytables.org/moin/ReleaseNotes/Release_2.2b1 임의의 대형에서 작동하는 표현식 (예 : '3 * a + 4 * b')을 평가할 수있는 클래스 인 Expr 추가 자원을 최적화하는 동안 배열 [...]. Numexpr 패키지와 유사하지만 NumPy 개체 외에도 Array, CArray, EArray 및 Column PyTables 개체와 같은 디스크 기반 동종 배열도 허용합니다.
AFoglia 09

5

64 비트 운영 체제와 64 비트 버전의 Python / NumPy를 사용하고 있는지 확인합니다. 32 비트 아키텍처에서는 일반적으로 3GB의 메모리를 처리 할 수 ​​있습니다 (메모리 매핑 된 I / O 등으로 인해 약 1GB가 손실 됨).

64 비트 및 사용 가능한 RAM보다 큰 사물 어레이를 사용하면 가상 메모리를 사용할 수 있지만 스왑해야하는 경우 속도가 느려집니다. 또한 메모리 맵 (numpy.memmap 참조)은 대용량 파일을 메모리에로드하지 않고 디스크에서 작업 할 수있는 방법이지만,이를 많이 사용하려면 작업 할 64 비트 주소 공간이 있어야합니다. PyTables도이 대부분을 수행합니다.



4

때로는 한 가지 간단한 솔루션이 행렬 항목에 사용자 지정 유형을 사용하는 것입니다. 필요한 번호의 범위에 따라 설명서를 사용할 수 dtype있으며 특히 항목에 대해 더 작습니다. Numpy는 기본적으로 객체에 대해 가장 큰 유형을 고려하기 때문에 이것은 많은 경우에 유용한 아이디어 일 수 있습니다. 다음은 예입니다.

In [70]: a = np.arange(5)

In [71]: a[0].dtype
Out[71]: dtype('int64')

In [72]: a.nbytes
Out[72]: 40

In [73]: a = np.arange(0, 2, 0.5)

In [74]: a[0].dtype
Out[74]: dtype('float64')

In [75]: a.nbytes
Out[75]: 32

그리고 사용자 정의 유형 :

In [80]: a = np.arange(5, dtype=np.int8)

In [81]: a.nbytes
Out[81]: 5

In [76]: a = np.arange(0, 2, 0.5, dtype=np.float16)

In [78]: a.nbytes
Out[78]: 8

3

테라 바이트의 RAM없이 2,500,000,000 요소 행렬을 처리하는 방법을 묻고 있습니까?

80 억 바이트의 RAM없이 20 억 개의 항목을 처리하는 방법은 매트릭스를 메모리에 보관하지 않는 것입니다.

이는 파일 시스템에서 조각을 가져 오는 훨씬 더 정교한 알고리즘을 의미합니다.


7
사실이 아니다. 요소의 99.99 % (실제적인 예)가 0이면 행렬의 모든 데이터를 메모리에 보관할 수 있습니다. 존재 (row, column, value)하는 항목 에 대한 목록 만 저장할 수 있으므로 0마다 4 바이트를 사용할 필요가 없습니다 .
Eric Wilson

6
@EricWilson : 질문에서 행렬이 희박하다고 제안한 곳은 어디입니까? 나는 그것을 완전히 놓쳤다. 견적을 제공 할 수 있습니까?
S.Lott


1

내가 numpy에 대해 아는 한, 아니오, 그러나 내가 틀릴 수 있습니다.

이 대체 솔루션을 제안 할 수 있습니다. 디스크에 매트릭스를 작성하고 청크로 액세스합니다. HDF5 파일 형식을 제안합니다. 투명하게 필요한 경우 ndarray 인터페이스를 다시 구현하여 디스크에 저장된 매트릭스를 메모리에 페이지 매김 할 수 있습니다. 디스크에서 다시 동기화하기 위해 데이터를 수정하는 경우주의하십시오.


57600 x 57600의 전체 행렬에 액세스하려면 어떻게해야합니까?
Gunjan Naik는
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.