brunch

You can make anything
by writing

C.S.Lewis

by being cognitive May 27. 2024

Andrej Karpathy의 Tokenizer 강의

'24.2월

Andrej Karpathy가 Tokenizer 강의를 올렸습니다.

강의 링크 : https://www.youtube.com/watch?v=zduSFxRajkE


재미있는 내용이 가득해서 몇번이고 돌려보면서 최대한 이해해봤습니다.


금방 까먹을 저를 위한 노트인데, 혹시라도 여기 계신 다른 분들께서 영상을 보실 때 참고가 될 수 있을까 싶어서 공유해봅니다.


[ 잡담 ]


. 우선, (보기 시작한 김에 작년에 올렸던 Build GPT from Scratch도 보니까), 일단, Andrej Karpathy도 Github Copilot을 사용하고 있습니다... 탑클래스 과학자가 코딩할 때 Copilot과 함께 생산성을 이미 극대화하고 있었네요. 업무에서 AI를 사용하는 사람과 하지 않는 사람의 격차가 이미 엄청나게 벌어지고 있다는 것을 새삼 느꼈습니다.


. 한국을 좋아한다고 들었는데, 이번 강의에서도 '만나서 반갑습니다.'를 봐서 더욱 반가웠습니다.


. 아마도 지구에서 가장 뛰어난 Tokenizer강의일 것입니다. (매우 옛날 사람같은 표현이지만, 옛날 사람이니까...) 이런 내용을 바다건너편에서 실시간으로 학습할 수 있다니, 정말 놀라운 세상입니다...


. 영어를 차근차근 말하는구나...라면서 작년 Lex Friedman 팟캐스트에 출연한 영상까지 클릭했습니다. 음, 강의할 때만 말이 느리고, 평소에는 말이 엄청 빠른 사람이었습니다.


. Andrej Karpathy는 Swifties (테일러 스위프트 팬클럽)은 아니지만, 테일러 스위프트가 쿨하다고 생각하기는 합니다.



[ 강의 노트 ]


. 현재 LLM이 겪고 있는 문제의 대부분은 Tokenizer때문이다.

  e.g. LLM이 스펠링에 취약하고, 문자를 거꾸로 뒤집는 간단한 작업을 못하는 이유? Tokenization때문

  e.g. LLM이 왜 비영어권 언어에 약한가? Tokenization때문

  e.g. LLM은 왜 간단한 산수를 못할까? Tokenization때문...

  ...


. Tokenization단위로 Unicode를 직접 매칭해서 쓰는 것도 가능하긴 하겠으나,

  현재 약 15만개의 문자를 표현할 수 있어서 vocab_size가 큰 것도 하나의 문제인데,

  Unicode는 가변적이기 때문에, 이것이 활용을 가로막는 보다 근본적인 이유임.


  예시 : print([ord(x) for x in "안녕하세요

 (hello in Korean!)"])

  [50504, 45397, 54616, 49464, 50836, 32, 128075, 32, 40, 104, 101, 108, 108, 111, 32, 105, 110, 32, 75, 111, 114, 101, 97, 110, 33, 41]


. Tokenizer는 (여러가지 이유로 ^^;) utf-8로 인코딩된 RAW BYTE를 사용하는 선택을 하게 되었고,

  이 RAW BYTE가 LLM의 원자ATOM에 해당한다고 볼 수 있다...!


  예시 : print(list("안녕하세요

 (hello in Korean)".encode("utf-8")))

  [236, 149, 136, 235, 133, 149, 237, 149, 152, 236, 132, 184, 236, 154, 148, 32, 240, 159, 145, 139, 32, 40, 104, 101, 108, 108, 111, 32, 105, 110, 32, 75, 111, 114, 101, 97, 110, 41]


. (최근에 Gemini Pro에서 Context길이를 1백만개 수준으로 높이긴 했지만) LLM에게 전달하는 input의 context 길이는 제약이 있을 수 밖에 없음.

  만약, input을 저 최소단위인 BYTE들을 그대로 입력하게 되면 context길이가 필요 이상으로 길어질 것. 따라서, 반복적으로 나타나는 것들을 묶어서 vocab으로 만들어서 sub-word화한 것이 token이고,

  Byte 들이 반복적으로 나타나는 Pair를 묶는 알고리즘이 바로 BPE (Byte Pair Encoding)임.

  (구현 예제 같이 따라가면 재미있습니다.)


. '적정한' vocab_size는 경험적으로 결정되는 값으로, OpenAI에서는 약 10만개의 token을 사용한다고 합니다.

  (vocab_size가 너무 작으면 input의 context 길이가 너무 길어져서 품질이 저하되고, vocab_size가 너무 크면 LLM이 충분히 단계적으로 생각하지 못하게 되어 품질 저하됨...)


. dog. dog, dog! 과 같은 표현이 자주 나오게 되면 BPE알고리즘에서 dog. dog, dog!를 punctuation포함해서 통째로 하나의 토큰으로 만들어버리는 경우가 생길 수 있다고 합니다. 이렇게 되면 실제로 LLM에서 punctuation으로 문장 단위를 이해하는데 혼란이 생길 수 있겠죠. 따라서, punctuation이나 's, 've와 같은 강제로 구분해야 하는 표현 들은 미리 정규식으로 구분해놓음으로써 BPE로 합쳐지지 않도록 합니다.


. pip install tiktoken <- OpenAI의 inference용 tokenizer임.


. gpt-2 token 길이를 세어보면, 50257개임.

  256개의 raw byte tokens + 50,000회의 BPE merge + "1 Special Token"

  Special Token은 <|endoftext|>임.


  텍스트가 끝났고, 학습을 새로 시작하자는 의미에 해당하는 Special Character인데, 이 또한 저 문구를 그대로 input으로 넣으면 ChatGPT가 잘 이해하지 못하는 또다른 특이한 현상이 있음. (이미지 참고)


. tiktoken은 명시적으로 training과 inference단계가 구분되어있음. 이에 반해, SentencePiece는 training과 inference를 동시에 시행하기 때문에 현업에서 보다 많이 사용되고 있음.

  Andrej Karpathy는 SentencePiece에서 historical baggage가 너무 많아서 이해하기가 어려운 점, 다큐멘테이션이 취약한 점 등이 마음에 들지 않는다고 함.

  따라서 Andrej Karpathy는 minbpe라는 프로젝트에 착수했고, 이것이 SentencePiece의 training과 inference를 동시에 할 수 있는 장점을 가져가면서 위에 언급한 단점을 극복하기를 기대하고 있음.


. LLM에서 token - transformer의 아키텍처는, 멀티모달에서 인풋만 바꿔주고 그대로 유지됨. 최근 Sora문서에서 나타난 것과 같이 token을 영상 patch가 대신하는 방식.


. SolidGoldMagiKarp 와 같은 특이한 단어를 언급하면 LLM이 갑자기 욕을 하는 등의 특이한 현상이 리포트됨. 알고보니, 위 단어는 tokenizer의 학습단계에서 사용된 Reddit문서에 들어있는 유저의 이름에 해당했음. 하지만, 토크나이저 학습과 LLM학습 단계가 명시적으로 나눠져있기 때문에, LLM학습단계에서는 SolidGoldMagiKarp라는 단어를 한번도 학습한 적이 없을 것. 따라서, 이는 vocab에는 존재하는데 embedding값이 초기에 설정된 random값들이 그대로 있어서, 욕설 등의 특이 행동을 하는 원인으로 판단. (그래서, 또크나이저가 또...)


<|endoftext|>를 읽을 수 없는 ChatGPT


작가의 이전글 WoShi.AI ('23.12월)
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari