Skip to main content

아이디어 공간을 더 잘 탐색하는 길

딥러닝 실험의 진전은 빠른 반복과 긴밀한 피드백 루프에 달려 있다. 이 글은 AI 번역본입니다. 오역 가능성이 있으면 댓글로 알려주세요.
Created on September 15|Last edited on September 15

Weights & Biases로 안내하는 딥러닝 탐색

딥러닝 논문은 종종 일관된 원칙에서 세련된 가설이 도출되고, 깔끔한 실험 설계와 설득력 있는 결과로 이어지는 모습을 보여준다. 그러나 실제로 딥러닝의 진전은 훨씬 더 혼란스럽다 그리고 무엇보다 빠른 반복과 긴밀한 피드백 루프에 의존한다. 나는 4년 동안 Flickr에서 대규모 객체 인식과 이미지 분류를 했고, 최근에는 Weights & Biases에 합류했다. 이 회사는 내가 선호하는 워크플로에 잘 맞는 딥러닝 개발 도구 키트인 wandb를 만든다. 탐색적 해킹 모드에 있을 때 wandb는 실험 공간을 이리저리 헤매는 경로를 추적해 주고, 더 유망한 영역으로 방향을 틀도록 도와준다. 이 글에서는 새로운 데이터셋에서 컴퓨터 비전 모델을 구축하고 최적화하는 실제 예시를 소개한다. 여기에는 간단한 Keras 모델에 wandb를 계측하는 방법과, 내 진행 속도를 가속한 몇 가지 실천법도 포함한다.

과제: 딥러닝으로 식물과 동물을 식별하기

첫 번째 wandb 프로젝트로, 나는 시도해 보았다 이 Keras 파인튜닝 튜토리얼 에서 iNaturalist 2017에는 5천 종이 넘는 생물의 사진이 67만 5천 장 이상 포함되어 있으며, 각 종은 13개 분류 중 하나에 할당되어 있다(엄밀히 말하면, 13개 자연 분류군들).
다른 분류군: 곤충, 포유류, 버섯
10가지 차이점을 찾아보세요? 서로 다른 굴뚝새 3종
나는 5개 레이어짜리 합성곱 신경망으로 시작했다 Keras 튜토리얼합성곱 레이어 3개와 완전연결 레이어 2개로 구성하고, ReLU 활성화와 맥스 풀링을 사용했다. 전체 iNaturalist 2017 데이터셋은 186 GB에 달하고 분포가 심하게 치우쳐 있어, 가장 빈도가 높은 10개 분류군에 걸쳐 50,000장의 균형 잡힌 하위셋을 만들었다[1]. 신경망이 학습하는지(적어도 2,000개 예제에서 이진 분류기로 과적합하는지) 확인한 뒤, 데이터의 균형 잡힌 10%(학습 5,000, 검증 800)를 넣고 배치 크기, 레이어 수, 마지막 완전연결 레이어의 크기, 드롭아웃을 조정했다.
작은 신경망과 데이터셋 덕분에 빠르게 반복하며 도구의 역량을 파악할 수 있었다. 10개 분류군 중 하나를 예측하는 베스트 모델의 학습/검증 정확도는 44.2%/45.3%였고, 전체 50K 데이터셋에서는 51.6%/48.3%로 올랐다(일부 과적합을 시사). 레이어가 7개뿐인데도 무작위 대비 대략 5배 더 낫다. 비교를 위해, InceptionV3( ImageNet 사전학습) 네트를 50K 데이터셋에 파인튜닝하면 학습 95.6%, 검증 84.5%까지 정확도가 오른다(예상대로 명확한 과적합—자연 사진들이 ImageNet과 매우 비슷하기 때문에, InceptionV3는 아무 튜닝 없이도 52.9%에 도달한다).

과정을 지도화하세요: 코드 5줄로 모든 곡선을 확인하기

