월가의 늑대 시장을 이겨라 - 월가를 뒤흔든 주식 천재의 필승 투자 전략
조던 벨포트 지음, 김태훈 옮김 / 한국경제신문 / 2025년 2월
평점 :
장바구니담기




이 서평은 출판사의 지원을 받아 작성하였습니다.

 

 

책 제목만 보면 시장을 아웃퍼폼하는 엄청난 비법이 담겨 있을 것 같지만, 아쉽(?!)게도 그런 건 없다. 오히려 코스톨라니의 "주식을 사라 그리곤 수면제를 먹고자라. 10년 뒤에 깨어나면 부자가 되어 있을 것이다."라는 조언에 걸맞는 책이다. 괜히 쓸데없이 고민하지 말고 혹은 함부로 행동하다가 수수료 날리지 말고, 공매도 같은 프로의 세계에 얼씬거리지도 말고 그냥 아마추어에 맞게 인덱스 펀드로 포트폴리오를 구성해라. 이게 책의 요지다.

 

허무할 수도 있을 것 같다. '더 울프 오브 월스트리트'의 실존 인물이라길래 엄청난 걸 기대한 사람에겐 특히 그럴 것 같다. 하지만 그런 건 있을 수 없다는 걸 오래전부터 투자 업종의 현인들이 얘기해왔고 지금도 얘기한다. 단기적으로 한 번에 되는 건 없다. 복리를 이용해야 한다 라는 건 버핏도 얘기했고 다른 투자자들도 얘기했다. 프로가 아니라면 굳이 시장을 완벽히 이기려 하지 말고 그냥 지수를 사라는 것도 마찬가지로 버핏이 이미 예전부터 얘기했다. 

 

결국 답은 멀리 있지 않은 것이다. 빨리 돈을 많이 벌기를 바라는 욕망이 그 답을 싫어하는 것일 뿐.

 

다른 영역은 행동하면 행동할수록 성공에 가까워질지 몰라도 투자의 영역은 그와 반대로 수수료와 세금이라는 중력이 강력하게 작동하는 영역인만큼 행동하면 행동할수록 마찰력은 커지고 원하는 목표에서 멀어진다.

 

그렇기에 어려운 것 같다.



댓글(0) 먼댓글(0) 좋아요(0)
좋아요
북마크하기찜하기 thankstoThanksTo
 
 
 
실리콘밸리가 원하는 사람 - 현직 실리콘밸리 엔지니어가 말하는 글로벌 커리어 & 로드맵
이원종 지음 / 비제이퍼블릭 / 2025년 2월
평점 :
장바구니담기





이 서평은 출판사의 지원을 받아 작성하였습니다. 

 

엔지니어가 말하는 글로벌 커리어 & 로드맵이라고 부제가 되어있지만 정확히 말하면 연구직 커리어를 가이드하는 책이다. 그동안 개발자를 위한 커리어 개발 가이드 서적은 많이 있었는데, 연구직을 위한 커리어 가이드 서적은 드물었기 때문에 이 책이 희소성을 가진다고 할 수 있다. 

 

특히 미국 진출을 원하는 연구직 포지션이라면 (물론 트럼프 2기 시대가 되면서 이전보다 많이 힘들어질 것으로 예상되지만) 도움이 많이 될 수 있을 듯하다. 

 

책에서 계속 강조하는 내용은 하드 스킬도 있겠지만, 결국 문화에 대한 내용이다. 정말 어렵게 회사에 입사한다 하더라도 결국 그 내부 구성원들과 소통하며 일을 해야 하는데, 한국 기업의 조직문화와 미국 기업의 조직문화는 (물론 미국 기업도 기업별로 팀별로 또 다르겠지만) 다를 것이고, 이를 이해하지 못하면 불필요한 갈등이 생기거나 혹은 적응하기 힘들 수도 있기 때문이다. 여기서 문화라고 함은 단순히 일하는 방식, 회식 만을 의미하는 게 아니라 직급 체계 등 전반적인 사회문화를 의미한다. 책에서도 설명하지만 한국에서 일반적으로 나누는 직급과 달리 미국에서는 직급 체계도 다르고, 커리어 육성 방식도 다르기 때문에 만약 간다면 그에 맞게 예상을 하고 적응해야지, 한국에 익숙한 채로 하다간 힘들 수 있을 거라고 생각한다.

 

논문을 잘 쓰는 법, 보고서를 잘 쓰는 법, 미국 취업하는 법 등 가이드를 구체적으로 잘 적어두었기 때문에(물론 위에서 말한 것처럼 트럼프 시대가 오면서 저자가 말한 방식이 작동하지 않을 수도 있다) 참고하면 큰 도움이 되리라 생각한다.

 



댓글(0) 먼댓글(0) 좋아요(0)
좋아요
북마크하기찜하기 thankstoThanksTo
 
 
 
자연어 처리를 위한 허깅페이스 트랜스포머 하드 트레이닝 - 코드와 결과물로 이해하는 언어 모델과 트랜스포머
박성환.남승우 지음 / 비제이퍼블릭 / 2025년 1월
평점 :
장바구니담기






이 서평은 출판사로부터 도서를 지원받아 작성하였습니다.

 

 

쉬운 책은 아니다. 실무형 책이기 때문에 쉽고 재밌게 원리부터 차근차근을 기대하기란 어렵다. 만약 그 점을 기대한다면 책에 실망할 확률이 높다. 그렇다 해도 대략적으로 용어나 단어에 익숙해진다고 생각하고 '대충' 보는 것도 괜찮다.

 

ML 리서처도 아니고 ML 엔지니어도 아니라면 굳이 이 책에 있는 개념들과 원리를 모두 하나하나 깊이 있게 알 필요는 없기 때문이다. 오히려 그보다도 대충 어떤 라이브러리가 쓰이는지, 어떤 용어가 쓰이는지 잘은 몰라도 '아 저런 단어가 쓰이는구나. 경량화라는 게 저런 의미구나'라는 정도만 이해해도 무방하다고 생각한다. (반대의 경우인 ML 리서처나 ML 엔지니어의 경우 얘기가 다르겠지만 말이다. 반대의 경우 이 책에서 나오는 설명과 코드 수준을 넘어서 원리까지 이해하고 최신 트렌드도 따라가야 할 것이다)

 

이렇게 서술하는 이유는 이 글을 서술하는 나부터 잘 모르겠기 때문이다. 이 쪽 분야에서 일하는 사람도 아니고 전문적인 교육을 받은 것도 아니다보니 알아듣는 말도 아주 조금은 있지만, 많은 경우 알아먹지 못한 게 사실이다.

 

그래도 좋았던 건 저자가 설명해주는 개념들과 역사를 훑어보니 어떤 걸 유튜브에 검색해서 하나하나 재미삼아 알아보면 좋을지 보이긴 했다는 거다. 저자의 말대로 이미 개인의 수준을 넘어선 토크나이저를 사전학습 시키는 걸 할 것도 아니고, 아키텍처를 직접 구축할 것도 아니고 그럴 실력도 안 되니 그저 하나하나 등산한다 생각하며 아주 조금씩 관심을 가져보는 게 그나마 할 수 있는 최선이 아닐까.

 

 

 

밑줄긋기

p.11

허깅페이스는 초기에 자연어 처리를 기반으로 성장하였습니다. 오픈소스 라이브러리 Transformers는 초기에 자연어 처리 관련 모델만을 지원했습니다. 서서히 규모가 커지며 모델뿐 아니라 학습 및 서빙을 위한 구현체가 등장했고 오늘날에 와서는 이미지 및 오디오 모델까지 다양한 인공지능 분야를 지원하는 전천후 라이브러리로 거듭났습니다. Transformers라이브러리는 원래 pytorch-pretrained-bert라고 불렸고 이후 pytorch-transfomers, Transformers 순으로 이름이 변경되었습니다. 파이토치, 텐서플로, 구글 잭스 라이브러리와 호환되며 BERT와 GPT 등의 언어모델이 등장하면서 점차 성장하였습니다.

 

허깅페이스가 엄청난 인기를 끌어 크게 성장하게 된 계기는 바로 구글이 한 논문을 발표한 사건 때문입니다. 구글 브레인은 2017년 [Attention is All You Need] 논문을 발표합니다. 바로 오늘날 자연어 처리를 넘어 전 분야에서 광범위하게 쓰이는 셀프 어텐션(self-attention) 기반 모델인 트랜스포머(Transfomer)를 발표한 사건입니다.

 

