Attention และบล็อก Transformer อนุมานจากค่าเฉลี่ย
เริ่มจากสรุป context ที่ถูกที่สุดคือค่าเฉลี่ย วัดว่ามันพลาดอย่างไร แล้วปล่อยให้สูตร attention เกิดจากการซ่อมมัน
ในหน้านี้
คุณมาถึงตรงนี้พร้อม tokenizer จาก บทที่ 7, ตาราง embedding จาก บทที่ 8, และ objective ที่มากับมัน: เมื่อมี tokens ก่อนหน้าแล้ว ให้ใส่ความน่าจะเป็นให้ token ถัดไป
สิ่งที่หายไปคือส่วนกลาง เพื่อทำนาย token model ต้องมี vector หนึ่งตัว ที่สรุปทุกอย่างก่อนหน้า และสิ่งที่คุณสร้างมายังไม่มีอะไรผลิตสิ่งนั้นได้ embedding ของ token ไม่ใช่มัน — นั่นคือ bigram model และมันไม่มีทางรู้ว่าประโยคเริ่มด้วยคำถาม การต่อ embeddings ก่อนหน้าทั้งหมดเข้าด้วยกันก็ไม่ใช่เหมือนกัน: จำนวนของมันเปลี่ยนทุก step และเมทริกซ์น้ำหนักขนาดคงที่รับอินพุตความยาวแปรผันไม่ได้
ดังนั้น: vector ขนาดคงที่หนึ่งตัว ที่สรุป vectors จำนวนแปรผัน นั่นคือปัญหาทั้งหมด และ attention คือสิ่งที่ได้จากการแก้มันด้วยวิธีขี้เกียจที่สุดเท่าที่เป็นไปได้ แล้วซ่อมสองอย่างที่พัง
คำตอบที่วงการเคยมี และทำไมเราจะไม่สร้างมัน
ลิงก์ไปยังส่วน: คำตอบที่วงการเคยมี และทำไมเราจะไม่สร้างมันตั้งแต่ปี 1997 ถึงประมาณ 2017 สรุปคือ recurrent state: เก็บ vector แล้วอัปเดตมันทุก token, ขนาดคงที่ อินพุตแปรผัน รูปร่างถูกต้องพอดี
มันล้มเหลวสามทาง และสถาปัตยกรรมของบทนี้ตอบทั้งสามทาง Backpropagating ผ่าน steps คูณ Jacobians ตัวเข้าด้วยกัน ทำให้ gradient หายไปหรือระเบิด — โรคที่ บทที่ 5 วัดภายใน node เดียว LSTM1 ถูกออกแบบมาเพื่อรับมือสิ่งนั้นโดยตรง และดันช่วงที่ใช้งานได้จากหลักสิบ steps ไปเป็นหลักร้อย โดยไม่เปลี่ยนข้อเท็จจริงที่ว่าข้อมูลจาก token 5 ไปถึง token 500 ได้ก็ต่อเมื่อรอดผ่านการอัปเดตแบบลำดับ 495 ครั้ง แหล่งข้อมูลทั้งหมดต้องยัดลงใน vector เดียว: ในการแปลแบบ sequence-to-sequence2 encoder บีบอัดอินพุตลงใน state สุดท้าย Bahdanau, Cho และ Bengio ตั้งชื่อคอขวดนั้นและแก้มันในปี 2014 สามปีก่อน transformer โดยให้ decoder รับผลรวมถ่วงน้ำหนักของ encoder states ทั้งหมด ด้วยน้ำหนักที่มันคำนวณเอง3 ทุกอย่างด้านล่างคือแนวคิดนั้น นำมาใช้กับ sequence ที่มองตัวเอง พร้อมลบ recurrence ออก และ การอัปเดตเป็นแบบลำดับโดยโครงสร้าง: ต้องมี และ GPU ที่มีคอร์หมื่นตัวก็ทำอะไรกับเรื่องนั้นไม่ได้ สถาปัตยกรรมที่ชนะไม่ได้ฉลาดกว่าอย่างเห็นได้ชัด แต่มันคือสถาปัตยกรรมที่ step แพงเป็นการคูณเมทริกซ์
inductive bias แบบคลาสสิกอีกอย่างคือ convolution — เลื่อนฟิลเตอร์เล็กตัวหนึ่งไปทั่วอินพุต เพื่อให้ feature ที่ตรวจพบที่ไหนก็ตรวจพบได้ทุกที่ — ก็ไม่ได้สร้างที่นี่เช่นกัน มันเกือบถูกต้องพอดีสำหรับภาพ และถูกมอบให้คอร์ส vision ไป หลังหน้านี้ทั้ง recurrence และ convolution จะไม่กลับมาอีก นั่นคือเหตุผลที่ทั้งสองไม่มีบทของตัวเอง: บทที่ 1 สัญญาว่าสิ่งที่ละไว้จะถูกประกาศ ไม่ใช่เงียบหาย
สรุปที่ถูกที่สุดเท่าที่มี
ลิงก์ไปยังส่วน: สรุปที่ถูกที่สุดเท่าที่มีฟังก์ชันที่ชัดเจนที่สุดของ vectors จำนวนแปรผันที่คืน vector หนึ่งตัวคือ ค่าเฉลี่ย:
อินพุตกี่ตัวก็ได้ เอาต์พุตขนาดคงที่ differentiable ฟรี ตาราง embedding บวกค่าเฉลี่ยนี้ บวก linear layer ไปยัง vocabulary คือ language model ที่สมบูรณ์ในสิบห้าบรรทัด มันยังแย่มากด้วย และวิธีที่มันแย่คือที่มาของการอนุมานทั้งหมด
corpus ด้านล่างคือ Shakespeare หนึ่งเมกะไบต์ 1,115,394 characters ผ่าน byte-level BPE tokenizer แบบที่สร้างในบทที่ 7 ด้วย vocabulary 1024: 459,760 tokens ที่ 2.43 characters ต่อ token แบ่ง 90/10 ทุก model กว้าง 128 เห็น 128 tokens และฝึก 3000 steps ของ AdamW ที่ ด้วย batch 64 Perplexity อยู่บน split ที่กันไว้4
| model | parameters | validation perplexity |
|---|---|---|
| token ปัจจุบันเท่านั้น ไม่มี context เลย | 263,168 | 59.71 |
| บวกค่าเฉลี่ยแบบสม่ำเสมอของทุกอย่างก่อนหน้า | 263,168 | 248.07 |
| บวก position embeddings ที่เรียนรู้ได้ | 279,552 | 245.93 |
| ค่าเฉลี่ยแบบสม่ำเสมอ บวก เข้ากับ token แทนที่จะแทนที่มัน | 263,168 | 60.45 |
อ่านแถวที่สองสองครั้ง การเฉลี่ย context ไม่ได้ช่วยเล็กน้อย แต่มันทำให้ model แย่กว่าการไม่สนใจ context เลยถึงสี่เท่า มีสองเหตุผล ทั้งคู่พิสูจน์ได้ ไม่ใช่แค่เชิงประจักษ์
ค่าเฉลี่ยมองไม่เห็นลำดับ การบวกสลับที่ได้ ดังนั้นการสับหน้าต่างไม่ทำให้สรุปเปลี่ยน — ไม่ใช่แค่ประมาณ:
A = torch.tril(torch.ones(T, T))
A = A / A.sum(1, keepdim=True) # rows of the averaging matrix
y = x[torch.randperm(T)] # the same tokens, shuffled
print((A[-1] @ x - A[-1] @ y).abs().max().item())2.9802322387695312e-08noise แบบ floating-point จากผลรวมที่เรียงใหม่: สรุปทั้งสองเป็น vector เดียวกัน model ที่มอง context ได้แค่ค่าเฉลี่ย แยก the dog bit the man ออกจาก the man bit the dog ไม่ได้ แถวที่สามพิสูจน์ว่าแก้ไม่ได้ด้วยการเพิ่มตำแหน่งให้กับอินพุต — learned position embedding บนทุก token ก่อนเฉลี่ย ซื้อมาได้ 2.14 จุดจาก 188 ตำแหน่งเข้าไปในผลรวม แล้วผลรวมก็ลืมมัน
และค่าเฉลี่ยกลบปัจจุบัน ที่ตำแหน่ง 100 token ปัจจุบันเป็นหนึ่งในร้อยของสรุป เรื่องนี้มีวิธีแก้ถูก ๆ ที่คุณมีอยู่แล้ว: เก็บ token ไว้แล้ว บวก สรุปเข้าไป — residual connection จาก บทที่ 6 และแถวที่สี่คือสิ่งที่มันทำ เมื่อซ่อมการเจือจางแล้ว ค่าเฉลี่ยแบบสม่ำเสมอไม่ช่วย อะไรเลย: 60.45 เทียบกับ baseline 59.71 ทุก token อยู่ในนั้น ถ่วงน้ำหนักเท่ากัน และการถ่วงเท่ากันก็เหมือนกับไม่มีข้อมูล
ปัญหาไม่ใช่การเฉลี่ย แต่คือ น้ำหนัก
ค่าเฉลี่ยคือการคูณเมทริกซ์ และ mask คือ softmax
ลิงก์ไปยังส่วน: ค่าเฉลี่ยคือการคูณเมทริกซ์ และ mask คือ softmaxการเฉลี่ยบน prefix ที่โตขึ้นดูเหมือน loop แต่มันคือการคูณหนึ่งครั้งด้วยเมทริกซ์ lower-triangular ที่แต่ละแถวรวมกันได้หนึ่ง — และยังเป็น softmax แบบตรงตัวด้วย:
loop = torch.stack([x[:t + 1].mean(0) for t in range(T)]) # the obvious version
A = torch.tril(torch.ones(T, T))
A = A / A.sum(1, keepdim=True)
mat = A @ x # the same thing
S = torch.zeros(T, T).masked_fill(torch.tril(torch.ones(T, T)) == 0, float("-inf"))
soft = F.softmax(S, dim=-1) @ x # and the same thing againloop vs matmul max |diff| = 5.960464477539063e-08
loop vs softmax max |diff| = 5.960464477539063e-08
the averaging matrix A (rows sum to 1, upper triangle is zero):
1.000 0.000 0.000 0.000 0.000 0.000
0.500 0.500 0.000 0.000 0.000 0.000
0.333 0.333 0.333 0.000 0.000 0.000
0.250 0.250 0.250 0.250 0.000 0.000
0.200 0.200 0.200 0.200 0.200 0.000
0.167 0.167 0.167 0.167 0.167 0.167ตอนนี้มีสามองค์ประกอบที่มีชื่อของ transformer อยู่บนจอแล้ว สามเหลี่ยมคือ causal mask ซึ่งถูกบังคับโดย objective: ถ้าตำแหน่ง มองเห็นตำแหน่ง ได้ คำตอบก็อยู่ในอินพุต — leak ที่บทที่ 6 บอกให้คุณ audit เพียงแต่มันอยู่ในสถาปัตยกรรม softmax คือวิธี implement mask: การตั้งค่า entries ที่ห้ามเป็น ส่งมันไปเป็นศูนย์พอดีและ normalise ส่วนที่เหลือ ดังนั้น masking และ normalising จึงเป็น operation เดียวกัน (ใช้ ไม่ใช่ -1e9: มันคือค่าที่ masking หมายถึง มันรอดจากการ cast เป็น float16 ในรูป และช่วยให้คุณไม่ต้องตัดสินว่าค่าคงที่ที่เลือกใหญ่พอสำหรับ range ที่บังเอิญอยู่หรือไม่ — ซึ่งคือกล่อง floating-point ของ บทที่ 2 ที่ถามคำถามซึ่งคุณไม่จำเป็นต้องตอบ) และ scores คือ free parameter ค่าเฉลี่ยแบบสม่ำเสมอคือสิ่งที่ได้เมื่อทุก allowed score เป็นเลขเดียวกัน ใส่เลขอะไรก็ได้ตรงนั้น แล้ว softmax จะเปลี่ยนมันเป็นน้ำหนักที่ถูกต้อง
ส่วนที่เหลือของบทนี้คือคำถามเดียว: เลขเหล่านั้นมาจากไหน
Query, key, value
ลิงก์ไปยังส่วน: Query, key, valueมันเป็น parameters ธรรมดาไม่ได้ เมทริกซ์ ที่เรียนรู้ได้จะเหมือนกันทุกประโยค — มันเข้ารหัสได้ว่า “มองย้อนกลับไปสี่ tokens” แต่ไม่มีวันเข้ารหัสได้ว่า “มองคำนามที่สรรพนามนี้อ้างถึง” น้ำหนักที่เชื่อมตำแหน่ง กับตำแหน่ง ต้องขึ้นกับสิ่งที่อยู่ที่ ทั้งสอง ตำแหน่ง เพราะความเกี่ยวข้องเป็นความสัมพันธ์ ไม่ใช่คุณสมบัติ: คำว่า it ไม่ได้เกี่ยวข้องในตัวเอง แต่มันเกี่ยวข้อง กับ บางอย่าง
ฟังก์ชันที่ถูกที่สุดของ vectors สองตัวที่คืนตัวเลขคือ dot product จากบทที่ 1 ให้ score ตำแหน่ง สำหรับตำแหน่ง เป็น แล้วกลไกก็ทำงาน — แย่ ในสองทางที่บังคับทุกอย่างที่เหลือ dot product ของ vector กับตัวเองคือ norm กำลังสอง ดังนั้นทุก token จะ attend ส่วนใหญ่ไปที่ตัวเอง และความสัมพันธ์จะ สมมาตร: ถ้า it attend ไปที่ animal อย่างแรง animal ก็ attend ไปที่ it อย่างแรง ซึ่งไม่จริงสำหรับภาษา ที่ adjective ต้องการ noun ของมันมากกว่า noun ต้องการ adjective มาก
ดังนั้นให้ token แต่ละตัวมีสองบทบาท เป็น linear maps ที่เรียนรู้ได้สองตัวของมัน: สิ่งที่ตำแหน่งนี้กำลัง มองหา, , คือ query; และสิ่งที่มัน เสนอให้ถูกพบด้วย, , คือ key ให้ score เป็น แล้วความสมมาตรก็หายไป เพราะ : token สามารถโฆษณาอย่างหนึ่งและค้นหาอีกอย่างได้
ยังมีอีกอย่างที่ผิด ผลรวมถ่วงน้ำหนักเดิมรวมบน เอง ซึ่งบังคับให้สิ่งที่ถูก คัดลอก เป็นสิ่งเดียวกับที่ถูก จับคู่ การจับคู่ต้องการ features ที่ระบุ token; การคัดลอกต้องการ features ที่มีประโยชน์ downstream ดังนั้นเรียนรู้ map ที่สาม คือ value แล้วรวมสิ่งเหล่านั้น
ตอนนี้สูตรเป็นแค่งานบัญชีรูปร่าง:
โดย คือ causal mask เป็นศูนย์บนและใต้เส้นทแยงมุม และเป็น เหนือเส้นทแยงมุม ใน code มันยาวสามสิบบรรทัด ซึ่งยี่สิบบรรทัดคือ shapes:
class Head(nn.Module):
"""One head of causal self-attention."""
def __init__(self, d_model, d_head, block):
super().__init__()
self.q = nn.Linear(d_model, d_head, bias=False)
self.k = nn.Linear(d_model, d_head, bias=False)
self.v = nn.Linear(d_model, d_head, bias=False)
self.d_head = d_head
self.register_buffer("mask", torch.tril(torch.ones(block, block)).bool())
def forward(self, x):
T = x.shape[1]
q, k, v = self.q(x), self.k(x), self.v(x)
s = q @ k.transpose(-2, -1) / math.sqrt(self.d_head)
s = s.masked_fill(~self.mask[:T, :T], float("-inf"))
w = F.softmax(s, dim=-1)
return w @ v Score, mask, normalise, mix ที่เหลือทั้งหมดคือ projection
การหารด้วยรากที่สอง และมันป้องกันอะไร
ลิงก์ไปยังส่วน: การหารด้วยรากที่สอง และมันป้องกันอะไรคำอธิบายแทบทุกอันของ บอกว่า “เพื่อไม่ให้ softmax saturate” ซึ่งจริง แต่ไม่อธิบายอะไรเลย เหตุผลเป็น variance สองบรรทัดจากบทที่ 2 ถ้า entries ของ และ เป็นอิสระ มี mean ศูนย์และ variance หนึ่ง แต่ละผลคูณ มี variance หนึ่ง และ variances ของสิ่งที่เป็นอิสระบวกกัน:
ดังนั้น scores มี standard deviation วัดจากคู่สุ่มสองหมื่นคู่:
d Var(q.k) std sqrt(d)
4 3.975 1.994 2.000
16 16.071 4.009 4.000
64 64.249 8.016 8.000
256 253.065 15.908 16.000
1024 1015.562 31.868 32.000เหตุผลที่เรื่องนี้สำคัญ: softmax ไวต่อสเกลในแบบที่ linear layer ไม่เป็น การคูณอินพุตของ linear layer สองเท่าทำให้เอาต์พุตสองเท่า; การคูณ scores ด้วยสิบก่อน softmax เปลี่ยน soft blend เป็น hard choice หนึ่ง row ของ 64 scores พร้อมและไม่มีการหาร:
| น้ำหนักใหญ่สุด ไม่หาร | entropy | effective tokens | น้ำหนักใหญ่สุด หารแล้ว | entropy | effective tokens | |
|---|---|---|---|---|---|---|
| 4 | 0.205 | 2.944 | 19.0 | 0.081 | 3.758 | 42.9 |
| 16 | 0.438 | 1.692 | 5.4 | 0.075 | 3.849 | 46.9 |
| 64 | 0.489 | 0.874 | 2.4 | 0.085 | 3.673 | 39.4 |
| 256 | 0.9999 | 0.0007 | 1.0 | 0.143 | 3.547 | 34.7 |
| 1024 | 1.0000 | 0.0000 | 1.0 | 0.132 | 3.644 | 38.3 |
“Effective tokens” คือ exponential ของ entropy: row นั้นเฉลี่ยจริง ๆ เหนือกี่ตำแหน่ง เมื่อไม่หาร ที่ head ที่เพิ่ง initialise attend ไปที่ token หนึ่ง ตัวพอดีจาก 64 โดยถูกเลือกจากการสุ่มล้วน ๆ
นั่นแย่ใน forward และแย่กว่าใน backward ในรูปร่างที่บทที่ 5 วัดบน ไปแล้ว softmax ที่ปักใจกับ entry เดียวแทบไม่มี derivative: diagonal ของ Jacobian คือ เป็นศูนย์ที่ปลายทั้งสอง จาก rows สุ่มสองพัน rows:
| ไม่หาร | หารแล้ว | rows ที่ saturated (น้ำหนักใหญ่สุดมากกว่า 0.99) | |
|---|---|---|---|
| 4 | 0.8427 | 0.9568 | 0.2 % → 0.0 % |
| 64 | 0.2940 | 0.9609 | 17.9 % → 0.0 % |
| 256 | 0.1406 | 0.9609 | 49.1 % → 0.0 % |
| 1024 | 0.0681 | 0.9611 | 70.4 % → 0.0 % |
ที่ เจ็ดในสิบ rows ถูกแช่แข็งก่อนเริ่มฝึก และ head ที่เริ่มแบบแช่แข็งเรียนรู้ไม่ได้ว่าควรมองอะไร เมื่อหารแล้ว ค่านี้ราบที่ 0.96 ทุก width และไม่มีอะไร saturate
ต่อไปคือส่วนที่ไม่มีใครตีพิมพ์: มันเปลี่ยน perplexity สุดท้ายไหม ลบการหารแล้วฝึก ที่ head widths สี่แบบ:
| head width | ไม่หาร | หารด้วย | หารด้วย |
|---|---|---|---|
| สี่ heads, | 37.29 | 38.07 | 37.89 |
| หนึ่ง head, | 48.51 | 46.10 | 45.99 |
| หนึ่ง head, | 65.37 | 47.53 | — |
| หนึ่ง head, | 67.06 | 49.15 | — |
| หนึ่ง head, | 76.69 | 59.17 | — |
สองแถวแรกมาจาก budget 3000-step ข้างต้น สามแถวสุดท้ายเป็น run ที่สั้นกว่า — 1500 steps, batch 32, หนึ่ง head, ไม่มี normalisation ก่อน projections — โดยทั้งสอง variants อยู่ใต้ settings เดียวกัน
ที่ การหารไม่มีค่าอะไร และ run ที่ไม่มีมันนำหน้าเล็กน้อยมาก นั่นไม่ใช่ใบอนุญาตให้ทิ้งมัน เพราะที่ 256 มันมีค่า 18 จุด perplexity และที่ 1024 มีค่า 17 กลไกเห็นได้จาก scores เอง:
| score std ตอน init | หลัง 1500 steps ไม่หาร | หลัง 1500 steps หารแล้ว | rows saturated ไม่หาร | หารแล้ว | |
|---|---|---|---|---|---|
| 256 | 10.49 | 121.67 | 2.13 | 91.9 % | 0.8 % |
| 512 | 15.13 | 836.85 | 2.66 | 98.7 % | 1.3 % |
| 1024 | 21.15 | 5147.46 | 3.44 | 99.9 % | 16.5 % |
head ที่ไม่หารไม่ฟื้นตัว มัน หนีเตลิด: standard deviation ของ scores จาก 21 ตอน initialisation กลายเป็น 5147, attention entropy ลดเป็นศูนย์ และ 99.9 % ของ rows ใส่น้ำหนักมากกว่า 0.99 ไว้ที่ token เดียว เมื่อ head กลายเป็น hard selector แล้ว gradient แทบเป็นศูนย์และไม่มีอะไรดึงมันกลับ ดังนั้นการ collapse จึงเสถียร head ที่หารแล้วอยู่ที่ score standard deviation 3.44 หลังการฝึกเดียวกัน ซึ่งเป็น soft blend ที่ยังเปลี่ยนได้
Vaswani et al. พูดเช่นนี้พอดีและไม่มากกว่านั้น — พวกเขาสงสัยว่าผลคูณ “มี magnitude ใหญ่ขึ้นสำหรับค่ามากของ ” แล้วหาร5 คำว่า ใหญ่ รับน้ำหนักไว้มาก และตารางบอกว่าใหญ่เริ่มตรงไหน: ไม่มีอะไรที่ 32 และทุกอย่างที่ 256
มากกว่าหนึ่งความคิดเห็น และสองในสามที่ไม่มีใครพูดถึง
ลิงก์ไปยังส่วน: มากกว่าหนึ่งความคิดเห็น และสองในสามที่ไม่มีใครพูดถึงหนึ่ง head คือ softmax row หนึ่งต่อหนึ่งตำแหน่ง ดังนั้นมันมีคำตอบเดียวต่อ “อะไรเกี่ยวข้องตรงนี้” การทำนายคำหลัง the ใน the animal that crossed the wet street ต้องการช่องวากยสัมพันธ์ subject และ token ก่อนหน้าพร้อมกัน และ probability distribution หนึ่งอันไม่สามารถกระจุกอยู่สามที่ได้ ดังนั้นรันหลาย heads ขนานกัน แต่ละ head กว้าง ต่อเข้าด้วยกัน แล้วผสมด้วยเมทริกซ์อีกตัว : คุณแบ่ง width เป็นส่วน ๆ ไม่ได้เพิ่มมัน
Attention ยังทำสิ่งเดียวพอดี — มันย้ายข้อมูล ระหว่าง ตำแหน่ง operation ทุกตัวใน code ข้างต้นเป็น linear ตามแกน feature และบทที่ 5 พิสูจน์แล้วว่า stack ของ linear maps คืออะไร ดังนั้นแต่ละ block จึงมี MLP เล็ก ๆ ที่ใช้กับ แต่ละตำแหน่งแยกกัน ขยาย width สี่เท่าแล้วกลับมา โดยมี GELU ตรงกลาง การแบ่งงานนี้ควรจำให้ขึ้นใจ: attention ผสมข้ามตำแหน่ง feed-forward network คำนวณภายในตำแหน่ง
บันไดเต็ม แต่ละแถวเพิ่มหนึ่งชิ้นจากแถวเหนือมัน:
| model | parameters | validation perplexity |
|---|---|---|
| ค่าเฉลี่ยแบบสม่ำเสมอ บวกเข้าไป | 279,552 | 60.45 |
| attention head หนึ่งตัว แทนที่ token | 328,704 | 55.47 |
| attention head หนึ่งตัว บวกเข้าไป | 328,704 | 46.10 |
| สี่ heads แทนหนึ่ง | 345,216 | 43.21 |
| บวก feed-forward network | 476,928 | 39.87 |
| บวก LayerNorm — block สมบูรณ์ | 477,696 | 38.07 |
น้ำหนักที่เรียนรู้ได้ชนะน้ำหนักแบบสม่ำเสมอ 14 จุด perplexity ซึ่งเป็นข้อโต้แย้งทั้งหมดของบทนี้ในหนึ่งแถว สี่ heads ซื้อเพิ่มอีก 3 ด้วย parameters เพิ่ม 16,512 และ head เดียวกันมีค่ามากกว่า 9 จุดเมื่อ บวก มากกว่า แทนที่: attention นำข้อมูลเข้ามา มันไม่ได้ตัดสินว่าตำแหน่งหนึ่งคืออะไร
ทีนี้ parameters อยู่ตรงไหนจริง ๆ ซึ่งมักทำให้คนที่เคยเห็นแต่ diagram แปลกใจ:
| width | heads | attention | feed-forward | total per block |
|---|---|---|---|---|
| 128 | 4 | 65,664 (33.2 %) | 131,712 (66.6 %) | 197,888 |
| 768 | 12 | 2,360,064 (33.3 %) | 4,722,432 (66.6 %) | 7,085,568 |
| 4096 | 32 | 67,112,960 (33.3 %) | 134,238,208 (66.7 %) | 201,367,552 |
สองในสามของทุก transformer block คือ feed-forward network ในทุกสเกล เพราะ attention มีเมทริกซ์ สี่ตัว และ MLP มีเทียบเท่าแปดตัว ไม่ว่า model จะรู้อะไร parameters ส่วนใหญ่ที่ถือมันไว้ก็อยู่ใน MLP ต่อหนึ่งตำแหน่ง
Residuals และ LayerNorm ที่รับมาจากบทที่ 6
ลิงก์ไปยังส่วน: Residuals และ LayerNorm ที่รับมาจากบทที่ 6LayerNorm ถูกสร้างและวัดในบทที่ 6 และบทนี้ใช้มันตามที่ทิ้งไว้ตรงนั้น residual connections ถูกตั้งชื่อและ ablate ไว้ตรงนั้น และถูกสร้างที่นี่ แถว “บวก ไม่ใช่แทนที่” ด้านบนคือ residual connections มีค่า 188 จุด perplexity สำหรับค่าเฉลี่ย และ 9 สำหรับหนึ่ง head LayerNorm7 normalise แต่ละตัวอย่างข้าม features ของมัน และบทที่ 6 ให้เหตุผลว่าทำไมมัน ไม่ใช่ BatchNorm ที่รอดมาที่นี่ — ไม่พึ่ง batch, ไม่มี running statistics, เหมือนกันใน training และ inference, ไม่สนใจความยาว sequence — ทุกข้อกลายเป็น requirement เมื่อคุณ generate ทีละ token ให้ผู้ใช้หนึ่งคน ซึ่งคือจุดที่บทที่ 13 ไปถึง มันมีต้นทุน 768 parameters และซื้อ 1.8 จุด perplexity
class Block(nn.Module):
def forward(self, x):
x = x + self.att(self.ln1(x))
x = x + self.ff(self.ln2(x))
return xดูว่า normalisation อยู่ตรงไหน: บน อินพุตของแต่ละ sub-layer โดย residual path จาก input ไป output ไม่เคยถูก normalise นั่นคือ pre-norm paper ปี 2017 ทำตรงข้าม x = LayerNorm(x + Att(x)) — post-norm ซึ่งวาง LayerNorm บน residual path เอง
Xiong et al. อธิบายความต่างผ่าน gradient ตอน initialisation ซึ่งใน post-norm network ถูกสเกลกับ depth แย่มาก — เหตุผลที่ transformer ต้นฉบับต้องมี learning-rate warmup จึงจะฝึกได้เลย8 สิบสอง blocks, 1000 steps, learning rate :
gradient norm per block at initialisation, before any step
pre-norm block 1 0.0498 ... block 12 0.0657 ratio last/first 1.32
post-norm block 1 0.0977 ... block 12 0.1613 ratio last/first 1.65
pre-norm, no warmup perplexity 37.82
pre-norm, 200-step warmup perplexity 37.62
post-norm, no warmup perplexity 308.05
post-norm, 200-step warmup perplexity 37.88Post-norm ที่ไม่มี warmup แย่กว่าแปดเท่า และ post-norm ที่มี warmup เท่ากับ pre-norm พอดี Warmup ไม่ใช่ best practice ทั่วไปตรงนี้ มันคือ patch สำหรับการจัดวาง normalisation แบบเฉพาะ และการย้าย LayerNorm เอาความจำเป็นของมันออก นั่นคือเหตุผลที่แทบทุก model ตั้งแต่ 2019 เป็น pre-norm และเหตุผลที่ diagram ปี 2017 ควรถูกอ่านเป็นประวัติศาสตร์ ไม่ใช่ specification
token อยู่ที่ไหน
ลิงก์ไปยังส่วน: token อยู่ที่ไหนลบ position embeddings แล้ว model ยังฝึกได้ มันแค่บอกไม่ได้ว่าอะไรอยู่ตรงไหน และนั่นเป็น symmetry ไม่ใช่ training failure ไม่มีอะไรใน attention score กล่าวถึง หรือ เอง ดังนั้นการสลับอินพุตจะสลับเอาต์พุต: self-attention เป็น permutation-equivariant มันคือความมองไม่เห็นลำดับของค่าเฉลี่ยในหน้ากากที่ดีกว่า — causal mask คืนลำดับบางส่วน เพราะแต่ละตำแหน่งเห็น prefix ต่างกัน แต่ภายใน prefix การเรียงทุกรูปแบบเหมือนกัน
สี่วิธีในการฉีดตำแหน่ง ฝึกบนหน้าต่าง 64-token และประเมินที่ 64, 128 และ 256 — เลยความยาวใด ๆ ที่มันเคยเห็น:
| positions | perplexity ที่ 64 | ที่ 128 | ที่ 256 |
|---|---|---|---|
| ไม่มีเลย | 48.79 | 52.63 | 57.52 |
| learned absolute embeddings | 38.63 | 108.47 | 181.94 |
| fixed sinusoids | 42.96 | 95.26 | 152.25 |
| RoPE | 44.12 | 50.52 | 84.84 |
| ALiBi | 44.95 | 43.51 | 42.49 |
Learned absolute embeddings — vector หนึ่งตัวต่อตำแหน่ง บวกเข้ากับ token — ชนะที่ความยาวที่ฝึก แล้วตกหน้าผา เพราะตำแหน่ง 100 ไม่เคยอยู่ใน batch และ embedding ของมันยังเป็น random vector ที่เริ่มต้นมา Sinusoids ตัวเลือกดั้งเดิม คำนวณแทนการเรียนรู้ จาก sines และ cosines ที่ความถี่เว้นแบบเรขาคณิต paper ปี 2017 หวังว่านั่นจะ extrapolate และตารางบอกว่าไม่ — ฟังก์ชันนิยามที่ตำแหน่ง 200 แต่ model ไม่เคยเรียนรู้ที่จะอ่านมันตรงนั้น RoPE9 ไม่เพิ่มอะไร แต่ หมุน query และ key ด้วยมุมที่แปรตามตำแหน่ง ในชิ้นสองมิติ; เพราะการหมุนทั้งสองฝั่งของ dot product เท่ากันทำให้มันไม่เปลี่ยน score จึงลงเอยว่าขึ้นกับ เท่านั้น ดังนั้นตำแหน่งกลายเป็น relative ฟรี ๆ และไม่มีตารางให้ใช้หมด มัน degrade แต่ก็เป็นการ degrade ALiBi10 คือผลลัพธ์ที่ง่ายที่สุดและประหลาดที่สุดที่นี่: linear penalty บน score แปรตามระยะทาง โดยมี slope ต่างกันต่อ head Perplexity ของมัน ดีขึ้น เมื่อหน้าต่างโตเกินความยาวฝึก จาก 44.95 เป็น 42.49 เพราะ penalty นิยามได้ทุกระยะและทุก head ทำสิ่งที่มันถูกฝึกให้ทำต่อไป
บทเรียนอยู่ยาวกว่าตาราง: สถาปัตยกรรมที่ represent บางอย่างไม่ได้ เป็นคนละปัญหากับสถาปัตยกรรมที่ไม่เคย learned range นั้น และอย่างหลังคือสิ่งที่กัดคุณ นี่ยังเป็นกลไกเบื้องหลังประกาศทุกครั้งว่า “เราขยาย context เป็น 128K” — เกือบทั้งหมดคือการ re-scale rotary encoding และนั่นคือเหตุผลที่ บทที่ 16 บอกว่า context limit เคลื่อนที่ ไม่ใช่หายไป
Dropout รับมาด้วยวิธีเดียวกัน: มันปรากฏบน attention weights หลัง softmax, บนเอาต์พุตของแต่ละ sub-layer ก่อน residual addition, และบน embedding sum ทำสิ่งที่บทที่ 6 อธิบายพอดี ใน runs pretraining ขนาดใหญ่ มักตั้งเป็นศูนย์ เพราะ model ที่เห็นแต่ละ token ครั้งเดียวไม่ได้อยู่ในสภาพที่จะ overfit
มันมีต้นทุนเท่าไร
ลิงก์ไปยังส่วน: มันมีต้นทุนเท่าไรมี tensors สองตัวใน layer ที่มี shape โดย คือจำนวน tokens: scores และ weights หลัง softmax อย่างอื่นทั้งหมด — ทุก projection, MLP ทั้งหมด — เป็น linear ใน
หนึ่ง attention layer กว้าง 512, 8 heads, batch หนึ่ง, float32 บน laptop GPU อ่านสองคอลัมน์มิลลิวินาทีเพื่อดู อัตราส่วน เท่านั้น: มันคือ wall clock บนการ์ด laptop 8 GB ที่ throttle จาก 1,785 MHz ลงต่ำกว่า 300 MHz เมื่อร้อน ดังนั้น cold run ของ code เดียวกันนี้จะกลับมาเร็วกว่าเจ็ดถึงสิบเท่า และ run ตอนยุ่งจะช้ากว่านั้นอีก คอลัมน์เมกะไบต์คือ allocator byte counts และไม่ขยับ
tokens ms total ms x4 ms projections attn matrix MB peak MB MB x4
128 2.246 - 1.324 0.5 14.6 -
256 2.855 1.27 2.113 2.0 19.2 1.31
512 5.761 2.02 3.105 8.0 34.4 1.79
1024 16.414 2.85 4.008 32.0 89.1 2.59
2048 51.573 3.14 9.989 128.0 296.1 3.32
4096 225.432 4.37 20.176 512.0 1100.1 3.72
8192 832.838 3.69 40.106 2048.0 4300.1 3.91
16384 OUT OF MEMORY 8192.0
fitted exponent (log-log slope, last four rows): time ~ n^1.91 memory ~ n^1.87คอลัมน์ x4 คืออัตราส่วนกับแถวด้านบน และการเพิ่ม เป็นสองเท่าลู่เข้า 4 พอดีทั้งเวลาและหน่วยความจำ — 3.91 ที่ step สุดท้ายเทียบกับทฤษฎี 4 คอลัมน์ projections คือ control: 4.0 ms ที่ 1024 tokens ไป 40.1 ms ที่ 8192 เป็นปัจจัยสิบสำหรับปัจจัยแปด Linear ตามที่โฆษณา
แล้วดูแถวสุดท้าย หนึ่ง attention layer, หนึ่ง sequence, ไม่มี model รอบมัน หน่วยความจำหมดบน GPU 8 GB ที่ 16,384 tokens — แค่ score matrix อย่างเดียวก็เป็น 8 GB แล้ว เพราะเป็น 8 heads คูณ 16,384 คูณ 16,384 คูณ 4 bytes ไม่ใช่ model; เป็น intermediate tensor ตัวเดียวใน layer เดียว
นั่นคือข้อเท็จจริงทางกายภาพใต้สามบทถัดไป มันคือเหตุผลที่ context window มีขีดจำกัดเลย ซึ่งบทที่ 16 เปลี่ยนเป็นราคา มันคือเหตุผลที่ FlashAttention มีอยู่ โดยคำนวณผลลัพธ์เดียวกันเป็น tiles โดยไม่เคยเก็บเมทริกซ์ — เป็น memory optimisation ก่อนจะเป็น speed optimisation11 และมันคือเลขคณิตเบื้องหลังราคาของ prompt ยาว ซึ่งบทที่ 24 จ่ายใน agent loop — เป็นคนละเรื่องกับข้อค้นพบอีกอย่างของบทนั้น ว่า model ยัง ใช้ context ยาวได้แย่ลงด้วย ซึ่งบทนั้นวัดและปฏิเสธที่จะโทษสูตรนี้
แสดงรายละเอียด
สอง variants ที่ทำให้ cache เล็กลง ตั้งชื่อไว้ที่นี่และจ่ายบัญชีในบทที่ 13
Generation cache keys และ values ของ tokens ที่ประมวลผลแล้ว — หนึ่ง key และหนึ่ง value ต่อ token, ต่อ head ต่อ layer Multi-query attention12 เก็บ query projections ตัว แต่มี key และ value projection เดียวที่ heads ทั้งหมดแชร์กัน หาร cache นั้นด้วย Grouped-query attention13 อยู่กึ่งกลาง: heads ถูกจัดกลุ่ม แต่ละกลุ่มแชร์ key และ value หนึ่งชุด ดังนั้น คือ attention ธรรมดา และ คือ multi-query แทบทุก open model ตั้งแต่ 2023 ใช้มันกับ 4 หรือ 8 groups ทั้งสองอย่างไม่ได้มีอยู่เพื่อคุณภาพ ทั้งสองมีอยู่เพื่อขนาดของ cache นั้น และบทที่ 13 ทำเลขคณิตที่เปลี่ยนมันเป็น “model ไหน fit ใน GPU ของคุณ”
สองรูปร่าง และขนาดของหนึ่งรูปร่าง
ลิงก์ไปยังส่วน: สองรูปร่าง และขนาดของหนึ่งรูปร่างpaper ปี 2017 อธิบาย encoder-decoder: stack หนึ่งอ่าน source ด้วย unmasked attention, stack ที่สอง generate target แบบ causal, และ attention ชนิดที่สามตรงกลางที่ queries ของ decoder พบ keys ของ encoder นั่นถูกต้องสำหรับการแปล ที่อินพุตและเอาต์พุตเป็นสอง sequences
สิ่งที่ชนะคือครึ่งแบบ decoder-only — stack เดียว causal ทั้งหมด อินพุตและเอาต์พุตอยู่ใน sequence เดียวกัน — และเหตุผลไม่ใช่ความงาม “ทำนาย token ถัดไป” รันได้บน text ใดก็ได้ ดังนั้น training set คืออินเทอร์เน็ต ไม่ใช่ parallel corpus และทุกอย่างกลายเป็นงานเดียวกันนั้น: การแปลคือ document ที่มี source แล้ว target, คำถามและคำตอบของมันคือ document, บทสนทนาที่มี tool call กลางทางคือ document บทที่ 11 ว่าด้วยการผลิตอย่างหลัง Encoders ไม่ได้หายไป — ตัวหนึ่งเห็นอินพุตทั้งหมดพร้อมกัน ซึ่งคือสิ่งที่ต้องการเมื่องานคือการ represent text ไม่ใช่ต่อมัน และนั่นคือเหตุผลที่ retrieval embeddings ของบทที่ 19 มาจาก encoders ไม่ใช่จาก model ที่กำลัง chat
เมื่อกำหนด block แล้ว ขนาด model คือเลขคณิต ต่อ block ด้วย width และการขยายสี่เท่า: สำหรับ พร้อม biases บนทั้งสี่ เหมือน GPT-2 มี — ตารางด้านบนละ bias ออกสามตัว จึงน้อยกว่า 2,304 ต่อ block ที่ ; สำหรับ MLP; สำหรับ LayerNorms สองตัว — บวก token table และสำหรับ absolute positions, สำหรับรูปร่างของ GPT-2 small — , 12 blocks, vocabulary 50,257, context 1024, output layer แชร์ embedding weights:
token embeddings 50,257 x 768 = 38,597,376
position embeddings 1,024 x 768 = 786,432
one block 7,087,872
12 blocks 85,054,464
final LayerNorm 2 x 768 = 1,536
total (weights tied) 124,439,808ซึ่งเป็นขนาดที่เผยแพร่ของ model นั้น สูตรไม่ใช่การประมาณ มันคือ model โปรดสังเกตด้วยว่าเกือบหนึ่งในสามของ small model คือ embedding table นั่นคือเหตุผลที่ vocabulary size เป็นการตัดสินใจทางสถาปัตยกรรม ไม่ใช่ preprocessing — trade-off ที่บทที่ 7 วางไว้
head มองอะไรจริง ๆ
ลิงก์ไปยังส่วน: head มองอะไรจริง ๆPerplexity เป็นตัวเลขเกี่ยวกับ corpus สิ่งที่ head หนึ่งทำเป็นคำถามอีกแบบ และ model ที่ฝึกบน Shakespeare หนึ่งเมกะไบต์เป็นเครื่องมือผิดสำหรับมัน: สิ่งที่ซื่อสัตย์คือการพูดว่า attention map ของ model 500,000-parameter ส่วนใหญ่ตีความไม่ได้ ดังนั้น: ใช้ภาษาที่คำถามมีคำตอบถูก
ภาพประกอบคลาสสิกคือ the animal did not cross the street because it was too tired ที่ it คือ animal เทียบกับ …because it was too wet ที่คำเดียวขยับ referent ไปที่ street นี่คือ Winograd schemas14 — คู่ประโยคที่เหมือนกันทุกอย่างยกเว้นคำเดียว และคำนั้นตัดสินว่าสรรพนามอ้างถึงอะไร
มันยัง แก้ได้ด้วยการโกง ซึ่งเป็นส่วนที่ tutorials ข้าม ถ้าผู้สมัครสองตัวเป็นสัตว์และสถานที่ tired และ wet ระบุ referent ด้วย หมวดหมู่ และ model ที่รู้แค่ว่ามีคำไหนอยู่ก็ทำถูกได้โดยไม่รู้อะไรเกี่ยวกับลำดับ วัดบน version นั้นของงาน ด้วยคู่ animal/place ที่กันไว้:
uniform causal average held-out referent accuracy 100.0 %
one transformer block held-out referent accuracy 91.7 %bag of words ชนะ transformer การสาธิตใด ๆ ที่สร้างบนประโยคนั้นไม่พิสูจน์อะไรเกี่ยวกับ attention
ดังนั้นปิดช่องโหว่: เลือกผู้สมัคร ทั้งสอง จาก pool เดียวกันของ nouns สิบหกคำ ซึ่งตัวใดก็ปรากฏใน slot ใดก็ได้ และแบ่ง adjectives ตาม บทบาท แทนหมวดหมู่ — สี่คำทำให้ it เป็นผู้ข้าม (tired, scared, slow, weak) สี่คำทำให้มันเป็นสิ่งที่ถูกข้าม (wet, wide, busy, steep)
the {x} did not cross the {y} because it was too {adj} , so the {ref} waited .ฝึกเป็น next-token predictor ธรรมดา ให้ score หนึ่งตำแหน่ง — คำหลัง so the — และสร้าง held-out set จากคู่ nouns ที่ลำดับ กลับกัน อยู่ใน training ดังนั้นอะไรก็ตามที่รู้ว่าสอง nouns ไหนอยู่ แต่ไม่รู้ว่าอะไรมาก่อน ต้องตอบกลับด้าน
| model | parameters | held-out | ตั้งชื่อ noun อีกตัว |
|---|---|---|---|
| token ปัจจุบันเท่านั้น | 5,796 | 5.2 % | 5.2 % |
| ค่าเฉลี่ย causal แบบสม่ำเสมอ | 5,796 | 27.9 % | 50.0 % |
| learned attention หนึ่ง head | 18,084 | 35.4 % | 64.6 % |
| สี่ heads | 22,244 | 75.0 % | 15.6 % |
| transformer block หนึ่ง | 55,716 | 92.7 % | 4.2 % |
| transformer blocks สอง | 105,508 | 100.0 % | 0.0 % |
โอกาสสุ่มในสอง nouns ที่มีอยู่คือ 50 % ค่าเฉลี่ยแบบสม่ำเสมอจบที่ 27.9 % และตอบด้วย noun ผิดของคู่นั้นครึ่งหนึ่งพอดี — ลายเซ็นของสิ่งที่รู้ว่ามีคำอะไรอยู่ แต่ไม่รู้อะไรเกี่ยวกับลำดับ ตามที่ shuffle test ทำนายไว้สาม sections ก่อน
ทีนี้ดู map: attention ที่ตำแหน่งซึ่งต้องตั้งชื่อ referent เฉลี่ยเหนือสี่ heads ของแต่ละ block สำหรับสองประโยคที่ต่างกันหนึ่งคำ ค่าเฉลี่ยสม่ำเสมอจะใส่ 0.067 บนแต่ละ token จากสิบห้า token ที่มองเห็น
the animal did not cross the street because it was too tired , so the animal waited .
blk 1 the:0.00 animal:0.70 did:0.00 not:0.00 cross:0.00 the:0.00 street:0.06
because:0.00 it:0.00 was:0.00 too:0.00 tired:0.00 ,:0.05 so:0.00 the:0.19
blk 2 the:0.00 animal:0.00 did:0.00 not:0.00 cross:0.00 the:0.00 street:0.00
because:0.00 it:0.00 was:0.00 too:0.00 tired:1.00 ,:0.00 so:0.00 the:0.00
the animal did not cross the street because it was too wet , so the street waited .
blk 1 the:0.00 animal:0.70 did:0.00 not:0.00 cross:0.00 the:0.00 street:0.06
because:0.00 it:0.00 was:0.00 too:0.00 wet:0.00 ,:0.05 so:0.00 the:0.19
blk 2 the:0.00 animal:0.00 did:0.00 not:0.00 cross:0.03 the:0.00 street:0.49
because:0.00 it:0.00 was:0.00 too:0.20 wet:0.03 ,:0.00 so:0.00 the:0.25Block 1 เหมือนกันในทั้งสองประโยค — 0.70 บน noun แรก ไม่ว่า adjective คืออะไร นั่นไม่ใช่ความล้มเหลวแต่เป็นหลักฐาน: ใน layer แรก query ที่ตำแหน่งหนึ่งเป็นฟังก์ชันของ token และ index ของตำแหน่งนั้นเอง และ the ที่ตำแหน่ง 14 เป็น token เดียวกันในทั้งสองประโยค head ชั้นแรก condition บนคำที่มันยังไม่ได้ fetch ไม่ได้ ดังนั้น block 1 ทำสิ่งเดียวที่มีประโยชน์ที่ทำได้ และลาก noun แรกไปข้างหน้า
Block 2 คือที่ที่ประโยคแยกทางกัน และ row เดียวกันข้าม adjectives ทั้งแปดแสดงกฎที่ model พบ:
| adjective | block 2 บน animal | บน street | บน adjective | คำตอบ |
|---|---|---|---|---|
| tired, scared, slow, weak | 0.000 | 0.000 | 1.000 | animal |
| wet, wide, busy, steep | 0.000 | 0.491 | 0.00–0.03 | street |
สำหรับ crosser-adjective block ที่สองใช้ weight ทั้งหมดบน adjective เพราะคำตอบอยู่ใน residual stream แล้ว — block 1 ใส่มันไว้ตรงนั้น — และสิ่งที่ต้องการมีแค่การยืนยัน สำหรับ crossed-adjective มันไป fetch noun อีกตัวแทน นั่นคือ two-hop circuit: head หนึ่งย้าย candidate ไปข้างหน้า head ใน layer ถัดมาอ่าน token ที่ตัดสินว่าจะเก็บมันหรือไม่ Composition ข้าม layers คือกลไก และนั่นคือเหตุผลที่หนึ่ง block ถึง 92.7 % และสอง block ถึง 100 %
มันยังเป็นรูปร่างของ circuit ที่มีเอกสารดีที่สุดใน models จริง Induction heads — previous-token head ที่ป้อน head ใน layer ถัดไปซึ่งเติม pattern [A][B] … [A] → [B] — คือสิ่งที่งาน interpretability ของ Anthropic ระบุว่าอยู่เบื้องหลังส่วนใหญ่ของ in-context learning และมันก่อตัวในช่วงเวลาที่ระบุได้ระหว่าง pretraining บทนี้ไม่พยายามทำ analysis นั้น: มันถูกมอบหมายต่อ พร้อม papers ทั้งสองใน references เพราะการอ่าน circuits ออกจาก model จริงเป็นสาขาวิจัย ไม่ใช่ section หนึ่ง
สุดท้าย implementation สามสิบบรรทัดข้างต้น พร้อม weights ที่คัดลอกจาก PyTorch เอง:
ours vs nn.MultiheadAttention max |diff| = 1.7881393432617188e-07
ours vs F.scaled_dot_product_attention max |diff| = 1.7881393432617188e-07บนเอาต์พุตที่ mean magnitude คือ 0.159: เลขคณิตเดียวกันในลำดับที่ต่างกัน ที่ precision float32
ต่อไปเรื่องนี้ไปไหน
ลิงก์ไปยังส่วน: ต่อไปเรื่องนี้ไปไหนคุณมีสถาปัตยกรรมที่ทุก model ในส่วนที่เหลือของคอร์สสร้างขึ้นจากมันแล้ว และมันเล็กกว่าชื่อเสียงของมัน: ค่าเฉลี่ยถ่วงน้ำหนักที่น้ำหนักถูกเรียนรู้, MLP ต่อหนึ่งตำแหน่งที่ถือ parameters สองในสาม, normalisations สองตัวและ additions สองครั้ง วางซ้อนกัน
สิ่งที่คุณยังไม่มีคือ model ที่รู้อะไร และการ stack ด้วยตัวมันเองจะไม่แก้เรื่องนั้น สอง blocks บน corpus นี้ถึง training perplexity 14.49 และ validation perplexity 40.57 เทียบกับหนึ่ง block ที่ 18.77 และ 38.07 — capacity มากขึ้น ดีขึ้นบนสิ่งที่มันเคยเห็น แย่ลงบนสิ่งที่ไม่เคยเห็น ซึ่งคือตารางของบทที่ 6 ที่มี transformer อยู่ในนั้น ระยะห่างระหว่าง model นี้กับ models ที่บทที่ 14 ถึง 30 คุยด้วย ไม่ใช่สถาปัตยกรรม มันคือ block เดียวกัน ทำซ้ำมากกว่าหลายครั้ง บน text มากกว่ามหาศาล
ซึ่งทำให้มันเป็นปัญหาบัญชี และบัญชีนั้นประหลาดกว่าที่เห็น text เท่าไร และใครเอามาจากไหน เลขคณิตเท่าไร และคุณประมาณมัน ก่อน ใช้เงินได้อย่างไร ถ้ามี budget คงที่ ทำให้ model ใหญ่ขึ้นดีกว่า หรือให้มันเห็นข้อมูลมากขึ้นดีกว่า — และมีคำตอบที่ถูกต้องไหม หรือมีแค่กระแส บทที่ 10 ตอบทั้งสามด้วยการวัด และติดราคาให้รูปแบบที่ถูกที่สุดและมีประโยชน์ของคำถาม: วันนี้ต้องใช้เงินเท่าไรในการฝึก model แบบ GPT-2 จากศูนย์
แหล่งที่มาและวิธีการ
ลิงก์ไปยังส่วน: แหล่งที่มาและวิธีการคำอธิบายสามชิ้นของเนื้อหานี้ทำหน้าที่ของมันได้ดีกว่าชิ้นนี้ และบทนี้เขียนมาให้อ่านคู่กับพวกมัน The Illustrated Transformer ของ Jay Alammar คือภาพ data flow ที่ดีที่สุดเท่าที่เคยวาด The Annotated Transformer ของ Harvard NLP คือ paper ปี 2017 ที่สอดแทรก code ที่รันได้ทีละบรรทัด Let’s build GPT: from scratch, in code, spelled out ของ Andrej Karpathy สร้าง model เดียวกันสด ๆ ในสองชั่วโมง และบันได ablations ด้านบนคือแกนเดียวกันที่วัดบน corpus อีกชุด สำหรับคำถาม interpretability ที่บทนี้แตะแค่บางส่วน แหล่งหลักคือ Elhage et al., A Mathematical Framework for Transformer Circuits (2021) และ Olsson et al., In-context Learning and Induction Heads (2022) ทั้งคู่จากกลุ่ม interpretability ของ Anthropic
รายการอ้างอิง
ลิงก์ไปยังส่วน: รายการอ้างอิง-
Hochreiter, S. and Schmidhuber, J. Long Short-Term Memory. Neural Computation 9(8), pp. 1735–1780 (1997). ↩
-
Sutskever, I., Vinyals, O. and Le, Q. V. Sequence to Sequence Learning with Neural Networks. arXiv:1409.3215 (2014). encoder-decoder ที่ context vector เดียวเป็นคอขวด ↩
-
Bahdanau, D., Cho, K. and Bengio, Y. Neural Machine Translation by Jointly Learning to Align and Translate. arXiv:1409.0473 (2014). Attention สามปีก่อน transformer ↩
-
Perplexity คือ exponential ของ mean cross-entropy ต่อ token จากบทที่ 8 ตัวเลขทุกตัวที่นี่ใช้ tokenizer เดียวกันและ validation split เดียวกัน ซึ่งเป็นเงื่อนไขเดียวที่ทำให้ perplexities สองค่าเปรียบเทียบกันได้ ↩
-
Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., Kaiser, Ł. and Polosukhin, I. Attention Is All You Need. arXiv:1706.03762 (2017). Section 3.2.1 คือหนึ่งประโยคเกี่ยวกับ ที่บทนี้ใช้หนึ่ง section ในการวัด ↩
-
Shazeer, N., Mirhoseini, A., Maziarz, K., Davis, A., Le, Q., Hinton, G. and Dean, J. Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer. arXiv:1701.06538 (2017). ↩
-
Ba, J. L., Kiros, J. R. and Hinton, G. E. Layer Normalization. arXiv:1607.06450 (2016). แนะนำและวัดในบทที่ 6; ใช้ที่นี่โดยไม่เปลี่ยน ↩
-
Xiong, R., Yang, Y., He, D., Zheng, K., Zheng, S., Xing, C., Zhang, H., Lan, Y., Wang, L. and Liu, T.-Y. On Layer Normalization in the Transformer Architecture. arXiv:2002.04745 (2020). การวิเคราะห์ gradient เบื้องหลัง pre-norm และข้อโต้แย้งว่า warmup เป็นอาการ ↩
-
Su, J., Lu, Y., Pan, S., Murtadha, A., Wen, B. and Liu, Y. RoFormer: Enhanced Transformer with Rotary Position Embedding. arXiv:2104.09864 (2021). ↩
-
Press, O., Smith, N. A. and Lewis, M. Train Short, Test Long: Attention with Linear Biases Enables Input Length Extrapolation. arXiv:2108.12409 (2021). ผล extrapolation ที่ทำซ้ำด้านบน ↩
-
Dao, T., Fu, D. Y., Ermon, S., Rudra, A. and Ré, C. FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness. arXiv:2205.14135 (2022). ↩
-
Shazeer, N. Fast Transformer Decoding: One Write-Head is All You Need. arXiv:1911.02150 (2019). ↩
-
Ainslie, J., Lee-Thorp, J., de Jong, M., Zemlyanskiy, Y., Lebrón, F. and Sanghai, S. GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints. arXiv:2305.13245 (2023). ↩
-
Levesque, H. J., Davis, E. and Morgenstern, L. The Winograd Schema Challenge. KR (2012). โครงสร้างเบื้องหลังประโยค animal / street ที่ทุก attention tutorial ใช้ ↩