프로젝트에 wandb를 추가하면 한 번에 계정을 만들기 정말 간단하다. wandb를 설치하고 API 키로 인증하는 두 가지 명령, 스크립트를 웹에서 볼 수 있는 wandb 프로젝트에 연결하는 세 줄, 그리고 로깅을 처리하도록 학습 메서드에 전달하는 WandbCallback 인스턴스 하나면 된다. Keras와 함께 쓰면 wandb가 학습과 검증 모두에 대해 에포크 단위의 정확도와 손실 같은 필수 항목을 자동으로 추적해 준다. 스크립트에 이 최소한의 변경만 적용해 실행하고, 제시된 URL로 이동한 뒤 생겨나는 플롯을 확인하면 된다. 이러한 기본 차트만으로도 모델이 학습 중인지 즉시 파악할 수 있다. 또한 내가 보통 Keras에서 지켜보는 부동소수점 숫자 행보다 훨씬 이해하기 쉽고 실행 간 비교도 수월하다. 별도의 지표 계산 코드나 차트 그리기 코드를 작성할 필요도 없다.
Keras용 W&B 기본 그래프: 학습 및 검증 정확도와 손실

주변에서 단서를 찾기: 핵심 지표에 집중하기

작은 CNN의 하이퍼파라미터를 살핀 방식은 전혀 체계적이지 않았다. 실제 해킹하듯이 해보겠다는 생각으로 스크립트에서 값을 바꾸고 레이어를 추가했으며, 서로 다른 머신(로컬 CPU, 준로컬 GPU, 원격 GPU)에 하드코딩한 여러 버전을 굴렸다. 뜻밖의 기쁨이었던 점은, 이 정보의 상당수(레이어 수, 각 크기 등)를 실행(run)별 “Model” 탭에서 복구할 수 있었다는 것이다. 이 탭은 계산 그래프의 모든 요소에 대해 이름, 타입(Conv2D, Activation, MaxPooling2D, …), 파라미터 수(더 이상 머릿속 계산은 필요 없다!), 출력 형태를 자동으로 보여준다. 더 흥미로운 네트워크 파라미터를 찾을수록, 나는 그것들을 wandb.config에 실험 단위 설정으로 명시적으로 저장했다. wandb.config는 배치 크기, 학습 예제 수, 학습 옵티마이저 종류처럼 사용자가 정의하는 값들을 담는 딕셔너리로, 단일 실험이나 학습 스크립트의 단일 호출에서 고정되길 기대하는 모든 항목을 넣는다. W&B에서 정의하는 실행(run)이 바로 이것이다. 기본 요약 지표(학습/검증 정확도/손실)와 wandb.config에 지정된 필드 집합은 해당 실행의 컬럼으로 저장된다. 이 컬럼들은 실행 목록이나 그래프를 정렬, 그룹화, 필터링하는 데 쓸 수 있고, 선택한 실행들에서 값이 모두 같으면 자동으로 숨겨지기도 한다. 덕분에 나는 주의를 기울일 창을 정교하게 좁힐 수 있었고, 손실이 폭주한 그 이상한 실행 하나를 찾거나 옵티마이저를 바꾸는 것(rmsprop로 전환)만으로 갑자기 모든 것이 좋아진 경우를 찾는 과정이 한결 단순해졌다.
일부 실행의 관련 config와 요약 지표 표시하기

유망한 방향 표시하기: 좋은 핸들은 인지적 부담을 줄인다

