Progress Bar를 만들어 보자, tqdm

AID·2024년 3월 17일
2

인공지능 공부 진척도: 78%|████████████████▍ | 78/100 [00:38<00:10, 2.02it/s]
모델 학습을 진행하면서, 위와 같은 진행 바(Progress Bar)를 정말 많이 보셨을 겁니다.
(저도 인공지능 공부를 처음 시작해서, 책에 있는 코드를 막 따라쳤을 때, 저 진행 바를 보고 '우와!' 하고 설렜던 기억이 아직도 새록새록하네요.)

위 진행 바는, Python의 'tqdm' 모듈을 이용한 것입니다!

tqdm은 Python으로 어떤 작업을 할 때 프로그램이 내가 의도한 대로 돌아가고 있는 중인지, 얼마나 진행되었는지를 확인하기 위해서 사용합니다.

많은 시간이 걸리는 작업의 경우에, 얼마나 시간이 남았는지, 진행도를 확인하는 것이 특히 중요한데요, 따라서 많은 경우에 모델 학습 시 tqdm을 활용하는 모습을 볼 수 있습니다.

백문이 불여일견! tqdm의 사용 방법 알아보기

tqdm은 주로 세 가지 사용 방법으로 나눠볼 수 있습니다.

iterable-based

우선, list, dict나 range와 같은 iterable 객체를 이용하는 방법이 있고, 이 방법으로 한번 이해해보도록 합시다.

from tqdm import tqdm # pip install tqdm
import time

iterable = ['A', 'I', 'D', 'i', 's', 'B', 'E', 'S', 'T']
bar = tqdm(iterable, # 진행 상황을 표시할 iterable 객체.
           desc = 'Description', # 진행 상황 표시줄의 제목.
           total = len(iterable), # 전체 반복량 (확률에서의 분모).
           leave = True, # 잔상 남김 여부, 기본적으로 True
           ncols = 100, # 진행 바 길이. px 단위
           ascii = ' =', # 바 모양, 첫 번째 문자는 공백이어야 함
           initial = 0 # 진행 시작값
           )

for c in bar:
    time.sleep(0.1)

Output : 
Description: 100%|====================================================| 9/9 [00:00<00:00,  9.88it/s]

tqdm()으로 iterable 객체를 감싸고, 위에서 설명된 method를 적절하게 사용하는 방법으로, 내 마음에 쏙 드는 Progress Bar를 만들 수 있습니다.

for c in bar:
    bar.set_description(f"Description '{c}'")
    time.sleep(0.1)

Output : 
Description 'T': 100%|================================================| 9/9 [00:00<00:00,  9.87it/s]

또한, 위와 같은 방식으로 루프를 돌면서도, bar의 description을 바꿀 수도 있죠.

for i in trange(100):
    time.sleep(0.01)
    
Output :
100%|██████████| 100/100 [00:01<00:00, 91.13it/s]

trange(i)라는 특별한 인스턴스도 존재하는데, 이는 tqdm(range(i))와 같은 의미를 가지고 있습니다.

Manual

with tqdm(total=100) as bar:
    for i in range(10):
        time.sleep(0.1)
        bar.update(10)

with 구문과, update()를 통해서 bar를 수동으로 컨트롤할 수 있습니다. iterable한 객체를 토대로 tqdm을 갱신시키는 것이 아니라, 수동으로 퍼센트를 올린다고 보면 좋을 것 같습니다.

Module

또한, tqdm은 스크립트나 커맨드라인에서도 매우 유용하게 사용될 수 있습니다. 파이프 사이에 tqdm을 삽입하기만 하면, 모든 stdin을 stdout으로 전달하면서 stderr에 진행 상황을 출력합니다.

$ time find . -name '*.py' -type f -exec cat {} \; | wc -l

Output : 
    857365

    real    0m3.458s
    user    0m0.274s
    sys     0m3.325s

sh에서 위 명령어를 입력하면, 아래와 같은 과정을 거쳐 그 결과를 얻을 수 있습니다.

1) `find .` : 현재 디렉토리(.)와 그 하위 디렉토리를 탐색하고
2) `-name '*.py': .py 확장자를 가진 파일을 찾고`
3) `-type f` : 파일 타입이 '파일(f)'인 항목만 찾는다.
4) `-exec cat {} \;` : 이 때, 찾은 각 파일({}는 각 파일 경로)에 대해 cat 명령을 실행한다. (cat은 파일의 내용을 표준 출력(stdout)으로 보냄) \;는 -exec 옵션의 끝을 나타낸다.
5) `|` : 파이프(pipe)는 한 명령의 출력을 다른 명령의 입력으로 전달한다. 여기서는 find 명령의 출력(즉, Python 파일의 내용)을 wc -l 명령의 입력으로 전달한다.
6) `wc -l` : wc는 'Word Count'의 약자로, 텍스트 데이터의 라인 수, 단어 수 등을 계산하는 명령이다. 이 때, -l 옵션을 사용하였으므로 라인 수(line count)만을 출력하도록 한다.

이 때, 이러한 명령 pipe 사이에서 tqdm을 이용해서 현재 진행도를 확인할 수 있습니다.

$ time find . -name '*.py' -type f -exec cat \{} \; | tqdm | wc -l

Output : 
    857366it [00:03, 246471.31it/s]
    857365

    real    0m3.585s
    user    0m0.862s
    sys     0m3.358s

커맨드라인에서도 진행상황을 시각적으로 쉽게 확인할 수 있다니, 굉장히 신기하지 않나요?

진행 상황을 쉽게 확인할 수 있는 tqdm!
더 자세한 내용은 아래 링크의 tqdm documentation을 참고해보세요 🙂

https://tqdm.github.io/


작성자 : 2기 안준영

profile
부산대학교 인공지능 동아리

0개의 댓글