Nvidia 에서 만든 data loading library인 DALI 공부 중

n년전 pytorch가 그랬듯, 툴 자체는 좋아보이는데 아직 사용자가 많지 않은지 error에 대한 정보를 얻기가 힘들다 ㅜ

일단 현재까지 파악한 건,

 

- TF 처럼 define and run 구조. -> 따라서 random 성이 있는 모듈은 구현되어 있지 않음

- pipe를 define할때는 transform을 추가하고, run할 때 transform에 들어갈 변수들을 parameter로 전달

ex. define할때 crop이 들어가면 run할때 crop size를 넣어줌 

 

=> 기본적으론 아래와 같이 돌아가고, custom dataset에서는 어떻게 줘야하는지 자꾸 오류가 나서

     일단 Nvidia측에서 제공하는 dataset으로 이것저것 실험 중

 

=> ToDo: crop 등등 transform하기 / CPU, GPU Mixed 성능비교하기 / torch랑 학습 시간 비교하기


DALI 공식문서

https://docs.nvidia.com/deeplearning/dali/user-guide/docs/

 

NVIDIA DALI Documentation — NVIDIA DALI 1.18.0 documentation

Multiple data formats support - LMDB, RecordIO, TFRecord, COCO, JPEG, JPEG 2000, WAV, FLAC, OGG, H.264, VP9 and HEVC.

docs.nvidia.com

Nvidia에서 DALI repo에 제공하는 dataset

https://github.com/NVIDIA/DALI/tree/main/docs/examples/data/images

 

GitHub - NVIDIA/DALI: A GPU-accelerated library containing highly optimized building blocks and an execution engine for data pro

A GPU-accelerated library containing highly optimized building blocks and an execution engine for data processing to accelerate deep learning training and inference applications. - GitHub - NVIDIA/...

github.com

# 돌리는데 성공한거

def simple_mixed_pipeline():
    jpegs, labels = fn.readers.file(file_root=data_dir)
    images = fn.decoders.image(jpegs, device="mixed")

    return images, labels


if __name__ == "__main__":
    pipe = simple_mixed_pipeline(batch_size=8, num_threads=2, device_id=0)
    start = time()
    pipe.build()
    pipe_out = pipe.run()
    end = time()
    print(pipe_out)
# 앞으로 돌려봐야할 것

from nvidia.dali.pipeline import Pipeline
from nvidia.dali import pipeline_def
import nvidia.dali.fn as fn
import nvidia.dali.types as types
from nvidia.dali.plugin.pytorch import DALIGenericIterator

import torchvision.models as models
resnet18 = models.resnet18()

from time import time

data_dir = "./test_DALI/images/"


@pipeline_def(batch_size=128, num_threads=4, device_id=0)
def get_dali_pipeline(data_dir, crop_size):
  images, labels = fn.readers.file(file_root=data_dir)
  # decode data on the GPU
  images = fn.decoders.image_random_crop(images, device="mixed", output_type=types.RGB)
  # the rest of processing happens on the GPU as well
  images = fn.resize(images, resize_x=crop_size, resize_y=crop_size)
  images = fn.crop_mirror_normalize(images,
                                    mean=[0.485 * 255,0.456 * 255,0.406 * 255],
                                    std=[0.229 * 255,0.224 * 255,0.225 * 255],
                                    mirror=fn.random.coin_flip())
  return images, label


train_data = DALIGenericIterator(
   [get_dali_pipeline(data_dir, (224, 224))], ['data', 'label'], reader_name='Reader')


for i, data in enumerate(train_data):
  x, y = data[0]['data'], data[0]['label']
  pred = resnet18(x)
  # loss = loss_func(pred, y)
  # backward(loss, model)

https://89douner.tistory.com/339

 

1. Representation Learning 이란?

안녕하세요. 이번글에서는 representation learning이라는 개념에 대해서 설명하려고 합니다. 개인적으로 2021년 동안 논문을 살펴보면서 가장 눈에 많이 띄었던 용어가 representation learning 이었습니다.

89douner.tistory.com

Representation Learning을 공부하면서 위 블로그 글을 일부 참고하여 작성하였습니다. 

스스로 다시 공부할 때 5-10분내로 복습하는 것을 목표로 했기 때문에 최대한 간소화하여 적었습니다


