Next-token prediction: embedding과 perplexity의 의미
32,033개 이름으로 문자 모델을 학습하고 gradient descent가 count table을 재발견하는 과정, 그리고 perplexity가 잘 맞지 않는 이유.
이 페이지에서
아래는 단어를 한 번도 본 적 없는 프로그램이 만들어 낸 이름 열 개입니다:
cexze momakurailezitynn konimittain llayn ka
da moliellavo emia sade ftlsp그중 어느 것도 이름은 아닙니다. 하지만 거의 모두가 시도하고 있습니다. 발음할 수 있고, 이름이 끝나는 자리에서 끝나며, 그중 하나인 emia은 실제 이름에서 글자 하나만 다릅니다. 이것들을 만든 프로그램은 729개의 숫자를 담고 있고, 단어도 음절도 사람도 알지 못하며, 인접한 글자 쌍을 한 번 세는 것만으로 맞춰졌습니다.
이 장이 끝날 때쯤 neural network는 같은 측정값에서 그 프로그램의 점수를 3분의 1 줄일 것입니다. 끝까지 볼 만한 부분은 network가 처음 하는 일입니다. 아무 지시도 받지 않았는데, 두 객체가 같은 질문의 답이기 때문에 잘 채워진 모든 행에서 count table을 소수 셋째 자리까지 재현합니다. 그 이후의 모든 것이 count로는 절대 할 수 없었던 일입니다.
Objective는 설계 선택이 아니라 항등식입니다
섹션 링크: Objective는 설계 선택이 아니라 항등식입니다7장은 정수의 sequence와, 왜 하나가 다른 하나 뒤에 와야 하는지에 대한 이유 없이 끝났습니다. 그 이유가 여기 있고, 2장의 한 줄입니다.
Language model은 지금까지의 token을 받아 다음에 올 token에 대한 distribution을 반환하는 함수입니다. vocabulary 항목마다 하나의 숫자, 음수가 아니며, 모두 더하면 1입니다. 그게 전부입니다. 여기서 전체 문서의 probability로 가려면 probability의 chain rule을 적용하면 됩니다:
이것은 항등식입니다. 무엇으로 이루어진 sequence든 참이고, 어떤 가정도 붙어 있지 않습니다. 따라서 작은 일, 즉 이전 token이 주어졌을 때 next token을 구하는 일을 하는 model은 이미 모든 가능한 문서에 probability를 부여하는 큰 일을 정확하고 공짜로 끝낸 것입니다. 이를 싸구려 요령처럼 말하는 흔한 프레이밍, 즉 “그저 다음 단어를 예측할 뿐”이라는 말은 논리를 거꾸로 이해한 것입니다. next token을 예측하는 것 자체가 joint distribution을 모델링하는 일입니다. 해야 할 두 번째 일은 애초에 없었습니다.
Loss도 똑같이 기계적으로 따라옵니다. 각 위치에서 model은 distribution 를 내고, 정답은 하나의 알려진 token이므로 4장의 cross-entropy가 그대로 적용됩니다:
이것은 평균 negative log-likelihood입니다. Gaussian이 들어가 있던 자리에 categorical distribution이 들어간 2장의 레시피입니다. 그리고 true distribution은 one-hot이므로 entropy가 0입니다. 따라서 4장의 항등식에 의해 cross-entropy는 KL divergence와 같습니다. 이 숫자를 낮추는 것과 model의 믿음을 데이터 쪽으로 끌어당기는 것은 같은 행위입니다.
한 가지 결과는 따로 한 문장으로 둘 가치가 있습니다. 이 분야 전체 밑에 깔린 경제적 사실이기 때문입니다. 라벨은 데이터를 한 칸 민 것입니다. 아무도 아무것도 annotate하지 않습니다. 1조 개 token의 텍스트는 이미 라벨이 붙은 1조 개의 예제입니다. 그래서 현대 model의 training corpus는 “누군가 만든 dataset”이 아니라 “인터넷”입니다.
정직한 baseline: 세기
섹션 링크: 정직한 baseline: 세기어떤 network보다 먼저 baseline입니다. 32,033개의 이름, 한 줄에 하나씩, 그리고 한 글자씩 더 많은 이름을 만들어 내는 일입니다.1
Vocabulary는 26개 글자와 이름의 시작과 끝을 모두 표시하는 boundary symbol . 하나로 이루어져 있습니다. 따라서 model은 이름이 어디서 시작하고 어디서 멈추는지 배워야 합니다. 총 27개 symbol이고, 가능한 가장 작은 model은 각 symbol 뒤에 다른 각 symbol이 얼마나 자주 왔는지 적은 table입니다.
N = torch.zeros((27, 27), dtype=torch.int32)
for w in words:
cs = ["."] + list(w) + ["."]
for a, b in zip(cs, cs[1:]):
N[stoi[a], stoi[b]] += 1
P = N.float()
P = P / P.sum(1, keepdim=True) # one distribution per row 산술 두 줄이면 model이 fitted됩니다. 그리고 이것은 heuristic이 아닙니다. count를 row total로 나누는 것은 categorical distribution에 대한 maximum-likelihood estimate이며, 미분 계산이 이미 끝난 2장의 레시피입니다.
names: 32033 train/val/test: 25626 / 3203 / 3204
training bigrams: 182583
the six most likely letters after 'a':
a -> '.' 0.1944 a -> 'n' 0.1600 a -> 'r' 0.0967
a -> 'l' 0.0749 a -> 'h' 0.0690 a -> 'y' 0.0606여기서 sample합니다. 현재 글자의 row에서 글자 하나를 고르고, 그 row로 이동하고, boundary symbol이 나올 때까지 반복합니다. 그러면 이 장 맨 위의 이름들이 나옵니다. 그것들은 구체적이고 유익한 방식으로 실패합니다. local하게는 그럴듯하지만 global하게는 말이 안 됩니다. momakurailezitynn의 모든 인접 글자 쌍은 실제 이름에 등장하는 쌍입니다. 다만 그런 쌍이 열일곱 개나 연속으로 있을 뿐입니다. Model에는 글자 하나만큼의 memory밖에 없으므로 자신이 너무 오래 이어지고 있다는 사실을 알 수 없습니다.
Perplexity, 그리고 읽는 법
섹션 링크: Perplexity, 그리고 읽는 법Held-out 이름에서의 loss는 2.4546 nats입니다. 이 숫자는 그 자체로는 아무 의미가 없고, 그래서 perplexity가 존재합니다:
Library가 대신 해 주지 않는 형태로 풀어 쓰면:
@torch.no_grad()
def perplexity(logits, Y):
logp = F.log_softmax(logits, dim=1) # log q for every symbol
chosen = logp[torch.arange(len(Y)), Y] # log q of the one that came next
return torch.exp(-chosen.mean()) Exponentiating은 logarithm을 되돌리고 숫자를 무언가를 세는 단위로 돌려놓습니다. 무엇을 세는지 보는 가장 깔끔한 방법은 아무것도 모르는 model을 측정하는 것입니다. 즉 context와 무관하게 모든 symbol에 probability 를 할당하는 model입니다:
uniform over 27 symbols loss 3.2958 nats ppl 27.000
bigram counts, add-one smoothed loss 2.4546 nats ppl 11.642정확히 27.000입니다. 왜냐하면 이기 때문입니다. Perplexity는 model이 고르고 있는 동등하게 가능해 보이는 선택지의 유효 개수입니다. Perplexity 27은 “전혀 모르겠다, 무엇이든 될 수 있다”는 뜻입니다. Count model의 11.642는 글자 하나의 context가 불확실성을 27개가 아니라 대략 12개 선택지에서 blind하게 고르는 사람 수준으로 줄였다는 뜻입니다. 그래서 raw loss가 아니라 perplexity가 인용됩니다.
두 가지 문제가 생깁니다. 그리고 두 번째 문제는 출판된 논문에서도 생깁니다.
Zero probability는 치명적입니다. Table의 729개 cell 중 113개는 training에서 한 번도 나오지 않습니다. 15.5 %가 비어 있는 셈입니다. Held-out set이 그 안에 들어가기 전까지는 괜찮습니다. 그런데 validation에서는 일곱 개 bigram이 그렇게 됩니다. 그중에는 d→q, z→j, 그리고 두 번 나온 q→o도 있습니다. Probability 0은 log 을 뜻하고, 이는 infinite loss와 infinite perplexity를 뜻합니다. 이름 3천 개 중 하나가 metric을 망가뜨립니다. 흔한 patch는 normalising하기 전에 모든 count에 1을 더하는 것이고, 여기서는 비용이 거의 없습니다. 2.4524 대신 2.4546입니다. 하지만 이 patch는 고백입니다. Count model은 전혀 generalise할 수 없습니다. q→u가 흔하고 o가 다른 곳에서 u처럼 행동하므로 q→o도 그럴듯하다고 추측할 방법이 없습니다. 두 symbol이 서로 닮을 수 있다는 개념이 없기 때문입니다. 모든 cell은 따로 학습되고, 이것을 고치는 것이 이 장 나머지의 목적입니다.
Perplexity는 token당 가격이고, token은 자유 parameter입니다. Model을 비교할 때 끊임없이 나타나는 실수이고, 들여다보면 쉽게 보입니다. 7장의 같은 영어 산문 corpus, 같은 interpolated bigram model을 두고, 텍스트를 자르는 방식만 바꿔 봅니다:
| 단위 | vocabulary | test의 tokens | cross-entropy | perplexity | bits per character |
|---|---|---|---|---|---|
| characters | 76 | 14,469 | 2.5217 | 12.45 | 3.6378 |
| BPE, 512 merges | 329 | 6,871 | 3.8547 | 47.21 | 2.6407 |
| BPE, 2,048 merges | 1,820 | 4,233 | 5.7468 | 313.20 | 2.4254 |
| words | 2,991 | 6,284 | 3.5627 | 35.26 | 2.2322 |
Perplexity는 이 행들 사이에서 25배나 달라집니다. Model에 대해서는 아무것도 바뀌지 않았습니다. 예측되는 대상의 크기만 바뀌었습니다. 전체 단어를 예측하는 것은 글자 하나를 예측하는 것보다 어렵기 때문에 prediction당 비용이 더 듭니다. 그리고 해야 할 prediction의 수는 더 적습니다.
이제 마지막 열을 읽어 보세요. 이 열은 total cost를 characters 수로 나누고 bits로 변환합니다. Table의 순서가 바뀝니다. Perplexity 기준 ranking은 characters, words, BPE-512, BPE-2048입니다. Bits per character 기준으로는 words, BPE-2048, BPE-512, characters입니다. Character model은 1위에서 꼴찌가 됩니다. Perplexity로 보면 512-merge model보다 6.6배 나빠 보이는 2,048-merge model은 실제로는 2.6407에 맞서 2.4254 bits로 둘 중 더 좋습니다.
따라서 perplexity는 같은 tokenizer를 공유하는 두 model 사이에서만 비교할 수 있습니다. 서로 다른 tokenizer를 가진 model은 bits per character로만 비교할 수 있습니다. 이는 Shannon이 1951년에 사람들에게 영어 텍스트의 다음 글자를 맞히게 하며 측정한 양이고, 대략 character당 1 bit로 경계가 잡혔습니다.2 우리의 최고 bigram은 2.23 bits에 있고, 이는 이 장이 아직 얼마나 더 가야 하는지를 잘 요약합니다.
같은 것, 학습으로 얻기
섹션 링크: 같은 것, 학습으로 얻기이제 같은 model을 network로 만들어 봅니다. 같은 곳에 도달하는 데 훨씬 더 많은 산술이 필요할 것이고, 같은 곳에 도달한다는 사실이 핵심입니다.
Table을 shape 인 하나의 weight matrix 로 바꿉니다. 현재 글자를 one-hot vector로 만들고, 곱한 뒤, 결과를 logits라고 부릅니다. 4장의 unnormalised scores입니다. 그런 다음 softmax, cross-entropy, gradient descent입니다.
W = torch.randn((27, 27), requires_grad=True)
for step in range(3000):
logits = W[xs]
loss = F.cross_entropy(logits, ys)
W.grad = None
loss.backward()
W.data -= 50.0 * W.grad강조된 줄에는 알아둘 만한 정의가 들어 있습니다. One-hot vector에 matrix를 곱하면 그 matrix의 한 row가 선택되므로, 이 곱셈은 lookup입니다. 모든 implementation은 산술을 건너뛰고 lookup을 직접 수행하며, 그것이 W[xs]입니다.
그것이 embedding table입니다. Vocabulary entry마다 한 row가 있고, token id로 indexed되는 matrix입니다. Geometry도, semantics도, 별도의 algorithm도 아닙니다. 내용물이 다른 모든 것과 함께 gradient descent로 학습될 뿐인 lookup table입니다. “embedding space”에 대한 모든 신비로운 주장은 여기에서 바닥을 드러냅니다.
Train한 뒤 어디로 가는지 봅니다:
step 1 train 3.7550 val 3.3882 max gap to the count table 0.757269
step 100 train 2.4732 val 2.4726 max gap to the count table 0.388354
step 1000 train 2.4557 val 2.4549 max gap to the count table 0.041862
step 3000 train 2.4547 val 2.4544 max gap to the count table 0.004048마지막 열은 softmax(W)의 어떤 cell과 count table의 대응 cell 사이의 가장 큰 absolute difference이고, 0으로 갑니다. 3,000 step 뒤 729개 cell 어디에서도 가장 큰 불일치는 0.004048이고 평균은 0.000224입니다. 최악의 cell은 전체 training set에서 열두 번 나온 q→i입니다. 1,000번 넘게 등장한 22개 row 중 최악의 불일치는 0.000562입니다.
count table network
a -> '.' 0.1945 0.1945
a -> 'n' 0.1601 0.1601
a -> 'r' 0.0967 0.0967Random number에서 시작해 “next letter의 log-probability를 크게 만들어라”라는 말만 들은 gradient descent가 count table을 재발견했습니다. 그럴 수밖에 없었습니다. Count는 maximum-likelihood estimate이고, cross-entropy는 negative log-likelihood이므로, 두 절차는 같은 objective를 optimise하며 그 objective에는 하나의 optimum이 있습니다. Network는 counting과 비슷한 것을 배운 것이 아닙니다. 천천히 counting으로 converged한 것입니다.
그러면 왜 누군가 굳이 이 일을 하겠느냐는 정당한 질문이 생깁니다. Count table은 여기서 더 갈 곳이 없지만, network는 갈 곳이 있기 때문입니다.
Context가 bottleneck이지 capacity가 아닙니다
섹션 링크: Context가 bottleneck이지 capacity가 아닙니다Model을 확장해 이전 character 하나보다 더 많이 보게 합니다. 이것은 Bengio의 2003년 architecture이며, 이 course 나머지 모든 model의 직계 조상입니다.4 마지막 세 character를 가져와 각각을 embedding table을 통해 10-dimensional row로 mapping하고, row들을 concatenate해 30개의 숫자로 만든 뒤, 5장의 hidden layer에 넣고, vocabulary entry마다 하나의 logit을 내는 output layer로 끝냅니다.
C = torch.randn((27, 10)) # the embedding table
W1 = torch.randn((3 * 10, 200)) # the hidden layer from Chapter 5
W2 = torch.randn((200, 27)) # one output per vocabulary entry
emb = C[X].view(-1, 30) # three lookups, concatenated
h = torch.tanh(emb @ W1 + b1)
logits = h @ W2 + b2
loss = F.cross_entropy(logits, Y)무엇이 새롭고 무엇이 아닌지 주목하세요. Hidden layer는 5장의 것 그대로입니다. Loss는 4장의 것 그대로입니다. 새로움은 앞쪽의 embedding table과 7장의 vocabulary만큼 넓은 output layer입니다. 그리고 두 번째 것이 지금까지 만들어진 모든 language model에서 비싼 부분입니다. 실제 vocabulary에는 100,000개 entry가 있고, 이 matrix multiply는 모든 position에서 실행되기 때문입니다.
같은 code를 동일하게 train하고, context window의 크기만 바꿉니다:
| context | parameters | validation loss | validation perplexity |
|---|---|---|---|
| counting, 1 character | 729 | 2.4546 | 11.642 |
| neural, 1 character | 7,897 | 2.4577 | 11.678 |
| neural, 3 characters | 11,897 | 2.1145 | 8.285 |
| neural, 8 characters | 21,897 | 2.0506 | 7.773 |
흥미로운 것은 두 번째 row입니다. 200-unit hidden layer와 count table보다 11배 많은 parameter를 가진 network가 count table과 정확히 같은 성능을 내고, 더 낫지는 않습니다. Capacity는 애초에 제한이 아니었습니다. Character 하나의 context는 특정 loss까지만 허용하며, 무엇을 덧붙여도 그 아래로 내려갈 수 없습니다. 정보가 거기에 없기 때문입니다.
세 character를 주면 perplexity는 11.68에서 8.29로 떨어집니다. 4,000개의 추가 parameter로 산 29 % 감소입니다. 여기서 counting을 이기는 이유는 앞서 진단한 바로 그것입니다. 세-character context에 대한 count model은 개의 row가 필요하고, 대부분은 비어 있거나 단 하나의 observation만 담습니다. 그리고 각각을 따로 배웁니다. Network는 공유합니다. a, e, i가 비슷한 embedding row를 갖게 되면, bra 뒤에서 배운 것이 bre로 transfer됩니다. bre를 한 번도 본 적이 없어도 그렇습니다. 이 transfer가 embedding table의 전부인 가치이고, row 2와 row 3 사이의 gap입니다.
Sample도 그에 맞게 좋아집니다:
deliah nellara joce kael quintis
salayson reety khyrmin mahnen madiaryxia아직 실제 이름 목록은 아닙니다. 하지만 deliah, nellara, kael는 목록에 있어도 어색하지 않을 것입니다. 그리고 끝없이 이어지는 괴물들은 사라졌습니다. Count model의 20개 sample 중 가장 긴 것은 19글자였고, 이 model의 20개 중 가장 긴 것은 13글자입니다.
Embedding table 안에는 실제로 무엇이 있나
섹션 링크: Embedding table 안에는 실제로 무엇이 있나Table은 입니다. Character마다 열 개 숫자의 row 하나가 있고, 모두 random하게 initialised되며 next-character loss의 gradient에 의해서만 움직였습니다. 아무도 거기에 무엇을 넣지 않았습니다. 그렇다면 무엇이 들어갔을까요?
질문하는 도구는 cosine similarity입니다. 이는 1장의 dot product에서 길이를 나눈 것입니다:
두 vector 사이의 angle을 측정하고 length는 무시합니다. Row의 length가 그 token이 얼마나 자주 나타났는지를 반영할 때, 의미가 무엇인지가 아니라, 원하는 것이 바로 이것입니다. 먼저 모든 vector를 length 1로 normalise합니다. 실제 system이 indexing 시점에 한 번 그렇게 합니다. 그러면 cosine similarity는 단순히 dot product입니다.
학습된 table에서 몇몇 character의 nearest neighbours는 다음과 같습니다:
'c' -> 'k':+0.598 'j' -> 'z':+0.650 'i' -> 'y':+0.541
'u' -> 'e':+0.482 'a' -> 'h':+0.367 '.' -> 'q':+0.077그중 일부는 민간전승이 약속하는 바로 그것입니다. 이름에서 c와 k는 서로 바꿔 쓸 수 있고, i와 y도 그렇습니다. j와 z는 둘 다 드물고, 대부분 initial에 오는 consonant이며, 비슷하게 행동합니다. Boundary symbol .는 아무것과도 가깝지 않습니다. 가장 가까운 letter와도 0.077입니다. 소리가 아니라 position을 표시하는 유일한 symbol이기 때문입니다.
그리고 일부는 그렇지 않습니다. a의 nearest neighbour는 다른 vowel이 아니라 **h**입니다. 모든 pair에 대해 평균을 내면:
mean cosine, vowel to vowel : +0.1889
mean cosine, consonant to consonant : +0.0765
mean cosine, vowel to consonant : -0.0042Vowel들은 consonant보다 서로를 더 닮았고, 그 효과는 실제이지만 작습니다. 무작위로 고른 2,000개의 다섯 글자 group에 대해 test하면, 그중 58개 group이 적어도 그만큼 깔끔하게 분리됩니다. 약 수준에서 significant한 gap입니다. 그러니 실제입니다. 하지만 embedding에 대한 대중적 설명이 암시하는 선명한 geometric island 같은 것은 전혀 아닙니다.
이것이 embedding table에 대한 정직한 설명이고, course의 나머지 동안 붙들고 있을 가치가 있습니다. 이것은 의미의 map이 아닙니다. 설계된 것이 아니라 학습된 coordinate change이며, 유일한 일은 다음 layer의 일을 쉽게 만드는 것입니다. Chapter 5가 XOR을 풀기 위해 plane을 접은 hidden layer에 대해 썼던 바로 그 문장입니다. 그 안에서 발견되는 structure는 loss를 낮췄기 때문에 존재합니다. Loss를 낮추지 않는 structure는 그냥 없습니다.
word2vec, GloVe, 그리고 모두가 인용하는 산술
섹션 링크: word2vec, GloVe, 그리고 모두가 인용하는 산술유용한 부분이 table이라면, 그것을 직접 노릴 수 있습니다. 그것이 word2vec입니다. Embedding lookup은 남기고, language model은 버립니다.5
Skip-gram with negative sampling objective는 한 줄입니다. Corpus에서 뽑은 실제 (centre, context) pair에 대해서는 dot product를 올리고, noise distribution에서 뽑은 개의 fake pair에 대해서는 낮춥니다:6
이것은 binary classification입니다. “이 두 단어가 정말 함께 등장했는가?” 그리고 full vocabulary를 전혀 건드리지 않기 때문에 저렴합니다. 이것이 2013년에 수십억 단어로 training을 practical하게 만든 이유입니다. GloVe는 반대 방향에서 비슷한 vector에 도달합니다. Example을 stream하는 대신 global co-occurrence count matrix를 factorise합니다.7 둘 다 count table이 만들어진 바로 그 statistic에 fitted됩니다. 압축된 counting입니다.
text8에서 train하면, 즉 English Wikipedia의 17,005,207개 word, 그중 적어도 다섯 번 등장한 71,290개, 100 dimensions, 세 pass로 train하면, vector는 자신들을 유명하게 만든 property를 갖고 나옵니다:
king -> charles 0.700, son 0.693, queen 0.686, henry 0.669, throne 0.667
physics -> chemistry 0.672, electromagnetism 0.661, quantum 0.654, theoretical 0.624
guitar -> bass 0.733, vocals 0.732, acoustic 0.728, guitars 0.703, drums 0.685
three -> seven 0.892, two 0.877, one 0.875, five 0.871, four 0.870아무도 instrument나 numeral이라는 category를 제공하지 않았습니다. 이제 유명한 부분입니다. king를 가져와 man를 빼고 woman를 더한 뒤, 결과에 가장 가까운 vector를 찾습니다.
king - man + woman
nothing excluded : king 0.693, elizabeth 0.657, wife 0.629, woman 0.607
a, b, c excluded : elizabeth 0.657, wife 0.629, mary 0.607 (queen is 4th, 0.604)king - man + woman에 가장 가까운 vector는 **king**입니다. 이것은 한 예제의 우연이 아닙니다. Mikolov의 evaluation set은 a : b :: c : ? 형태의 질문을 냅니다. 8,869개 semantic 질문(paris : france :: rome : italy)과 10,675개 syntactic 질문(walking : walked :: swimming : swam)입니다. 이 vocabulary가 답할 수 있는 4,103개 semantic 질문 전체에서, winner는 세 input word 중 하나인 경우가 **99.8 %**입니다. Published demonstration은 이것을 언급하지 않습니다. Standard scoring rule이 보기 전에 a, b, c를 삭제하기 때문입니다. 합법적인 rule이고, 그 rule은 산술보다 더 많은 일을 하고 있습니다:
| 답을 고르는 방식 | semantic | syntactic |
|---|---|---|
| offset, input 제외(standard) | 17.0 % | 11.9 % |
| offset, 아무것도 제외하지 않음 | 0.1 % | 0.4 % |
c만의 nearest neighbour, input 제외 | 13.1 % | 9.3 % |
b만의 nearest neighbour, input 제외 | 2.3 % | 0.4 % |
세 번째 row를 곱씹어야 합니다. a와 b를 버리고, 아무 산술도 하지 않고, c에 가장 가까운 것을 반환하면 semantic score의 77 %를 유지합니다. Analogical reasoning처럼 보이는 것의 대부분은 proximity와 obvious answer를 금지하는 rule의 조합입니다. 이는 Linzen이 properly trained vectors에서 측정한 것이고 위 baseline이 재현하는 것입니다.8 이 particular vector들은 작습니다. Published model 뒤에 있는 수십억 단어가 아니라 1,700만 단어입니다. 그러니 percentage는 state of the art가 아니라 shape로 읽으세요. 그 shape는 모든 scale에서 살아남습니다. Arithmetic은 실제이지만, 모두가 인용하는 그 하나의 demonstration보다 훨씬 약합니다.
Static과 contextual: word마다 vector 하나, 또는 occurrence마다 하나
섹션 링크: Static과 contextual: word마다 vector 하나, 또는 occurrence마다 하나지금까지의 모든 것에는 data structure에 내장된 단단한 한계가 있습니다. Table은 token마다 row 하나를 갖습니다. bank라는 단어는 vector 하나를 얻습니다. 강에 대한 문장에서도, mortgage에 대한 문장에서도 같은 vector입니다. ID lookup은 다른 어떤 것에도 의존할 수 없기 때문에 필연적입니다.
해결책은 table에서 vector를 읽어 오는 일을 멈추고, sentence에서 그것을 계산하기 시작하는 것입니다. 이것이 contextual embedding입니다. 2018년에 ELMo가 도입했고, 같은 해 BERT가 standard로 만들었습니다.910 실제 model에서 측정하면 숫자가 설명보다 더 선명합니다:
sentence A: "He sat on the bank of the river and watched the water go by."
sentence B: "She deposited the cheque at the bank on the corner of the street."
static vector for 'bank' (a row of the input embedding table)
cosine A vs B ........................ 1.000000
contextual vector for 'bank', layer by layer
layer | A vs B | A vs another river sentence | B vs another money sentence
0 | 0.9512 | 0.9512 | 0.9359
4 | 0.5647 | 0.8987 | 0.7716
9 | 0.4284 | 0.8699 | 0.7568
12 | 0.5278 | 0.8702 | 0.7335첫 row는 approximate가 아니라 exact입니다. bank의 static vector는 두 sentence에서 같은 768개 숫자이므로 cosine은 구조상 1입니다. 아홉 layer 뒤 두 occurrence는 0.43에 놓이는 반면, 서로 다른 river sentence에 있는 bank는 0.87에 머뭅니다. 이 과정 어디에도 sense label은 없었습니다. Sense가 분리된 것은 그것을 분리하는 일이 training objective, 즉 neighbour들로 hidden token을 맞히는 일을 더 쉽게 만들기 때문입니다.
두 가지 detail은 주목할 만합니다. Layer 0은 이미 1.0이 아니라 0.9512입니다. Position embeddings가 더해졌고 단어가 각 sentence에서 다른 위치에 있기 때문입니다. 그리고 similarity는 layer 11과 12에서 다시 올라갑니다. Pretrained model의 final layer는 training objective에 특화되어 있고, representation을 가져오기에 가장 좋은 곳이 아닌 경우가 많습니다.
세부 정보 보기
Optional: weight tying.
bert-base-uncased에서 embedding table은 입니다. 23,440,896개 숫자, 즉 **model의 109,482,240개 parameter 중 21.4 %**입니다. 작은 language model에서는 비율이 더 큽니다. 그래서 한 가지 trick은 거의 보편적으로 쓰입니다. Input table과 logits를 만드는 output layer가 같은 matrix이고, 한 번은 row lookup으로, 한 번은 transpose되어 사용됩니다.11 Output layer는 이미 모든 vocabulary entry에 vector를 할당합니다. 각 vector와 dot product를 취하기 때문입니다. Tying은 token을 읽는 데 쓰는 vector와 그것을 쓰는 데 쓰는 vector가 같은 object여야 한다고 말합니다. Parameter를 줄이면서 perplexity도 개선합니다. 둘이 동시에 일어나는 경우는 드물기에 눈여겨볼 만합니다.
Embedding model은 language model이 아닙니다
섹션 링크: Embedding model은 language model이 아닙니다의미로 corpus를 search하려면 sentence마다 vector 하나가 필요합니다. 그것들이 주어지면 search는 trivial합니다. 이것이 semantic retrieval의 전부이고, 19장은 그 주변의 모든 것에 관한 장입니다:
E = normalise(embed(sentences)) # (200, d), every row of length 1
q = normalise(embed([query])) # (1, d)
scores = q @ E.T # one matrix multiply
top5 = scores[0].argsort()[::-1][:5]따라서 유일한 진짜 질문은 embed가 어디서 오느냐입니다. 당연해 보이는 방법은 pretrained language model을 가져와 각 sentence를 통과시키고 token vector를 평균내는 것입니다. 다음은 그 방법을 네 가지 alternative와 비교한 결과입니다. 두 가지 방식으로 score했습니다. STS benchmark의 1,379개 pair에서 cosine과 human similarity judgement 사이의 rank correlation, 그리고 그중 paraphrase 강도가 가장 높은 200개 pair로 만든 index에서 top-1 retrieval입니다. 각 pair의 한쪽을 index하고 다른 쪽을 query로 썼습니다.
| sentence가 embedded되는 방식 | rank correlation | 200-sentence index의 top-1 |
|---|---|---|
| binary word overlap(model 없음) | 0.5500 | 89.0 % |
| 위에서 train한 static vector의 mean | 0.5263 | 85.5 % |
BERT, [CLS] token | 0.2030 | 67.0 % |
| BERT, token vector의 mean | 0.4729 | 84.0 % |
| MiniLM, contrastively trained | 0.8203 | 92.0 % |
가운데 세 row를 처음 두 row와 맞춰 읽어 보세요. 1억 900만 parameter의 pretrained transformer를 obvious한 방식으로 쓰면, 두 sentence가 공유하는 단어 수를 세는 것보다 sentence similarity 판단을 더 못합니다. 방금 train한 100-dimensional text8 vector를 평균낸 것보다도 못합니다. Tutorial들이 여전히 추천하는 [CLS] token은, BERT가 sentence-level objective를 붙여 pretrained되었다는 이유로 추천되지만, 그 절반보다도 못합니다.
이것은 BERT의 결함이 아닙니다. Objective의 문제입니다. Language model은 hidden state가 token을 predict하도록 train됩니다. 그 어디에도 두 paraphrase가 서로 가까워져야 한다는 요구는 없고, cosine이 “same meaning”을 뜻하는 geometry에 대한 reward도 없습니다. 마지막 row는 크기가 5분의 1인 model(22,713,216 parameters)이고, 전혀 다른 loss로 train되었습니다. Contrastive learning입니다. Example은 pair입니다. 질문과 답, sentence와 paraphrase 같은 것들입니다. Objective는 true pair를 끌어당기고 sampled negative를 밀어냅니다. 이것이 Sentence-BERT의 contribution이자 embedding-model industry 전체의 출발점입니다.12 Dense Passage Retrieval은 같은 recipe를 search에 직접 적용하며, query용 encoder 하나와 passage용 encoder 하나를 둡니다.13
그래서 practical rule은 다음과 같습니다:
Embedding model은 마지막 layer를 제거한 language model이 아닙니다. 보통 훨씬 작고, 다른 objective 위에 있는 다른 model입니다. Cosine이 당신이 원하는 의미를 갖는 것은 그것이 target인 pair 위에서 train되었기 때문입니다. 위 table은 하나를 다른 것으로 대체할 때 치르는 비용입니다.
그리고 이 family는 word order에 실패합니다. “The dog bit the man”과 “the man bit the dog”는 동일한 bag of words를 가지므로 word overlap과 static-vector average는 cosine이 정확히 1.000000입니다. Position을 보기는 하는 mean-pooled BERT도 거의 그 값에 도달합니다. Contrastively trained MiniLM조차 0.979에 놓습니다. Retrieval task가 누가 누구에게 무엇을 했는지에 달려 있다면, 어떤 cosine threshold도 당신을 구하지 못합니다.
19장은 이 토대 위에 production retrieval system을 만들고 구체적인 cosine cut-off에 도달합니다. 이 장의 마지막 측정은 그런 숫자가 마법이 아니라 defensible한 값이 되게 해 줍니다.
차원의 저주, table 하나로 보기
섹션 링크: 차원의 저주, table 하나로 보기Real embeddings는 수백 또는 수천 개 component를 가지며, 그 위에서는 distance가 이상하게 행동합니다. dimensions의 unit cube에서 random point 1,000개를 뽑고, 그중 어떤 두 점 사이의 가장 큰 distance와 가장 작은 distance의 ratio를 봅니다:
| dimensions | nearest pair | farthest pair | ratio |
|---|---|---|---|
| 2 | 0.0007 | 1.3612 | 1921.66 |
| 10 | 0.2361 | 2.3397 | 9.91 |
| 100 | 3.0047 | 5.1752 | 1.72 |
| 1,000 | 11.7809 | 14.0306 | 1.19 |
| 10,000 | 39.6152 | 42.0125 | 1.06 |
1만 dimensions에서는 가장 먼 점 pair가 가장 가까운 pair보다 겨우 6 % 더 멉니다. 모든 것이 대략 모든 것과 equidistant해지고, “nearest neighbour”는 많은 정보를 담지 못하게 됩니다. 이것이 차원의 저주이며, 큰 vector database가 exact nearest-neighbour search를 하지 않는 이유 중 하나이기도 합니다. 같은 동전의 다른 면은 cosine threshold를 작동 가능하게 만듭니다. Random unit vector 1,000쌍을 측정하면 mean cosine은 100 dimensions에서 , 768에서 에 놓이고, standard deviation은 0.0968과 0.0357입니다. 768 dimensions에서는 random pair의 0.2 %만이 absolute value로 0.1을 넘습니다. 따라서 측정된 similarity 0.4는 “40 % 비슷함”이 아닙니다. 우연이 만들어 내는 어떤 값보다도 훨씬 바깥에 있습니다. 그래서 0.3에서 0.7 사이의 threshold가 noise 한가운데 앉아 있는 것이 아니라 signal과 noise를 나눕니다.
다음으로 어디로 가는가
섹션 링크: 다음으로 어디로 가는가이 장의 model은 고정된 수의 이전 character를 읽고, 각각을 lookup한 뒤, 결과를 순서대로 붙입니다. 이 design에는 두 가지 문제가 있고, 사실 같은 문제입니다.
Context table을 다시 보세요. 세 character에서 여덟 character로 가면 parameter는 거의 두 배가 되었고 0.06 nats를 샀습니다. Cost는 context에 따라 linear하게 자랍니다. position이 하나 늘 때마다 첫 weight matrix의 slab가 하나 더 필요합니다. 하지만 benefit은 그렇지 않습니다. 이것을 1,000 tokens까지 밀어붙이면 첫 layer만으로도 model의 나머지보다 커지고, 대부분은 어떤 prediction에도 중요하지 않은 position에 쓰입니다.
두 번째 문제도 바로 이것입니다. Model에는 이전 tokens 중 어떤 것이 중요한지 결정할 방법이 없습니다. Position 2는 자기 weight를 갖고, position 7도 자기 weight를 갖습니다. 그 안에 무엇이 있든 영구적으로 그렇습니다. Model이 nell를 spelling할 때 decisive character는 바로 직전 글자입니다. Sentence에 pronoun이 들어 있을 때 referent를 정하는 word는 40 tokens 뒤에 있을 수 있습니다. 그리고 “40 back”에 fixed slot을 배정할 수는 없습니다. 다음번에는 6일 것이기 때문입니다.
우리가 원하는 것은 각 prediction마다 이전 각 token이 얼마나 많이 count되어야 하는지를 계산하는 model입니다. Layout이 고정한 weight가 아니라 content가 만들어 낸 context 위의 weight입니다. 이것을 조심스럽게 적어 보면 아주 평범한 것으로 시작합니다. 이전 tokens 위의 average입니다. 그런 다음 그 average의 weight가 learned되게 하고, 묻는 token이 무엇인지에 따라 달라지게 합니다.
그것이 attention이고, 9장입니다.
Sources and method
섹션 링크: Sources and method함께 읽을 만한 자료: Jurafsky와 Martin의 Speech and Language Processing 3장. N-gram model, smoothing, perplexity를 여기서 다룰 수 있는 것보다 훨씬 더 carefully하게 설명하며, adding one보다 interpolation과 back-off가 왜 나은지도 포함합니다. 확률론적 관점의 language modelling은 Stanford CS229 notes §17.1–17.2를 보세요. 그리고 위 Linzen 논문은 짧고 처음부터 끝까지 읽을 가치가 있습니다.
-
Name-generation example, dataset, 그리고 count table에서 Bengio-style network로 가는 progression은 Andrej Karpathy의 building makemore series를 따릅니다. 그중 처음 두 part가 이 장의 가장 좋은 companion입니다. ↩
-
Shannon, C. E. Prediction and Entropy of Printed English. Bell System Technical Journal 30(1), pp. 50–64 (1951). 사람들이 영어의 다음 글자를 맞히는 실험, 그리고 원래의 bits-per-character 측정. ↩
-
Shannon, C. E. A Mathematical Theory of Communication. Bell System Technical Journal 27 (1948). Source coding theorem, 그리고 prediction과 compression의 동일시. ↩
-
Bengio, Y., Ducharme, R., Vincent, P. and Jauvin, C. A Neural Probabilistic Language Model. Journal of Machine Learning Research 3, pp. 1137–1155 (2003). 위에서 사용한 architecture: word마다 embedding 하나, fixed window 위에서 concatenate, hidden layer를 거쳐 vocabulary 위의 softmax로. ↩
-
Mikolov, T., Chen, K., Corrado, G. and Dean, J. Efficient Estimation of Word Representations in Vector Space. arXiv:1301.3781 (2013). CBOW와 skip-gram, 그리고 위에서 사용한 analogy set. ↩
-
Mikolov, T., Sutskever, I., Chen, K., Corrado, G. and Dean, J. Distributed Representations of Words and Phrases and their Compositionality. arXiv:1310.4546 (2013). Negative sampling, frequent word subsampling, 그리고 위에서 사용한 3/4 power로 올린 noise distribution. ↩
-
Pennington, J., Socher, R. and Manning, C. GloVe: Global Vectors for Word Representation. EMNLP 2014. Streamed local window 대신 global co-occurrence matrix의 factorisation에서 얻은 word vectors. ↩
-
Linzen, T. Issues in evaluating semantic spaces using word analogies. RepEval 2016, arXiv:1606.07736. 위에서 재현한 offset-free baseline의 source. ↩
-
Peters, M. et al. Deep contextualized word representations. arXiv:1802.05365 (2018). ELMo: bidirectional language model이 계산하는 occurrence마다 하나의 vector. ↩
-
Devlin, J., Chang, M.-W., Lee, K. and Toutanova, K. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. arXiv:1810.04805 (2018). bank experiment에서 측정한 model. ↩
-
Press, O. and Wolf, L. Using the Output Embedding to Improve Language Models. arXiv:1608.05859 (2016), and Inan, H., Khosravi, K. and Socher, R. Tying Word Vectors and Word Classifiers. arXiv:1611.01462 (2016). 같은 trick에 대한 두 개의 독립적인 argument. ↩
-
Reimers, N. and Gurevych, I. Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks. arXiv:1908.10084 (2019). 첫 measurement, 즉 mean-pooled BERT가 sentence similarity에서 averaged static vector보다 못하다는 결과가 위 table이 재현한 것입니다. ↩
-
Karpukhin, V. et al. Dense Passage Retrieval for Open-Domain Question Answering. arXiv:2004.04906 (2020). Two-encoder retriever의 contrastive training. 19장 retrieval stack의 직접적인 조상입니다. ↩