2018년 트랜스포머 인코더(encoder) 기반인 구글에서 발표한 BERT 모델과 트랜스포머 디코더(decoder) 기반인 GPT 모델이 오픈소스로 공개되었고 BERT와 GPT를 시작으로 하여 사전학습 모델을 활용하는 것이 머신러닝 트렌드가 되며 사전학습한 모델을 활용하는 것이 머신러닝 트렌드가 되며 사전학습한 모델을 공유하는 라이브러리인 Transfomers가 주목받게 되었습니다. 이로 인해 개발자 사이에 폭발적인 인기를 끌게 되고 이 시기가 허깅페이스 성장의 기점이 됩니다. 

 

p.26

허깅페이스 Datasets는 자연어 처리, 음성 처리, 컴퓨터 비전 작업을 위한 데이터셋을 공유하는 라이브러리입니다. 한 줄의 코드로 공개되어 있는 데이터셋을 불러오고 딥러닝 모델에 빠르게 활용할 수 있습니다. 참고로 허깅페이스는 모든 사람이 볼 수 있는 공개된 커뮤니티이기 때문에 보안 이슈에서 자유로운 뉴스나 위키피디아 등에서 쉽게 얻을 수 있는 일반적인 데이터를 공유하는 경우가 많습니다. 그래서 실제 자신만의 모델을 구축하기 위해 미세 조정을 진행할 때는 원하는 다운스트림(downstream) 태스크에 맞는 자체적으로 구축한 데이터를 활용하여 학습을 진행합니다.

 

p.27

한국어 자연어 이해 평가(Korean Language Understanding Evaluation, KLUE) 데이터셋을 활용해 보겠습니다. KLUE는 언어 모델의 한국어 능력을 평가하기 위한 데이터셋으로 총 여덟 가지 다양한 태스크로 구성되며 각 태스크는 다음과 같습니다.

 

1. 의존 구문 분석(Dependency Parsing, DP)

2. 기계 독해 이해(Machine Reading Comprehension, MRC)
3. 개체명 인식(Named Entity Recognition, NER)
4. 자연어 추론(Natural Language Inference, NLI)

5. 관계 추출 (Relation Extraction, RE)

6. 문장 유사도 비교 (Semantic Textual Similarity, STS)

7. 주제 분류 (Topic Classification, TC a.k.a YNAT)

8. 대화 상태 추적 (Dialogue State Tracking, DST a.k.a WoS)

 

p.37

이전 머신러닝과 과거 초기 신경망 모델에서는 형태소(명사, 조사, 접사, 어미 등 뜻을 가진 가장 작은 말 단위)를 기준으로 자연어를 토큰화했으며 이를 벡터화(vectorize) 또는 임베딩(embedding)하여 사용하였습니다. 그러나 형태소를 기반으로 토큰화하면 모든 형태소에 대한 단어사전(vocabulary)을 구축할 수 없기 때문에 지속적으로 업데이트해야 한다는 단점이 있습니다. 

 

이런 방식을 보완하기 위해 최근에는 서브워드(subword - 단어보다 더 작은 의미 단위) 기반 토크나이저가 등장했습니다. 서브워드 토크나이저는 기존 형태소 기반 토크나이저보다 언어 간 독립성을 보장하고 사전 어휘 이외의 자연어(Out Of Vocabulary, OOV) 문제를 해결할 수 있으며, 신조어 처리 등 다양한 변수에 대응하기가 용이하다는 등 여러 장점이 있기에 최근 언어 모델에 쓰이는 토크나이저 방식입니다. 토큰화 방법은 주로 파일 압축 알고리즘을 토대로 구현된 바이트 페어 인코딩(Byte Pair Encoding, BPE), 센텐스피스(SentencePiece), 워드피스(WordPiece) 등 방식을 사용합니다. Transformers는 자주 사용되는 서브워드 토크나이저를 모아 구현했으며 파이썬에서 사용할 수 있는 라이브러리로 토크나이저 클래스를 지원합니다. 단, 예외로 SentencePiece는 외부 라이브러리를 따로 설치해 이용합니다. 모델과 함께 학습된 토크나이저를 손쉽게 다운로드할 수 있고 이를 활용해 자연어를 해당 모델이 인식할 수 있도록 빠르게 전처리할 수도 있습니다.

 

p.38

사전학습한 모델은 각각 단어사전이 존재합니다. 따라서 각 모델에 맞게 학습된 토크나이저를 필요로 하기에 모든 토크나이저 역시 PretrainedTokenizer를 상속받으며 사용하려는 사전 학습 모델과 동일한 repo_id로 호출해야 합니다.

 

p.40

토크나이저는 일반적인 토큰과는 다른 특수 토큰(special token)을 가집니다. 이는 컴퓨터가 인식하기 위한 말 그대로 특별한 토큰이며 special_tokens_map으로 해당 토크나이저의 특수 토큰을 확인할 수 있습니다. 대표적인 특수 토큰으로 각각 begins of sentence와 end of sentence를 뜻하는 <bos>,  <eos> 토큰, 비슷한 역할인 [CLS], [SEP] 토큰 등이 있습니다.

 

p.41

