Notice
Recent Posts
Recent Comments
05-18 01:37
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

Byeol Lo

Pytorch - 대규모 이미지 처리 오류 모음 본문

AI/Pytorch

Pytorch - 대규모 이미지 처리 오류 모음

알 수 없는 사용자 2023. 9. 5. 14:40

 Pytorch에서 프로젝트를 수행하면서 이미지 처리를 했었는데, 회고록의 느낌으로 포스트를 남긴다. 다른 분들에게도 다음과 같은 오류들이 있을 수 있기 때문에 그 분들에게 도움이 되었으면 한다.

 

Data Download & Pre-Processing

 대용량의 데이터를 다운 받을 때 혹은 전처리를 할 때는 다음 multi-processing을 써서 다운로드 받는게 좋다. 환경마다 다 다른 cpu 개수를 가지고 논리 프로세서 개수 또한 지원이 다르기에 다음과 같은 코드를 활용하자. python의 multiprocessing은 따로 공부를 해서 이용하는 것을 추천한다.

# Python 3.8.12

import multiprocessing

MULTIPROCESSING_WORKERS = multiprocessing.cpu_count()

def func1(args):
	# 작업 처리

if __name__ == "__main__":
    with p:
        p.map(func1, (iterable_instance))
        p.close()
        p.join()

 보통 다운로드는 url로 처리하기에 iterable_instance의 element들을 순회하면서 processing을 하자. 또한 worker에게 작업이 끝났으면 종료시켜야 하기에 p.close()와 p.join()을 써준다.

 데이터를 처리하다보면 PIL 중에 gray scaled image, RGBA 등이 있을 수 있다. 따라서 PIL Image를 통해 image를 열려고 할 때 Image.open(...).convert("RGB")를 추가하자.

from PIL import Image, ImageFile

img = Image.open("path").convert('RGB')

'RGB' 말고도 다양한 값들을 넣어볼 수 있으니 다음을 통해 확인하자.

 

Torchvision Transforms ToTensor

 PIL.Image 인스턴스와 numpy.ndarray의 인스턴스를 입력 받고 자동으로 C*H*W 순서의 shape를 가지는 FloatTensor를 반환하는 함수이다. Input을 어떤 것을 넣어야 할지만 기억해두자.

import torchvision
from PIL import Image, ImageFile

ImageFile.LOAD_TRUNCATED_IMAGES = True

f = torchvision.transforms.ToTensor()
img = Image.open(path)
img = f(img)
print(img.shape)

 

Data Visualization

 Visual Studio Code는 한 코드 한 코드 나눠서 실행해서 시각화에 부적절하다. Jupyter Notebook은 한 코드 한 코드로 시각화를 하나하나 할 수 있기 때문에 jupyter notebook을 쓰는 것이 좋다. 또한 PIL의 Image.show는 jupyter notebook에서 안나타나는 경우가 있는데, display(Image.open(path_name))을 사용해주자.

from PIL import Image, ImageFile

ImageFile.LOAD_TRUNCATED_IMAGES = True

display(Image.open(path))

 

Seed Setting

seed = 7777
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
torch.backends.cudnn.benchmark = False
torch.backends.cudnn.deterministic = True

 보통 위 코드를 맨 위에 두고 실행하면 재현이 가능하기에 써주는 것이 좋다.

# main.py
from tmp import f1


print(f1())
# tmp.py
import random


random.seed(7)


def f1():
    return random.randint(1, 10)

반드시 난수를 적용해야하는 코드의 파일 내에서 random.seed()를 설정해주어야 적용된다.

 

Torch Automatic Mixed Precision

 torch의 연산은 기본적으로 float32로 처리된다. 이렇게 처리하면 메모리를 많이 사용하게 되는데 모델의 학습에 있어서는 float16으로 해도 float32와 별 차이가 없기에 속도 상의 이득을 보려면 float16이 훨씬 좋다.

import torch

# optimizer = ...
scaler = torch.cuda.amp.GradScaler()