이 반복 루프—지금까지 시도한 일부 실행에서 패턴을 찾고, 다음 실행을 그 패턴을 확인하거나 깨거나 확장하도록 구성하는 것—만으로는 여전히 단기 기억에 많은 임시값(관련 실행 이름, 관련 컬럼, 오른쪽 차트의 올바른 색상 선 등)을 붙잡고 있어야 했다. 실행에 설명적인 이름을 붙이니 이 정신적 목록이 줄었다. 특히 시리즈 실행에는 공통 접두어를 유지하고, 시험 변수와 값을 강조했다(예: 베이스 네트워크에서 드롭아웃 d와 배치 크기 b만 바꿔 “base_d_0.2_b_32”, “base_d_0.4_b_64”, “base_d_0.6_b_128” 같은 실행 이름을 사용). 실행 이름과 관심 있는 다른 모든 파라미터에 대한 커맨드라인 argparse를 추가하고(로깅을 위해 wandb.config에 바로 전달할 수 있다) 나서 실험 효율이 훨씬 좋아졌다. 실행 명령에서 관련 파라미터를 모두 직접 수정할 수 있게 되었기 때문이다. 학습 스크립트를 디버깅할 때 —quiet_mode나 드라이런 플래그는 특히 유용한데, UI의 잡음을 줄여 준다.
점차 이러한 실행들이 통찰과 더 구조화된 실험으로 응집되었고, 나는 이를 wandb 리포트에 기록하기 시작했다. 리포트는 데이터 테이블, 플롯, 마크다운, HTML 등 다양한 시각화를 통해 프로젝트를 매우 유연하게 보여주는 뷰다. 프로젝트 자체는 지속적으로 업데이트되지만, 리포트는 진행 상황을 스냅샷처럼 담아 세부 내용을 편리하게 되새기거나 다른 사람과 공유하도록 설계되어 있다. 그날의 실험에 대한 메모, 할 일, 질문, 인사이트를 관련 차트와 함께 증거로 남기면, 중간 결과를 추적하고 다음에 무엇을 탐색할지 기억하는 데 도움이 된다. 예를 들어, ImageNet으로 사전학습된 높은 정확도의 잘 알려진 합성곱 신경망을 파인튜닝하는 것은 대부분의 비전 과제에서 신뢰할 수 있는 베이스라인이다. 하지만 이 데이터셋에 최적인 베이스 모델은 무엇일까? 나는 작은 5K 데이터셋에서 InceptionV3, InceptionResNetV2, Xception, ResNet50의 손실, 학습 정확도, 검증 정확도를 비교했고, Inception 계열이 가장 좋은 성능을 보인다는 것을 확인했다(또한 ResNet50에 대한 Keras 경고는 초기 검증 정확도가 매우 낮은 점으로 미뤄 버그에 가까워 보인다는 점도 눈에 띄었다). InceptionResNetV2는 InceptionV3보다 크기/파라미터 수가 두 배이므로, 앞으로는 더 콤팩트한 InceptionV3를 선택하기로 했고, 나중에 참고할 수 있도록 결과를 명확히 요약해 두었다. 이제 다른 가능한 베이스 모델 변형들을 모두 무시함으로써 초점을 좁힐 수 있고, 동시에 나중에 이 질문으로 돌아오더라도 더 잘 대비할 수 있다. ResNet50 초기화를 디버그해야 한다는 것을 알 것이고, 각 구성 실행에 사용한 정확한 config로 연결되는 링크도 갖게 될 것이며, 관련 차트를 깊게 다시 분석하지 않아도 될 것이다(“내가 왜 다시 InceptionV3를 쓰고 있지? 더 작게/더 깊게/다르게 해보면… 아, 맞다, 그래서 이걸 쓰는 거였지”).
미래의 나를 위한 간결한 인사이트: 관련 메모, 시각적 근거, 그리고 실행 config까지 정확히 포함하기
다른 실험에서는 10개 분류군 각각의 정밀도를 추적한 결과, Animalia와 Plantae가 예측하기 가장 어려웠다(다른 레이블보다 5–10% 낮음). 이는 타당한데, 동물과 식물은 생물학적 계(kingdom)으로, 생물학적 강(class)보다 더 크고 상위의 범주이기 때문이다. 더 많은 종을 포함하고 시각적 다양성도 크므로, 고정된 수의 예시로 학습하기가 더 어렵다.
또 다른 예시: 클래스별 정밀도를 추적하며 얻은 핵심 요점
다음 글들에서는 초기 실험을 커리큘럼 학습 패러다임, 즉 학습 데이터의 순서가 성능에 영향을 주는지로 확장해 볼 예정이다. 그 과정에서 유용하다고 판단되는 wandb 기능과 실천 방법도 계속해서 소개하겠다. 그동안 관련 코드는 여기에서 확인할 수 있다 여기 아래 케라스-cnn-네이처.
전체 iNaturalist 데이터셋은 186 GB로, 편의를 위해 12K 서브셋을 다운로드할 수 있다 여기, 그리고 심링크를 이용해 더 다루기 쉬운 서브셋을 생성하는 도구들도 있습니다 여기.







이 글은 AI로 번역된 기사입니다. 오역이 있을 수 있으니 댓글로 알려주세요. 원문 보고서는 아래 링크에서 확인할 수 있습니다: 원문 보고서 보기