일반적으로 두 개의 번호 기호(##)는 앞 토큰과 공백 없이 이어짐을 의미합니다. SentencePiece 토크나이저는 기본으로 ## 표시를 붙여서 이어짐을 표시하고 BPE 토크나이저는 토큰 앞부분에 밑줄 문자(언더바, _)를 붙여서 사용합니다. 

 

p.42

대부분 인코더 기반 모델은 [CLS], [SEP]처럼 대문자를 대괄호로 감싸고 디코더 기반 모델에서는 <bos>, <eos>와 같이 소문자를 홀화살괄호로 감싸 사용합니다. 인코더-디코더 기반 모델은 두 가지 방법 중 하나로 혼용되는 편입니다. 대부분 해당 형식을 따르지만 꼭 정해진 것이 아니기 때문에 모델별로 특수 토큰을 확인하는 것이 가장 확실한 방법입니다.

 

p.45

DataCollator는 데이터셋 요소 목록을 입력으로 사용하여 배치를 형성하는 객체입니다. 학습할 때, 모델에 데이터를 입력하기 전 추가 처리를 진행하기도 합니다. 학습할 때 미니배치 단위로 데이터에 어떤 작업을 진행해야 할 때 많이 쓰이는데, 이를 처리하는 것을 콜레이터(Collator)라고 합니다. 이러한 요소는 train_dataset과 eval_dataset 모든 요소와 동일한 유형으로 사용합니다.

 

p.55

Trainer는 학습을 전체 관리하는 클래스입니다. TrainingArguments는 Trainer에서 사용하는 파라미터를 관리하는 데이터 클래스입니다. 또한 파이토치의 완전한 학습을 위한 API를 제공합니다. 한 가지 유의해야 할 점이라면 Trainer는 파이토치에서만 사용할 수 있습니다. 과거에는 텐서플로에서도 사용할 수 있는 TFTrainer가 있었지만 텐서플로는 자체 추상화 수준이 매우 높기에 사용하지 않게 되었습니다.

 

p.58

Pipeline을 활용하면 굉장히 쉽게 추론을 사용할 수 있습니다. Pipeline은 모델과 태스크를 입력하거나, 혹은 특정 태스크로 학습된 모델을 입력하면 전처리부터 결과를 내는 모든 과정을 한 번에 처리해주는 강력한 기능입니다. 모델을 다 학습했다 하더라도 원본 텍스트 데이터를 입력하여 모델이 추론하도록 사용하기 위해서는 모델과 토크나이저를 불러와서 기울기를 제거하거나 디바이스를 설정하고 텍스트 인코딩과 모델 디바이스를 설정한 후, 결과를 추론하고 보기 쉽게 결과를 후처리해야 비로소 사람이 편하게 식별 가능한 결과를 얻을 수 있습니다. 꽤나 번거로운 작업입니다. Pipeline은 이런 문제를 간단히 해결합니다. 원본 텍스트 데이터를 그대로 입력하면 서너 줄의 코드만으로 딕셔너리에 정리된 모델 추론 결과를 얻을 수 있습니다.

 

p.69

OOM 대처법

 

배치 사이즈는 늘리고 싶은데 메모리 공간이 부족한 경우 가중치 누적(Gradient Accumulation)을 활용할 수 있습니다. 배치 데이터는 batch_size개 데이털르 한 번에 입력받아 순전파(forward propagation)를 거치고 곧바로 역전파(backward propagation)도 배치 크기만큼 한 번에 진행합니다. 반면 가중치 누적을 사용하면 순전파 연산은 batch_size개만큼 한 번에 연산을 진행하지만 이를 바로 역전파에 업데이트하지 않습니다. gradient-accumulation값만큼 순전파를 진행한 후 실행 결과를 통합해 한 번에 역전파 및 업데이트를 진행합니다. 즉, 실질적인 batch_size 크기가 batch_size * gradient_accumulation이 됩니다. 이 방법은 GPU 메모리가 작을 때 유용하게 사용할 수 있으나 속도가 느릴 수 있다는 단점이 있습니다.

 

p.88

챗GPT와 다수의 오픈소스 생성형 언어 모델이 떠오른 2023년부터 대규모 언어 모델(LLM)이 생성형 언어 모델의 주류가 되었습니다. 개인이 토크나이저부터 사전학습을 구축하는 사례는 흔히 찾기 어려우며 모델 및 토크나이저 사전학습을 위한 데이터를 구축하는 일 자체가 개인으로서는 불가능한 수준에 도달했습니다. 그럼에도 불구하고 해당 내용을 작성하는 이유는 토크나이저 또한 언어 모델의 일부로써 필수적인 요소로 기능하기 때문입니다. 소속된 직장이나 연구실 등 어떤 곳에서나 대규모 학습이 필요할 때 도움이 될 수 있길 바랍니다.

 

지금까지 Transformers 라이브러리를 이용해 모델과 함께 사전학습된 토크나이저를 불러와 활용했습니다. 사전학습된 모델을 미세조정하는 과정에서는 모델과 함께 학습된 토크나이저를 그대로 사용하면 되지만, 사전학습 단계부터 직접 진행해야 하는 경우에는 토크나이저 또한 함께 학습해야 했습니다. Tokenizers 라이브러리는 그러한 상황에서 간단한 코드 몇 줄로 서브워드 토크나이저를 학습할 수 있도록 하며, 이를 Transformers 라이브러리에서도 사용할 수 있도록 변환하는 등 다양한 기능을 제공합니다. Tokenizers 라이브러리의 또 다른 특징은 러스트(Rust) 언어로 구현되었다는 점입니다. 파이썬이란 언어는 쉬운 문법과 넓은 확장성으로 정말 많은 분야에서 사용됩니다. 굉장히 강력한 장점이지만 모두가 인정하는 한 가지 단점이 존재하는데, 바로 속도가 느리다는 점입니다. 허깅페이스에서는 이 점에 집중하여 매우 빠른 저수준 언어 러스트를 사용해 빠른 속도로 토큰화를 진행할 수 있돌고 처리했습니다.

 

p.109

트랜스포머 모델이 등장한 이후 대부분의 모델이 트랜스포머 모델 인코더나 디코더 중 하나만 사용하거나 둘 다 사용하는 형태로 구성되기 시작합니다. 2018년 6월, 트랜스포머 디코더 구조를 사용한 최초의 사전학습 모델인 GPT가 제안되었습니다. GPT 모델은 대규모 데이터로 미리 학습된 최초의 트랜스포머 기반 모델입니다. 

 

p.111

인코더 기반 모델은 트랜스포머 모델의 인코더 부분만 사용하는 모델입니다. 인코더 기반 모델은 대부분 문장 분류나 토큰 분류와 같은 비교적 연산이 단순한 태스크에 사용됩니다. 사전학습을 진행한 후 임베딩 레이어와 트랜스포머 인코더 부분만을 저장하며 태스크에 따라 모양에 맞는 헤더를 부착해 미세조정합니다. 예를 들어, 문장 분류에서는 한 토큰의 벡터 정보만 가져다 선형 레이어를 부착해 사용하고 토큰 분류에서는 토큰마다 완전 연결층을 연결해 토큰별로 어떤 품사인지 분석하는 방식 등이 존재합니다.

 

인코더 기반 모델은 완성된 문장을 입력받아 이를 이해하는 것을 목적으로 하기에 이를 자연어 이해라고도 부릅니다. 주로 문장 분류 등 비교적 간단한 작업에서 사용합니다. 인코더 모델에는 BERT, RoBERTa, XLM, ELECTRA 등이 있습니다. BERT 이후 제안된 RoBERTa는 BERT 사전학습 전략을 보완하여 전처리 중 최초 한 번이 아닌 에포크마다 토큰을 무작위로 마스크하는 동적 마스킹을 제안해 기존 방법론을 개선하였습니다. 이후에는 대규모 모델을 학습하는 대신 달느 전략으로 압축 기술인 지식 증류를 사용하여 성능을 거의 유지하면서 크기를 줄인 DistilBERT가 출시되었고, 큰 어휘 임베딩을 두 개의 작은 행렬로 분리하고 레이어악 파라미터를 공유하도록 학습 효율성에 초점을 맞춘 ALBERT, 단어와 위치가 두 개 벡터로 인코딩되어 분리되는 어텐션 메커니즘이 추가된 DeBERTa 등이 제안되었습니다. 

 

p.112-113

- 토큰 임베딩(token embeddings) : 우리가 알고 있는 기본 임베딩 층입니다. 각 토큰은 정해진 크기의 실수 벡터로 변환됩니다. 기본 크기 BERT-Base 모델은 768의 길이를 가집니다.

 

- 세그먼트 임베딩(segment embeddings): BERT 모델은 사전학습을 진행할 때 두 문장을 입력받아 예측하는 방법이 포함됩니다. 세그먼트 임베딩은 입력된 두 문장을 구분하기 위해 사용하는 임베딩으로, 각 문장에 각기 다른 벡터값을 적용합니다. Transformers 라이브러리에서는 token_type_ids라는 이름으로 사용됩니다. 단, 모델에 따라 사용하지 않는 경우도 있습니다.

 

- 포지션 임베딩(position embeddings): 문장 순서 정보를 인식시키기 위해 사용됩니다. 순서대로 모델에 입력되는 순환신경망(RNN)과 달리 셀프 어텐션 방법은 여러 토큰을 동시에 연산하기에 모델이 토큰 순서 정보를 이해할 수가 없습니다. 이를 위해 사용되는 방법으로, 토큰 위치에 따라 다른 벡터값을 추가해 순서정보를 인식시킵니다.

 

한 가지 유의할 점은 기본 트랜스포머 모델은 위치 인코딩을 사용한다는 것입니다. 위치 임베딩이 위치에 따른 임베딩 값을 학습 간으한 파라미터로 처리하는 반면 위치 인코딩의 임베딩 값은 변화하지 않는 상수 값입니다. BERT 이후의 모델들은 위치 임베딩을 기반으로 위치 정보를 전달하지만 위치 정보를 입력하는 부분은 모델마다 상이합니다. 각 모델의 차이를 자세하게 알고 싶다면 위치 정보를 입력하는 부분을 유심히 살펴보기 바랍니다.

 

BERT 모델은 사전학습을 위해 다음 문장 예측(Next Sentence Prediction, NSP)과 마스킹된 언어 모델 (Masked Language Model, Masked LM)이라는 두 가지 방법을 제안합니다. 그 중 NSP는 모델에 두 문장 A 와 B가 주어졌을 때 어떤 문장이 앞선 문장인지를 예측하는 이진 분류 태스크입니다. 두 문장의 구분을 위해 앞서 언급한 세그먼트 임베딩을 사용합니다. Masked LM은 앞서 간략히 설명했듯 입력 토큰 일부를 [MASK] 토큰으로 치환하여 입력한 후, 바뀐 토큰이 원래 무엇인지를 추론하는 태스크입니다. 해당 치환 과정을 마스킹 혹은 오염(corruption)이라 표현하며, BERT 논문에서는 마스킹이란 표현을 사용합니다. 잘 쓰이지 않는 NSP와 달리 꽤 오랜 기간 사용되었던 학습 방법입니다.

 

p.113

문장 분류 태스크는 2차원 문장 임베딩에서 여러 클래스 중 하나만을 고르는 1차원 확률분포를 반환합니다. 이를 위해 모델은 고차원 데이터를 저차원 데이터로 압축하는 풀링(pooling) 작업을 진행합니다. 풀링에는 여러 가지 방법이 있는데 단순히 특정 차원축의 모든 벡터값을 합하거나(reduce-sum) 혹은 평균(reduce-mean)내어 사용하는 등의 방법이 있습니다.

 

트랜스포머 인코더 모델은 문장의 모든 정보를 하나의 토큰 벡터에 저장하도록 학습하며 해당 토큰이 바로 문장 가장 앞에 자리한 [CLS] 토큰입니다. [CLS] 토큰은 Classification을 뜻하며 문장의 맨 앞에 삽입되어 분류 태스크에 사용되거나 문장 시작(Begin Of Sentence, BOS)을 알리는 토큰으로 사용되고, 나머지 태스크에서는 대부분 무시됩니다. 전술한 바와 같이 분류 태스크에 한하여 문장 전체 정보를 [CLS] 토큰에 담도록 학습하며, [CLS] 토큰 벡터를 입력으로 받는 순방향 신경망(FeedForward Neural Network, FFNN)을 추가로 부착해 미세조정을 진행합니다.

 

p.136

질의응답(Question-Answering, QA) 태스크는 모델이 질문에 대해 답변을 하게 만드는 태스크로 주어진 문장 텍스트와 질문을 모델에 입력해 그에 대한 답변을 하도록 합니다. 또한, 컴퓨터가 질문에 대한 답변을 하도록 하는 기계 독해 이해(Machine Reading Comprehension, MRC) 작업 하위 카테고리로 분류할 수 있으며 주어진 정보를 기반으로 답변을 하는 특성으로 인해 정보 검색, 대화형 시스템, 지식 기반 시스템 등 다양한 응용 분야에 유용하게 활용될 수 있습니다.

 

질문에 대한 답변을 만드는 과정은 추출(extractive)과 생성(generate) 두 가지로 나뉩니다. 추출 질의 응답은 질문에 대한 답변을 입력된 콘텍스트에서 말 그대로 추출해내는 방식이고 생성 질의 응답은 문제에 대한 답을 입력 콘텍스트를 참고하여 새로 작성하는 방법입니다.

 

- 추출: 주어진 콘텍스트에서 답변을 추출합니다.

- 생성: 질문에 정확하게 답하는 맥락에서 답을 생성합니다.

 

일반적으로 BERT와 같은 인코더 기반 모델은 추출 방법처럼 사실을 기반으로 답변하는 데에는 강한 모습을 보이지만 개방형 질문에 대해 왜 그런지 답하는 문장 생성 기반 작업에서는 비교적 취약한 모습을 보입니다. T5와 같은 인코더-디코더 모델, 혹은 GPT 같은 디코더 기반 모델은 인코더 모델에 비해 해당 작업에 보다 더 좋은 결과를 추출합니다. 

 

p.142-143

디코더 기반 모델

 

트랜스포머 아키텍처에는 인코더만으로 구성된 모델뿐만 아니라 디코더만으로 구성된 모델도 존재하며, 오히려 인코더 기반 모델보다 디코더 기반 모델에 훨씬 더 다양한 종류의 모델이 속해 있습니다. 특히 GPT 모델은 디코더 모델의 대표 예시로, 현시점에 가장 영향력 있는 인공지능 기업이라 할 수 있는 오픈AI에서 고안되었습니다. GPT 모델은 BERT 모델과는 다르게 디코더 구조로 이루어져 있으며 이후에 대규모 언어모델(LLM) 시대를 이끈 챗GPT 모델의 기반이 되었습니다. 또한 인코더 기반 BERT와 디코더 기반 GPT는 트랜스포머 각각의 구조를 활용하여 수많은 거대 데이터를 학습하여 사용하는 사전학습 모델 개념이 시작된 모델이기도 합니다.

 

이번 섹션에서는 디코더 기반 모델에 대해서 알아보려고 합니다. 디코더 기반 모델은 문장 앞부분 일부만을 입력받아 이를 이어서 작성하는 형태이며 이를 자연어 생성이라고도 말합니다. 주로 문장 자동완성 등 복잡한 작업에서 사용하고 GPT-1~4, PaLM, BLOOM, MT-NLG, LaMDA, LLaMA 등이 있습니다.

 

디코더 기반 모델의 대표인 GPT 모델은 디코더로 구성되어 입력 시퀀스에서 이전 단어를 기반으로 다음 단어를 예측하는 방식으로 학습합니다. 이런 방식으로 GPT 모델은 문맥을 이해하고 문장을 생성하며 이를 통해 대화 응답, 텍스트 생성, 내용 요약 등 다양한 자연어 처리 작업을 수행합니다. GPT-1은 2018년에 처음 발표되었고 영어 위키피디아와 뉴스 기사로 학습하여 파라미터 수 약 1.17억 개(117M)로 시작하였습니다. 이후 학습하는 데이터 크기와 모델 파라미터 개수, 즉 모델의 크기가 커질수록 성능이 대폭 향상된다는 것이 정설로 자리잡으며 인터넷에 있는 대용량 웹페이지 텍스트를 학습시키게 되었고 GPT-2는 파라미터 수 약 15억 개(1.5B), GPT-3는 파라미터 수 약 1,750억 개(1.75T)로 발전해왔습니다. GPT도 구체적으로 보면 내부 언어 이해가 어떤 방식으로 진행되는지에 대해 설명이 모호한 점이 있습니다. 하지만 데이터와 모델의 크기가 커짐에 따라 추가 미세조정을 하지 않아도 명령문(Prompt)과 샘플 데이터 몇 개(few-shot) 혹은 샘플 데이터 없이(zero-shot) 추론할 수 있는 방향으로 발전을 거듭하고 있습니다. 

 

기본 구조

 

디코더 기반 모델은 이름 그대로 트랜스포머 모델 디코더 부분만을 분리해 사용하는 구조입니다. 셀프 어텐션, 인코더 참조 어텐션, FFNN으로 이루어진 기존의 트랜스포머 디코더에서 인코더 참조 부분을 제거하여 두 단계로 구성됩니다. 자신을 참조하는 셀프 어텐션을 거치고 인코더와 동일하게 FFNN 층을 거칩니다. 이를 여러 개 레이어로 층층이 쌓은 형태의 모델이 바로 디코더 기반 모델입니다. 인코더 기반 모델의 주요 태스크는 완성된 문장을 분석하는 것이기에 이미 완성된 문장이 입력된다는 전제하에 문장의 시작부터 끝까지 한 번에 분석을 진행합니다. 이에 반해 디코더 기반 모델의 주요 태스크는 미완성의 문장을 이어서 작성하는 생성 태스크입니다. 미완성 상태로 작성 중인 문장을 실시간으로 확인하며 직접 이어 나가야 하기에 문장 일부만으로 자연스럽게 다음 단어를 예측하는 단방향 형태로 분석을 진행합니다.

 

p.144

인과적 언어 모델(Causal LM)은 디코더 기반 언어 모델의 시작과 끝이라고 할 수 있는 생성 태스크입니다. 생성 태스크는 앞서 디코더 기반 모델을 설명했던 바와 같이 주어진 문장을 토대로 다음에 쓰일 토큰을 예측하는 모델입니다. 완성되지 않은 문장을 이어나갈 수도 있고 완전한 문장을 입력받더라도 같은 주제로 계속해서 유연하게 답을 작성할 수도 있습니다. 심지어 정해진 양식에 따라 대규모 데이터셋을 활용하여 학습한다면 모델과 자유롭게 대화할 수 있는 챗봇이 될 수도 있습니다. 그야말로 무궁무진한 가능성을 지닌 태스크라고 할 수 있습니다. 허깅페이스에서는 이전 토큰에 따라서 다음 토큰이 결정되기에 이를 인과적 생성(Causal Generation)이라 부릅니다. 

 

p.157

인코더 기반 모델과 디코더 기반 모델의 가장 큰 차이는 입력 방식입니다. 이는 모델 구조에도 영향을 끼치는 문제인데, 인코더 기반 모델은 이미 완성된 문장을 입력받는 구조이므로 어텐션 과정에서 모든 토큰이 다른 모든 토큰에 영향을 끼칠 수 있습니다. 그에 반해 디코더 기반 모델은 완성되지 않은 문장을 입력받는 것을 전제로 하며 이로 인해 다음에 출력된 토큰은 이전 순서 토큰에 영향을 줄 수 없습니다. 인코더 기반 모델은 문장을 양방향으로 분석하며 디코더 기반 모델은 단방향으로 분석합니다.

 

분석 방법의 차이로 인해 디코더 기반 모델로 문장 분류와 같은 태스크를 수행할 때 인코더 모델과 동일하게 처리하면 애로사항이 발생합니다. 디코더 모델은 이전 토큰의 영향을 받는 가장 마지막으로 입력된 토큰 벡터만을 가지고 추론을 진행해야 하는데, 문제는 모델에 입력되는 문장 길이가 모두 달라 여러 개를 동시에 처리하기가 어렵다는 것입니다. 이를 해결하기 위해 패딩 토큰을 사용해 배치로 입력되는 데이터는 길이를 맞추어야 합니다.

 

p.160-161

인코더-디코더 기반 모델

 

BERT와 같은 인코더 기반 모델, GPT와 같은 디코더 기반 모델을 보면 한 가지 의문이 생길 수 있습니다. 기초가 되는 트랜스포머 모델은 인코더-디코더 기반 모델인데 굳이 인코더나 디코더 둘 중 하나의 구조인 모델을 사용할 이유가 있을까? 기본 트랜스포머 구조와 같이 둘 다 사용하면 안 되는 것일까? 답은 '상관없다'입니다. 인코더-디코더 기반의 기본 형태를 유지한 채로 높은 성능을 낼 수 있는 모델도 존재하며 이를 대표하는 모델이 있습니다. 이번 섹션에서는 트랜스포머 인코더-디코더 기반 모델에 대해 알아보겠습니다. 

 

기본 구조

 

트랜스포머 모델의 구조와 동일하게 인코더-디코더 모델에서도 셀프 어텐션 기반 인코더와 디코더가 사용됩니다. 다른 점이라면 기본 트랜스포머 성능을 높이기 위해 더 많은 수의 학습 파라미터를 사용한 것, 그리고 다양한 태스크에서 효과적인 성능을 낼 수 있도록 다른 활성화 함수 등 추가 방법론을 도입한 것입니다.

 

인코더-디코더 기반 모델은 완성된 문장을 입력받아 입력과는 완전히 다른 새로운 문장을 생성하는 것을 목적으로 합니다. 디코더 기반 모델의 자연어 생성과 비슷하지만 입력된 문장을 이어 나가는 디코더 기반 모델과는 달리 완전히 새로운 문장을 작성한다는 차이가 있습니다.

 

인코더-디코더 모델은 주로 번역 등 태스크에서 사용합니다. 대표 모델로 BART, T5, Marian 등이 있습니다. 

 

BART 모델은 Bidirectional Auto-Regressive Transformer, 즉 양방향 자동 회귀 트랜스포머의 약자로 말 그대로 GPT 같은 생성 태스크를 진행할 때 입력을 BERT 방식과 같이 양방향으로 분석합니다. NSP와 Masked LM을 사용한 BERT 모델, Masked LM과 비지도 학습을 사용한 GPT 모델과 달리 BART 모델은 원본 데이터를 여러 가지 방법으로 오염시키고 이를 복구해 다시 생성하는 방식으로 학습을 진행합니다. 데이터를 오염시키는 방법은 다음과 같습니다. 

 

- 토큰 마스킹(Token Masking): BERT에서도 사용했던 일반적인 Masked LM과 동일합니다.

- 토큰 삭제(Token Deletion): 랜덤한 토큰을 삭제하고 이를 복구합니다. 마스킹 방법은 특정 토큰을 [mask] 토큰으로 변경했던 반면, Deletion 방법은 말 그대로 특정 토큰을 랜덤으로 삭제하기 때문에 어떤 위치의 토큰이 사라졌는지 알 수가 없습니다.

- 텍스트 채우기(Text Infilling): 입력 문장 중, 연속되는 토큰 몇 개를 묶어 토큰 뭉치(text span)를 생성해 이 범위를 [mask] 토큰으로 치환합니다. 이때, 토큰 뭉치 길이는 포아송 분포를 따르며 길이가 0일 수도 2 이상일 수도 있습니다. 길이가 0인 경우 정상 문장에서 [mask] 토큰만 생성되고 2 이상인 경우 여러 토큰이 하나의 [mask] 토큰으로 바뀌게 됩니다. 따라서 모델이 범위에서 누락된 토큰 수에 대해서도 학습할 수 있도록 합니다.

- 문장 순서 바꾸기(Sentence Permutation): 입력 문서를 문장 단위로 분할한 후, 문장의 순서를 무작위로 섞어버립니다.

- 문서 회전(Document Rotation): 입력 문장 중, 토큰 하나를 무작위로 정해 해당 토큰이 문장의 시작이 되도록 해당 문장 토큰을 밀어냅니다. 시작 토큰 앞에 있던 토큰은 문장 맨 뒤로 이동합니다.

 

여러 가지 방법으로 데이터를 오염시킨 후 모델이 이를 복원하는 방식으로 사전학습을 진행하여 낮은 품질의 데이터에서도 효과적으로 문장을 생성할 수 있도록 진행합니다. 

 

p.162

인코더-디코더 기반 모델은 트랜스포머 모델을 기반으로 합니다. 트랜스포머 모델이 번역을 목적으로 고안된 만큼 해당 계열 모델 역시 주된 태스크는 생성, 그 중에서도 번역과 같이 새로운 문장을 작성하는 것입니다. 어떤 문장이 주어졌을 때 해당 문장을 기반으로 새로운 문장을 작성하는 태스크를 허깅페이스에서는 조건부 생성(Conditional Generation)이라는 이름으로 부릅니다. 디코더 기반 모델의 인과적 생성과 같이 일반적인 상황에서 다수 개발자가 따로 구분하지 않고 생성이라 부르기 때문에 여기에서도 '생성'이라는 명칭을 사용하겠습니다. 

 

인코더-디코더 기반 모델에서의 생성은 디코더 기반 모델 생성과는 달리 입력 문장과 직접 연결되는 방식이 아닙니다. 다시 말해 이어서 쓰는 게 아니라 질문에 대한 답변에 좀 더 가깝다고 할 수 있습니다. 일반적으로는 입력 문장을 다른 언어로 번역하는 기계 번역이나 긴 문서를 짧은 문장으로 요약하는 요약 태스크에 주로 사용합니다.

 

p.214

2020년 GPT-3를 기준으로 이후에 제안된 모델의 파라미터 개수는 이전에 비해 기하급수적으로 증가했고 최근 대규모 언어 모델이라고 불리는 LLaMA, Alpaca, Mistral, Gemma 등 모델은 파라미터 수가 최소 20억 개(2B)에서 시작하여 많게는 4,050억 개 (405B)라는 어마어마한 크기를 가지고 있습니다.

 

모델 크기와 성능이 선형적인 관계를 가진다는 트랜스포머 기반 모델 특성상 기반이 되는 모델 아키텍처 자체가 바뀌지 않는 이상 크기 증가는 필연적인 일이었습니다. 또한 아무리 제로샷(Zero-shot) 러닝, 퓨샷(Few-shot) 러닝, 프롬프트 엔지니어링 등 기법이 대두되고 발전해도 사전학습된 모델을 사용하는 데이터 도메인에 맞춰진 미세조정이 확연히 높은 성능을 보이는 것이 명백한 사실입니다. 모델 크기가 증가함에 따라 이를 학습하고 추론할 때 연산량과 사용되는 자원량 또한 무시하지 못할 정도로 커지게 되었고 이는 곧 하드웨어에 가해지는 부담으로 직결되었습니다. 모델은 점차 발전하는데 정작 이를 활용하지 못하는 상황이 발생하게 되자, 연구 방향도 "어떻게 성능을 끌어올릴 수 있는가"와 더불어 "어떻게 모델을 효율성 높게 사용할 수 있는가"에 초점을 맞춰 모델 크기 최적화, 모델 경량화라는 주제에도 집중하는 결과를 낳았습니다. 

 

p.215

PEFT(Parameter-Efficient Fine-Tuning)는 의미 그대로 파라미터를 미세조정하는 효율을 높이는 방법론이자 동명의 라이브러리입니다. 사전학습된 대규모 모델의 파라미터를 좀 더 효율적으로 적용하기 위한 개념입니다. 사전학습된 모델을 미세조정하는 것은 굉장한 시간과 비용을 발생시킵니다. PEFT 방식을 활용하면 사전학습 모델의 모든 파라미터가 아닌 소수 추가 파라미터만으로 다양한 다운스트림 태스크를 진행합니다.

 

좀 더 자세히 설명하자면 사전학습 모델 대부분의 파라미터를 동결(freeze)시켜 업데이트가 되는 것을 막고 소량의 추가 파라미터만 학습하여 저장공간과 계산 비용을 대폭 줄여 미세조정과 유사한 성능을 내도록 하는 것이 PEFT의 목표입니다. PEFT 방식을 활용하면 모델 전체 파라미터를 미세조정할 때 발생하는 치명적인 망각(Catastrophic Forgetting) 문제를 피할 수 있고 학습할 데이터가 적은 경우에는 전체 파라미터 미세조정보다 더 나은 성능을 보였습니다. 또한, 이러한 방식을 통해 한정된 컴퓨팅 자원에서 활용하기 어려운 비교적 큰 크기의 LLM을 적은 계산 비용으로 학습하고 저장할 수 있게 됩니다. 결론적으로 PEFT 방식을 활용하여 미세조정을 한 경우 학습한 파라미터는 단 몇 MB에 불과하지만 전체 미세조정에 필적하는 성능을 얻을 수 있습니다. 

 

p.230

양자화(Quantization) 방법은 모델 경량화 기법 중 하나로 모델 가중치의 데이터 타입을 용량이 적은 타입으로 변경하여 모델 메모리 사용을 줄이고 추론 속도를 가속화하는 데 큰 영향을 미치는 유용한 기술입니다. 너무 큰 규모 모델은 미세조정뿐 아니라 추론마저도 자원이 부족한 환경에서는 쉬운 일이 아닙니다. 양자화 기술을 사용하여 한정된 자원 환경에서도 큰 규모 모델을 사용할 수 있도록 모델 자체의 용량을 줄일 수 있습니다. 

 

양자화란 많은 비트를 사용하는 데이터 타입을 적은 비트를 사용하는 데이터 타입으로 변경시키는 것을 말합니다. 예를 들어, 대부분 모델의 파라미터는 32비트 부동소수점(float32)으로 저장되는데 이 파라미터 타입을 16비트 부동소수점(flaot16)로 변경할 수 있습니다. 해당 방법을 사용하면 모델이 메모리상 차지하는 용량을 줄일 수 있을 뿐 아니라 연산 속도도 빨라질 수 있기에 추론 속도의 개선을 기대할 수 있습니다. 단, 32비트 파라미터를 16비트로 바꾸는 작업이기에 당연히 정보 손실이 일어나며 이로 인해 성능이 저하되므로 성능과 가용 자원 사이에서 적절한 중간점을 찾아야 합니다.

 

일반적으로 모델을 양자화하면 추가 다운스트림 태스크를 수행하지 않습니다. 그러나 PEFT 어댑터를 양자화 기술과 동시에 사용하면 이를 좀 더 유연하게 관리할 수 있으며 큰 규모 모델을 효율적으로 학습할 수 있습니다. 

 

p.237

fp16과 bf16 모두 실수를 표현하는 16비트 데이터 타입입니다. 부동소수점 실수를 사용할 때는 메모리를 부호(+-), 지수부(exponent), 가수부(mantissa) 세 가지로 나누어 사용합니다. 

 

32비트를 사용하는 fp32는 부호 1, 지수부 8, 가수부 23비트로 이루어집니다. 16비트인 fp16의 경우 부호 1, 지수부 5, 가수부 10비트로 나뉩니다. 지수부가 줄어들었으므로 값의 범위 또한 좁아지게 됩니다. 표현력이 떨어지므로 그만큼 성능이 줄어들게 됩니다. 

 

bf16은 동일하게 16비트로 이루어졌지만 비트 1, 지수부 8, 가수부 7로 이루어집니다. fp16보다 지수부가 많기 때문에 더 넓은 범위의 값을 가질 수 있지만, 가수부가 적기 때문에 세부적인 정밀도가 떨어지게 됩니다.

 

fp16과 bf16 모두 32비트의 값을 압축하는 형태이기에 정보 손실은 필연적입니다. 다만 인공신경망 모델은 가수부보단 지수부의 크기로 인한 범위에 더욱 민감하기에 일반적으로 bf16 타입을 많이 사용하는 추세입니다.

 



댓글(0) 먼댓글(0) 좋아요(0)
좋아요
북마크하기찜하기 thankstoThanksTo
 
 
 
대규모 머신러닝 시스템 디자인 패턴 - 14가지 패턴으로 분산 머신러닝 파이프라인 구축하기
위안 탕 지음, 정민정 옮김 / 한빛미디어 / 2024년 11월
평점 :
장바구니담기



이 서평은 출판사의 후원을 받아 작성하였습니다.

 

어떤 분야가 되었건 마찬가지겠지만, 머신러닝도 똑같이 실무에 가면 이런저런 문제에 부닥친다. 특히 단순히 머신러닝의 수학적 모델링에 관한 문제뿐 아니라, 서버나 다른 인프라 같은 문제들이 실무를 해야 하는 사람들에게 풀기 어려운 과제가 되곤 한다. 

 

풀기 어렵다는 말은 단순히 문제가 기술적인 측면에서 어렵다는 의미는 아니다.

물론 기술적으로 어렵다. 분산처리 시스템인데 당연히 어려울 수밖에 없다. 

 

하지만, 실무를 해야하는 곳이 분산처리 시스템을 운용해야할 만큼 규모가 큰 데이터를 다루는 곳이라면, 각 팀마다 R&R이 다를 것이고, 인프라를 다루는 팀이나 DBA나 각각 분리되어있고, PM 조직도 따로 있을 것이기 때문에 이들과의 소통 및 협업을 통해 원하는 것을 이끌어내야 한다는 점이 더 어려울 것이다. 

 

그렇기에 이 책은 ML을 실무로 하지 않는 나 같은 사람에게도 유용한 책일 수 있다.

 

이 책을 100% 이해할 필요가 없기 때문이다. 깊이 있는 MLOps는 잘 모르더라도, 대략적으로 어떤 용어를 어떤 개념으로 사용하는지, 어떻게 문제접근을 하는지 소통을 하기 위한 도구 정도로 생각하면서 읽어본다면, 컴퓨터 공학적 지식도 쌓으면서 인프라와 ML 모두에 가까워질 수 있다. 물론 쉽진 않겠지만 말이다.

 

 

 

 

 

밑줄긋기

 

p.51

넘파이 배열 형태로 메모리에 올라가있던 Fashion-MNIST 데이터셋을 텐서플로의 from_tensor_slices() API를 사용해 tf.Dataset 객체로 변환했다. 이 과정에서 넘파이 배열은 메모리상에 여러 번 복사되었고, 결과적으로 tf.GraphDef의 메모리 제한값인 2GB에 다다르면서 메모리 에러가 발생했다. 즉, 이런 방식으로는 이보다 큰 데이터셋은 사용할 수 없다.

 

이런 문제는 텐서플로와 같은 프레임워크를 사용하다보면 흔히 발생할 수 있다. 해결책은 간단하다. 이런 패턴은 텐서플로의 성능을 최대로 활용하지 않는 패턴이므로, 더 큰 데이터셋을 사용하기 위해서는 전체 데이터셋을 메모리에 모두 올리지 않고 사용할 수 있는 다른 API를 사용해야 한다. 

 

예를들어 tensorflow_io는 기본 텐서플로가 제공하지 않는 파일 시스템이나 파일 포맷 등과 관련된 기능을 모아놓은 라이브러리이다. 아래 코드와 같이 tfio.IODataset.from_mnist()를 이용하면 MNIST 데이터셋을 로컬 디스크에 저장하지 ㅇ낳고 바로 메모리에 올릴 수 있다. 이는 tensorflow_io가 내부적으로 HTTP 파일 시스템을 사용하기 때문이다.

 

import tensroflow_io as tfio

dataset_url = "https://storage.googleapis.com/cvdf-datasets/mnist/"
d_train = tfio.IODataset.from_mnist(
    dataset_url + "train-images-idx3-ubyte.gz"
    dataset_url + "train-labels-idx1-ubyte.gz"
   )

 

p.54~55

배치 처리를 수행하기에 앞서 고려해야 하는 사항이 있다. 이 방식은 데이터셋을 스트리밍 방식으로 전체 데이터셋의 일부로 학습을 실행할 수 있는 수학적 연산이나 알고리즘에만 적용할 수 있다. 다시 말해 알고리즘 학습을 위해 전체 데이터셋을 한 번에 학습하는 것이 필요하다면 배치 처리를 사용할 수 없다. 예를 들어 학습을 위해 특정 피처의 총합을 알아야 하는 알고리즘이라면 배치 처리는 실행 가능한 방법이 아니다. 전체 데이터셋의 부분 집합으로는 해당 정보를 얻을 수 없기 때문이다. 머신러닝 연구자나 실무자가 Fashion-MNIST에 대해 더 나은 성능과 정확도를 얻고자 다양한 머신러닝 모델을 사용한다고 가정해보자. 이때 어떤 알고리즘이 모델의 파라미터를 업데이트하기 위해 각 클래스마다 최소 10개의 데이터를 필요로 한다면, 배치 처리는 적절한 방법이 아니다. 모든 미니배치에 각 클래스별로 항상 최소 10개의 데이터가 포함되는 것이 아니기 때문이다. 특히 배치 크기가 작다면 더욱 그렇다. 극단적인 예시로 배치 크기가 10인 경우를 생각해보자. 모든 미니배치에 각 클래스의 데이터가 최소 하나씩 포함되는 경우, 즉 10개 클래스의 데이터를 모두 한 장씩 포함한 10장이 구성되는 경우는 매우 드물 것이다.

 

기억해야 할 또 다른 점이 있다. 머신러닝, 특히 딥러닝 모델을 학습시킬 때 적절한 배치 크기는 자원을 얼마나 사용할 수 있느냐에 따라 크게 달라진다는 것이다. 특히 공유 자원 환경(shared-resource environment)이라면 배치 크기를 결정하는 것이 더욱 어려워진다. 머신러닝 학습에서 자원을 얼마나 효율적으로 활용하는지는 모델의 구조뿐만 아니라 배치 크기에도 달려 있다. 이렇게 자원과 배치 크기 사이의 상호 의존성은 머신러닝 실무자가 작업을 효율적으로 실행하고 자원을 활용하기 위해 고려해야 하는 것들을 더욱 복잡하게 만든다. 

 

다행히도 배치 크기를 자동으로 최적화해주는 알고리즘과 프레임워크가 있다. 예를 들어 AdaptDL(https://github.com/petuum/adaptdl)을 사용하면 자동으로 배치 크기를 조절하여 효율적으로 분산학습을 할 수 있다. 이 프레임워크는 학습 과정에서 시스템 성능과 그레이디언트 노이즈 스케일을 측정하여 가장 효율적인 배치 크기를 선택한다. 

 

p.58

배치 처리 방식은 모델을 배치별로 순차적으로 학습시킬 충분한 시간이 있는 경우에만 괜찮은 방법일 수 있다. 그러나 실제 애플리케이션을 개발하기 위해서는 더 효율적으로 모델을 학습시키는 방법이 필요하다. 

 

p.60

큰 데이터셋을 여러 개의 작은 조각으로 나누어 여러 워커에 분산시키는 프로세스를 샤딩(sharding)이라고 하며, 이러한 작은 데이터 조각을 데이터 샤드(data shard)라고 한다.

 

p.61

샤드는 본질적으로 전체 데이터셋의 일부를 포함하도록 분할하는 수평 데이터 분할 (horizontal data partition)이며, 가로 분할이라고도 한다. 

 

p.63

수동 샤딩의 가장 큰 문제는 샤드가 균일하지 않게 할당될 수 있다는 점이다. 샤드의 크기가 균일하지 않으면 문제가 발생할 수 있다. 일부 샤드는 과도하게 커져 과부하가 걸리는 반면, 다른 샤드는 지나치게 작아 워커의 자원이 낭비될 수 있다. 이러한 불균형은 여러 개의 워커로 모델을 학습시키는 프로세스가 지연되는 원인이 된다. 

 

p.64~65

한 샤드에 너무 많은 데이터가 들어가게 되면 속도가 느려지거나 서버에 과부하가 걸릴 수 있으므로 피하는 것이 좋다. 이 문제는 전체 데이터셋을 너무 적은 수의 샤드에 강제로 분산시키는 경우에 발생할 수 있다. 개발 환경 혹은 테스트 환경에서는 시도해도 큰 문제가 되지 않지만, 프로덕션 환경에서 사용하기에는 이상적이지 않다. 

 

또한 데이터셋에 새로운 데이터가 업데이트될 때마다 수동으로 샤딩을 진행하는 것은 운영 비용이 클 뿐만 아니라 복잡도 또한 높아진다. 데이터 유실을 방지하기 위해 여러 개의 워커가 전부 백업되어야 하며, 데이터 마이그레이션 혹은 스키마 변경이 일어나는 경우 모든 샤드가 동일한 스키마 복사본을 유지하는 것 또한 보정되어야 한다. 

 

이러한 문제를 해결하기 위해 수동 샤딩 대신 알고리즘을 기반으로 하는 자동 샤딩을 사용할 수 있다. 예를 들어 해시 샤딩(hash sharding)은 데이터 샤드의 키값으로 해시를 생성한다. 생성된 해시값은 각 데이터가 속할 샤드를 결정한다. 균일한 해싱 알고리즘을 사용한다면 해시 함수가 데이터를 서로 다른 워커에 고르게 분산시킬 것이므로 위에서 언급한 문제를 줄일 수 있다. 또한 비슷한 데이터가 같은 샤드에 배치될 가능성도 낮아진다. 

 

샤딩 패턴은 매우 큰 데이터셋을 여러 데이터 샤드로 나누어 여러 워커에 분산시키고, 각 워커가 개별 데이터 샤드를 독립적으로 사용함으로써 성능을 크게 높인다. 이 방법을 활용하면 배치 처리가 순차적으로 모델을 학습시킴으로써 생기는 지연을 피할 수 있다. 배치와 샤딩 패턴은 전체 데이터셋을 모두 사용하면서 모델 학습 프로세스를 향상시킨다. 다만, 전체 데이터셋을 여러 번 사용해야 하는 머신러닝 알고리즘과 같은 경우에는 배치 및 샤딩을 두 번 이상 수행해야 한다.

 

p.66

트리 기반 알고리즘이나 딥러닝 같은 현대의 머신러닝 알고리즘은 대부분 여러 에포크에 걸친 학습이 필요하다. 1 에포크란 전체 데이터셋을 모두 사용하는 한 번의 주기를 의미한다. 즉, 데이터셋에 포함된 모든 데이터를 최소 한 번씩 전부 사용해서 학습을 진행하는 단위다. 

 

p.68~69

머신러닝 모델을 여러 에포크에 걸쳐 학습시키는 데 비현실적으로 많은 시간이 든다면 어떤 방법으로 개선할 수 있을까? 첫 번째 에포크는 말 그대로 머신러닝 모델이 전체 데이터셋을 처음 사용해서 학습하는 단계이기 때문에 할 수 있는 방법이 거의 없다. 하지만 두 번째라면 어떨까? 모델이 이미 데이터셋을 한 번은 사용했다는 점을 활용해 볼 수 있지 않을까?

 

모델 학습에 사용하는 노트북이 충분한 연산 자원과 메모리, 저장 공간을 가지고 있다고 가정해보자. 머신러닝 모델이 학습 데이터를 메모리에 올려서 사용했다면 나중에 학습할 때 디스크에서 메모리로 올리는 작업을 반복하는 대신 데이터를 메모리에 유지시키는 방법이 있다. 다른 말로 하면 학습 데이터를 캐싱(caching)해놓는 것이다. 데이터가 디스크 대신 메모리에 유지된다면 해당 데이터에 다시 접근하는 것은 훨씬 빨라진다. 

 

p.70~71

캐싱 패턴을 활용하면 모델 학습 과정에서 동일한 데이터셋을 반복적으로 가져오느라 낭비되는 시간을 크게 줄일 수 있다. 캐싱의 또 다른 장점은 머신러닝 파이프라인에서 예상치 못한 오류가 발생했을 때 캐시에 저장된 데이터를 재활용할 수도 있다는 점이다.

 

p.72

일반적으로, 보다 견고하고 안정성이 요구되는 시스템이 필요한 상황이라면 디스크 캐시를 사용하고, 속도나 시간 비용을 줄이는 것이 더 중요한 상황이라면 인메모리 캐시를 사용하는 편이 좋다. 특히 디스크 캐시는 원격 데이터베이스로부터 데이터를 가져와서 사용할 때 매우 유용하다. 네트워크 통신은 매우 느리고 때로는 불안정한 경우도 있기 때문이다. 

 

p.87

머신러닝 엔지니어 혹은 DevOps 엔지니어는 파라미터 서버 패턴을 구성할 때 파라미터 서버와 워커를 각각 몇 대씩, 혹은 어떤 비율로 구성할지 결정하는 데 어려움을 겪을 수 있다. 워커가 계산한 그레이디언트뿐만 아니라 파라미터 서버에 있는 최신 모델 파티션을 주고받는 것까지 고려한다면 워커와 파라미터 서버 간 발생하는 통신 비용은 적지 않다. 모델이 더욱 커서 파라미터 서버의 수가 더 늘어난다면 각 워커에서 실행되는 연산에 비해 통신 비용이 막대해지는 경우가 생길 수도 있다. 



댓글(0) 먼댓글(0) 좋아요(0)
좋아요
북마크하기찜하기 thankstoThanksTo
 
 
 
머니스톰 - 40년 만에 찾아온 부의 변곡점
김한진.송주연 지음 / 페이지2(page2) / 2024년 2월
평점 :
장바구니담기


 

 

통화주의 관점에서 경제 입문서라고 해도 좋을만한 책이다.

 

어찌보면 굉장히 보수적인 관점이라고 볼 수도 있겠지만, 그럼에도 불구하고 지금같은 인플레이션 시기에는 귀기울여 들어봐야 하는 관점이기도 하다. 물론 그렇다고 해서 통화주의가 무조건 답인건 아니겠지만 말이다.

 

거시경제에 대한 책이 늘 그렇듯, 책 전반부를 읽다보면 내 잘못도 아니고 파월 의장의 잘못이거나 누군가의 잘못인데 왜 저 멀리 살고 있는 나까지 피해를 봐야 하는가 라는 생각이 들기도 한다. 하지만 이런 상황을 바꿀 순 없다. 언제나 이런 거시경제적 상황은 통제할 수 없는 외생변수로 남아있을 것이기 때문이다. 

 

그렇기에 이런 책을 읽는 목적은 변하는 외생변수에 맞춰 내가 통제할 수 있는 변수를 통제하는 것. 비가 올 때 우산을 쓰고 담벼락 아래로 비를 피하듯, 상황을 이해하고 그에 맞게 행동할 수 있게 되는 것이다. 

 

그나저나 좋은 내용이지만, 읽더라도 비관적인 관점을 피하기는 그리 쉽지 않은 듯 하다. 

언제쯤 이 비가 그칠지 모르겠지만, 언젠가 겨울이 가고 봄이 오듯 조금 더 따뜻한 때가 오지 않을까 기대해본다.

 

 

 

p.38~41

연준이 인플레이션 파이터로 나섰을 때는 1960년대 베트남 전쟁과 1970년대 두 차례의 석유파동을 겪으면서 그야말로 미친 인플레이션이 찾아왔을 때였다. 바로 이 시기에 연준의 존재감이 급부상했다. 1961년 1%대에 머물렀던 미국의 기준금리는 1972년 초 3.3%를 거쳐 1981년에는 무려 20%까지 올랐다. 1970년대 끔찍한 하이퍼 인플레이션을 경험했던 탓인지 연준은 돈을 얼마든지 풀 수 있는 권한을 가졌음에도 불구하고 1980년대 내내 높은 금리를 유지하며 신중한 정책 스탠스를 견지했다.

 

물론 1980년대 중반까지 경제성장과 함께 통화량 자체는 꾸준히 늘었지만 국내총생산(GDP) 대비 총통화(M2)의 상대 비율은 여전히 50~60%대에 머물고 잇었는데, 이는 이 시기에 통화정책이 비교적 중립적이고 신중했음을 시사한다. 1987년부터 2000년까지는 미국경제가 매우 안정된 성장을 보인 국면이었는데 이 기간 중 연준의 기준금리는 세 차례나 인상됐고 GDP 대비 통화량은 계속 낮아졌다. 이후 닷컴버블이 붕괴되자 연준은 경기 부양을 위해 기준금리를 2003년 1% 까지 큰 폭으로 내렸다. 그 전에 금리를 올려놨기 때문에 내릴 수 있는 버퍼(완충장치)가 있었다. 하지만 이때까지만 해도 연준은 물가 안정에 초점을 두며 신중한 통화정책을 펼쳤다.

 

문제는 그다음 2008년 글로벌 금융위기 이후부터였다. 연준은 위기를 수습하기 위해 재빨리 금리를 내리는 동시에 시중에 유동성을 과감히 공급했다. 2008년 말부터 2010년 초까지 늘어난 미국의 총통화는 약 1조 2,000억 달러였는데 1913년부터 2008년까지 약 100년간 증가한 총통화가 1조 달러였으니 이보다 더 많은 통화가 불과 1년 3개월 만에 풀린 셈이다. 1년 남짓한 이 기간 중 미국의 본원통화는 2배나 늘었고 이렇게 한번 고삐 풀린 통화는 그 이후에도 쭉쭉 늘어났다. 연준의 행보에 뭔가 큰 변화가 생긴 시기였다. 

 

그런데 특이한 점이 있다. 연준은 달러를 새로 찍어 특별히 지정한 24곳의 거대 은행 금고에 넣는 방식으로 통화를 풀었는데 은행 시스템이 보유한 초과 지급준비금이 2008년 금융위기 전 20억 달러에서 2010년 2월에는 약 1조 2,000억 달러로 600배나 증가했다. 은행 시스템에 천지개벽이 일어난 것이다. 은행에 쌓여 있는 초과 지급준비금은 장기간 초저금리(일부 다른 국가는 마이너스 기준금리)와 만나 시중 통화량 증가로 이어졌을 뿐만 아니라, 다양한 인플레 요인들과 만나며 물가를 자극해왔다. 넓게 보면 연준이 통화를 광적으로 푼 시기는 2000년 닷컴버블 붕괴 이후 최근까지 약 20여 년간으로 볼 수 있는데 그렇게 쌓여온 통화량은 경제와 자산시장 전반에 상당한 영향을 주고 있는 것으로 추정된다.

 

이렇게 미국의 총통화는 2000년 초 4조 6,000억 달러에서 꾸준히 늘어나 2022년 말에는 21조 달러를 넘어섰다. 세계경제와 금융의 중심지인 미국에서만 지난 20여 년간 달러가 약 5배 풀린 것이다. 문제는 지난 20년간 늘어난 총통화의 무려 3분의 1이 2020년 팬데믹 이후 3년도 채 안 된 시기에 증가했다는 점이다. 

 

이런 현상은 미국에만 국한된 얘기가 아니다. 유로존도 2000년 60.7%에 불과하던 GDP 대비 총통화 비율이 2008년 초까지는 82.3%로 높아졌고 이후 코로나 대유행을 거치면서 2021년 5월에는 123.1%까지 치솟았다. 

 

p.53

일본중앙은행(BOJ)은 2011년 동일본 대지진 등으로 경제가 어려움에 빠지자 2013년 1월부터 매월 13조 엔 규모의 국채 매입을 실시하고 물가 상승률 목표치 2%로 상향 조정하는 양적완화 정책을 강화했다. 아베노믹스와 함께 시작된 YCC정책(수익률곡선 제어정책)은 중앙은행이 장기 금리 목표를 달성하기 위해 채권을 매수 또는 매도하는 정책을 말한다. 코로나19 회복 과정에서 물가가 급등하자 미국 등 주요 중앙은행은 금리를 인상했으나, 일본은행은 여전히 완화적 통화정책을 유지하고 있다. 다른 국가보다 낮은 인플레이션으로 여전히 경기 부양의 필요성을 안고 있기 때문이다. 그러나 미국과의 금리 격차가 커지면서 엔화의 평가절하 압력이 확대되자 일본은행은 2022년 12월 국채금리 변동폭을 기존 +/- 0.25% 정도에서 +/- 0.5% 정도로 확대했다. 이후 2023년 7월, BOJ는 금리 변동폭 상한선을 0.5%로 유지하되 어느 정도 초과 변동을 용인하겠다고 밝혔다. 시장은 이를 BOJ가 장기금리 상승을 일부 허용하고 YCC 출구전략을 밟기 시작했다는 신호로 받아들이고 있다. 

 

p.57

생산성 저하 이면에 좀비기업이 있었다는 연구 결과가 많다. 국제결제은행(BIS)의 통화경제국장 보리오(Borio)는 저금리가 투자 부진과 생산성 저하로 이어진다는 사실을 규명하면서 좀비기업 점유율과 정책 금리 하락 사이의 밀접한 상관관계를 발견했다. 즉, 저금리는 좀비를 낳고 좀비는 저금리를 낳는다는 것이다. (출처 : [금리의 역습], 에드워드 챈슬러, 임상훈 옮김)




댓글(0) 먼댓글(0) 좋아요(0)
좋아요
북마크하기찜하기 thankstoThanksTo