for image, label in data_loader:
    with torch.autocast(device_type = 'cuda', dtype = torch.float16):
        #... float 16으로 연산할 부분
        loss = criterion(...)
    scaler.scale(loss).backward()
    scaler.step(optimizer)
    scaler.update()
    optimizer.zero_grad()

 

Segmentation fault (Core Dumped)

 이 오류가 왜 뜨는지는 알지만 아직도 어떻게 고치는지는 잘 모르겠다. 하지만 분명한 것은 다음과 같다.

  1. null 값을 가리키는 포인터에 접근해서
  2. 할당 받은 메모리 공간을 넘은 곳을 건드려서
  3. 더 이상 존재하지 않는 메모리를 가르켜서
  4. read-only 표시 메모리 영역을 쓰려고 해서
  5. python의 라이브러리 끼리 호환이 안되어 잘못된 메모리 경로를 가리키게 돼서

 따라서 우선적으로 python의 버전과 pytorch, numpy, pandas, torchvision등의 버전 호환을 살펴보고 또한 pyarrow나 scipy 등의 관련된 라이브러리 들을 찾아보면서 호환되는 버전들을 전부 다운 받아준다. 이게 안된다면 다음으로 고려해볼 것은 dataloader의 num_workers를 줄이는 것이다. 보통 gpu의 배수로 하는 것이 좋으며, 줄일 때도 배수로 줄이자. 이것 마저도 안돼서 다음을 찾아보았다.

apt-get update

apt-get install gdb
mkdir -p ~/.config/gdb
cd ~/.config/gdb
wget https://hg.python.org/cpython/rawfile/3.8/Tools/gdb/libpython.py
# 위 링크의 3.8은 사용하는 버전으로 수정하는 것이 좋다.

vim ~/.gdbinit

.gdbinit에는 다음과 같은 코드들을 넣어준다.

python3
import gdb
import sys
import os

sys.path.append('python packages 경로') # python3 -c 'import sys; print(sys.path)'로 경로 확인
sys.path.insert(0, os.path.expanduser('~/.config/gdb'))

def setup_python(event):
    import libpython
    gdb.events.new_objfile.connect(setup_python)
    
end

vim을 빠져나오고 trouble shooting을 위해 문제가 있던 코드 파일을 실행한다.

gdb --args python3 test.py # 여기서 문제가 있는 코드 파일은 test.py

해당 log들을 확인하면서 메모리를 차지하고 있는 process ID를 찾아 다음을 입력한다.

sudo kill -9 (PID)

위 솔루션도 안되면 나도 모르겠다. 다른 환경에서 실행해보자.

 

ValueError: Decompressed Data Too Large

 데이터가 가끔 비정상적으로 큰 데이터가 있을 수 있는데, 여기서 많은 양의 메타데이터가 포함된 파일이 압축을 풀 때에는 시스템/서버에 과부하가 걸리는 것을 방지하기 위해 PIL에서 이를 제한하고 있다. 공식 문서에 따르면 다음과 같다.

open also sets Image.text to a dictionary of the values of the tEXt, zTXt, and iTXt chunks of the PNG image. Individual compressed chunks are limited to a decompressed size of PngImagePlugin.MAX_TEXT_CHUNK, by default 1MB, to prevent decompression bombs. Additionally, the total size of all of the text chunks is limited to  PngImagePlugin.MAX_TEXT_MEMORY, defaulting to 64MB.

다음 두 가지 해결책을 해보자.

from PIL import ImageFile, PngImagePlugin

# sol. 1
MAXIMUM_DECOMPRESSED_SIZE = 1024
MEGA_BYTE = 2**20

PngImagePlugin.MAX_TEXT_CHUNK = MAXIMUM_DECOMPRESSED_SIZE * MEGA_BYTE

# sol. 2
ImageFile.LOAD_TRUNCATED_IMAGES = True

 

'AI > Pytorch' 카테고리의 다른 글

Pytorch - 데이터 처리  (0) 2023.09.06
Comments