Representaion Learning이 뭔지 알기위해서는 먼저 Representation의 개념부터 잡아야한다 

https://www.deeplearningbook.org/contents/representation.html

 

https://www.deeplearningbook.org/contents/representation.html

 

www.deeplearningbook.org

먼저 Deep Learning 교과서에는 이런 구절이 있다. 

"Many Information processing tasks can be very eay or very difficult depending on how the information is represented"

: 정보처리과정은 그 정보를 어떻게 표현하는 지에 따라 매우 쉬울수도, 매우 어려워질수도 있다. 

 

여기서 느낄 수 있듯이 representation이란 결국 어떠한 task를 위해 input을 잘 가공하는 것을 의미한다.

 => CNN기반의 deep learning network도 해당 task를 잘 수행하기 위한 feature를 뽑아내는 과정으로 볼 수 있다.

예를 들어 softmax classifier를 사용하는 모델은 이에 맞게 잘 표현할(=representation) feature를 뽑아낼 것이다. 

 

단순하게 비유하자면 classifier로 학습된 model에서 뽑은 feature는 classify를 위한 representation이기 때문에

이를 segmentor의 input으로 넣는다고 잘 작동하지 않을 것이라는 사실과 비슷하다. 

 


여기까지 무슨소린지는 알겠는데, 내가 궁금했던 것은

그래서 굳이 "Representation Learning이라는 점이 pre-training과 다른점이 무엇인가"이다

=> 보통 Representation Learning은 Unsupervised Learning에서 많이 사용하는 듯하다.  

(혹은 pretraining도 Representation Learning의 범주 안에 속한다고 봐야하나? )

VAE같이 explicit한 distribution을 따르도록 학습시키는 경우를 그 예시로 들 수 있다. 

VAE의 경우 normal distribution이 인풋이미지를 가공하여 만든 new representaion이 되는 것이다. 

 


 

예시를 들면 조금 더 이해하기가 쉬운데, CLIP이 좋은 예시가 된다. 

 

 

 

최종 목표는 zero-shot prediction을 위한 pretraining이기 때문에 

이를 잘표현할 수 있는 방식으로 text encoder와 image encoder가같은 도메인의 feature를 표현할 수 있게 학습을 유도하는 것이다. 이것이 representation learning의 한 종류로 볼 수 있다. 

 

=> meta-learning은 이와 달리 few shot task를 잘하기 위한 스킬적인 측면이라고 볼 수 있다.

학습의 결과물이 fewshot을 잘 할수있는 domain을 학습시키는 것이 아니라

스킬적인 측면에서 gradient update를 few-shot 시나리오에 맞춰해주는 것이라 차이가 있다. 

'딥러닝 공부 > 짧은 AI' 카테고리의 다른 글

t-sne 요약  (0) 2023.09.10
어쩌다보니 공부한 domain adaptation  (0) 2023.01.09

axel을 알게 된 경위는 대부분의 CV 엔지니어가 그렇듯이 ImageNet 다운받다가 경악할만 속도에 지쳐서..

wget보다 속도가 빠른 리눅스 다운로더가 없는지 검색하던 찰나에 알게 되었다 ㅋㅋㅋ

 

먼저 wget을 사용하는 방법은 아래와 같다

wget "다운로드링크"

# 여러 링크를 연속적으로 다운받고 싶다면
# txt 파일에 여러 다운로드 링크를 쓰고
wget -i "txt파일"

근데 이미지넷은 서버 관리를 도대체 어떻게 하는건지 ㅜ 아니면 단순 이용자수가 너무 많아서 그런건지 

wget으로 이미지넷 트레인셋을 다운받을려면 예상 시간이 2-3일이었다...

그래서 더 빠른 다운로더가 없는지 찾던 차에 axel에 대해 알게되었다.

 

apt get으로 axel을 설치한 후 마찬가지로 아래와 같이 사용하면 된다. 

axel "다운로드 링크"

이미지넷을 다운받을 때는 속도가 5배 이상 차이났던걸로 기억하는데 

오늘 coco 데이터셋을 다운받을 때는 속도가 둘다 동일하게 1M/s 이상이 나왔다 

axel의 유일한 단점이라면 다운로드 과정을 보여주는 UI가 더럽다는 점 정도..?

어차피 다운받고 그거 들여다 보고 있을건 아니니 크게 문제될 건 없다. 

 

COCO에서는 속도가 비슷하게 리포트 되는거 보니까 단순 이미지넷 서버의 문제일 수도 있는 것 같다 ㅋㅋㅋ

 

axel 사용 -> 퍼센트 갱신될 때마다 출력이 계속되서 더럽다
wget 사용시

글 쓰면서 한번 더 wget을 써보니 지금은 또 wget이 더 빠르기도..?

사용시마다 서버상태, 로컬 인터넷 상태 등등에 따라 성능 차이가 많이 있는 것도 같다

 

결론은 axel이 항상 더 빠른 건 아니지만, 서버 상태가 안좋을 땐 axel이 더 좋은 것 같다..?

 

Ex. 내가 어제 겪은 상황:

-> detection

   -> A

      -> a.py

   -> B

      -> b.py

      ->bb.py

   -> C

      -> c.py

   -> detect.py

-> test.py

 

가장 상위 폴더에 detection이라는 폴더와 test.py가 있고,

detection 폴더 안에 폴더 A, B, C가 있음. 


test.py와 detect.py는 거의 같은 내용으로 같은 모듈들을 import 해야함

test.py에서 A폴더 내의 a.py, B 폴더내의 bb.py를 import할때는

아래와 같이 하면 되고 (test.py를 실행하는 경로는 가장 상위 경로니까 ) 

from Detection.A.a import {a.py 내에 있는 함수 이름}
from Detection.B.bb import {bb.py 내에 있는 함수 이름}

 

같은 함수를 detect.py 내에서 import 할때에는 아래와 같이 하면 된다.

(detect.py를 실행하는 경로는 ROOT/detection이니까)

from A.a import {a.py 내에 있는 함수 이름}
from B.bb import {bb.py 내에 있는 함수 이름}

 

문제는, detect.py와 test.py가 둘다 A.a를 import 하는데 

다시 A.a가 C.c를 import 하는 상황이다. (실제로는 폴더가 한 5개정도 됐음,,,,,🤣)

 

이게 왜 문제냐면, 

A.a를 test.py도 import 하고, detect.py도 A.a import 해야하는데, 

test.py ->  A.a.py -> C.c.py 일때는 실행하는 경로가 ROOT이고

detect.py -> A.a.py ->C.c.py 일때는 실행하는 경로가 ROOT/Detection 이었다.

(물론 ROOT에서 python Detection/detect.py로 실행하면 문제가 없지만, 내 경우에는 Detection 내에서 실행을 해야했다)

 

그럼 A.a.py는 from C.c import {C.c에 있는 함수}로 import 하면 test.py 실행시 문제가 생기고

from Detection.C.c import (C.c에 있는 함수)로 import 하면 detect.py 실행시에 문제가 생긴다 😥

 

이를 해결하기 위한 방법은 크게 

1. CLI 커맨드로 bash 자체에 영구적으로 export PYTHONPATH 하는 방법 (영구해결)

2. python 파일 최상단에서 sys.path에 ROOT/Detection 폴더를 추가해주는 방법

  (해당 프로세스나 창이 꺼지면 리셋되는 듯?)

 

근데 1번은.. 내가 잘 이해를 못한건지,,,종종 잘 안되는 경우가 많아서ㅜ

이렇게 아래처럼 전체 파일에 python path로 root path를 붙여주면 제일 잘되는거 같다

 

이렇게 하면 파일이 실행되는 ROOT 경로를 system path에 추가해주기 때문에 

import error를 일으키는 파일 위에 추가를 해주거나 가장 상위 파일에 추가를 해주면 대부분 문제가 없다. 

 

import os
import sys
from pathlib import Path


FILE = Path(__file__).resolve()
ROOT = FILE.parents[0]  # root directory
if str(ROOT) not in sys.path:
    sys.path.append(str(ROOT))  # add ROOT to PATH

아래는 좀더 심플한 버젼! 근데 위 코드가 더 general하게 error 안날꺼 같다.

import os, sys
if not os.getcwd().endswith("Detection"):
	sys.path.append(os.getcwd() + "/Detection")

+ Recent posts