5 คะแนน โดย GN⁺ 2024-01-04 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ย่อกระบวนการอนุมานของ Transformer ให้เป็นตัวอย่างการแปล Hello World → Hola Mundo เพื่อให้ไล่ตามด้วยมือได้ตั้งแต่การทำ tokenization ไปจนถึง encoder, decoder และการคำนวณความน่าจะเป็นของ token ถัดไป
  • แทนที่จะใช้การตั้งค่าขนาดใหญ่จากบทความต้นฉบับ ตัวอย่างนี้ใช้ embedding 4 มิติ, attention head 2 หัว และชั้น feedforward 8 มิติ เพื่อทำให้ลำดับการคูณเมทริกซ์และ softmax มีขนาดเล็กลง
  • Encoder จะบวก positional encoding เข้ากับ token embedding แล้วผ่าน multi-head self-attention และชั้น feedforward เพื่อสร้าง representation เชิงบริบทของลำดับอินพุต
  • Decoder เริ่มจาก SOS และใช้ทั้ง token ที่สร้างก่อนหน้าและผลลัพธ์จาก encoder โดยใน encoder-decoder attention query คำนวณจาก decoder ส่วน key/value คำนวณจากผลลัพธ์ของ encoder
  • embedding สุดท้ายของ decoder จะผ่านชั้นเชิงเส้นและ softmax เพื่อกลายเป็นความน่าจะเป็นของ token ถัดไป แต่ตัวอย่างนี้ใช้ น้ำหนักแบบสุ่ม จึงไม่ควรคาดหวังคุณภาพการแปลจริง

เป้าหมายและสมมติฐาน

  • ตรวจสอบด้วยตัวอย่าง end-to-end ว่า คณิตศาสตร์ระหว่างการอนุมาน ภายในโมเดล Transformer เชื่อมต่อกันอย่างไร
  • ลดขนาดโมเดลลงมากเพื่อให้ตามการคำนวณด้วยมือได้ง่าย
    • แทนมิติ embedding 512 ในบทความต้นฉบับ ตัวอย่างนี้ใช้ 4 มิติ
    • ใช้ attention head 2 หัว แทน 8 หัวในบทความต้นฉบับ
    • ใช้มิติ feedforward 8 มิติ แทน 2048 ในบทความต้นฉบับ
  • พื้นฐานที่ต้องมีคือพีชคณิตเชิงเส้นระดับพื้นฐาน และการคำนวณส่วนใหญ่ดำเนินไปด้วยการคูณเมทริกซ์
  • โฟกัสที่ว่าการคำนวณจริง ดำเนินไปอย่างไร มากกว่าว่า Transformer “คืออะไร”
  • ควรอ่านคำอธิบายเชิงสัญชาตญาณร่วมกับ The Illustrated Transformer ส่วนบทความต้นฉบับคือ Attention is all you need

การสร้างอินพุตของ encoder

  • Tokenization

    • โมเดล machine learning ประมวลผลตัวเลข ไม่ใช่ข้อความ จึงแปลงข้อความอินพุตเป็น token ID
    • เพื่อความเรียบง่าย ตัวอย่างนี้แบ่ง "Hello World" เป็น token ระดับคำสองคำคือ "Hello" และ "World"
    • วิธี tokenization จริงอาจแบ่งเป็นแบบอิงคำ แบบอิงตัวอักษร หรือแบบอิง subword
    • แบบอิงคำต้องใช้ vocabulary ขนาดใหญ่ และถือว่า "dog" กับ "dogs" เป็น token คนละตัว
    • แบบอิงตัวอักษรมี vocabulary เล็ก แต่อาจมีข้อมูลเชิงความหมายน้อย
    • subword tokenization อยู่กึ่งกลางระหว่างวิธีแบบคำและแบบตัวอักษร และฝึก tokenizer ด้วยกระบวนการเชิงสถิติ
  • Token embedding

    • token ID เองไม่มีความหมาย จึงแปลงแต่ละ token เป็น embedding ซึ่งเป็นเวกเตอร์ขนาดคงที่
    • embedding ในตัวอย่างใช้ค่าที่กำหนดขึ้นเอง
      • Hello -> [1, 2, 3, 4]
      • World -> [2, 3, 4, 5]
    • ใน Transformer จริง การแมป embedding ก็ถูกเรียนรู้เช่นกัน และโมเดลจะเรียนรู้ representation ของ token ให้เหมาะกับงาน
    • embedding ทั้งสองถูกรวมเป็นเมทริกซ์เดียวเพื่อใช้ในการคูณเมทริกซ์ต่อไป
  • Positional encoding

    • embedding อย่างเดียวไม่สามารถบอก ตำแหน่งในประโยค ของคำได้ จึงต้องบวก positional encoding เข้าไป
    • บทความต้นฉบับใช้ positional encoding แบบ sine/cosine คงที่ และตัวอย่างนี้ก็ใช้วิธีเดียวกัน
    • positional encoding ในตัวอย่างคำนวณได้ดังนี้
      • Hello -> [0, 1, 0, 1]
      • World -> [0.84, 0.99, 0, 1]
    • บวก token embedding กับ positional encoding เพื่อสร้างเมทริกซ์อินพุตของ encoder
      • Hello -> [1, 3, 3, 5]
      • World -> [2.84, 3.99, 4, 6]

การคำนวณ Self-attention

  • การสร้าง Q, K, V

    • self-attention คำนวณ query(Q), key(K) และ value(V) จาก input embedding
    • ตัวอย่างนี้ใช้ attention head 2 หัว โดยแต่ละหัวมีเมทริกซ์ WQ, WK, WV ของตัวเอง
    • เมทริกซ์น้ำหนักแต่ละตัวจะแปลง embedding 4 มิติเป็น query/key/value 3 มิติ
    • ในหัวแรก นำเมทริกซ์อินพุตไปคูณกับ WK1, WV1, WQ1 เพื่อได้ K1, V1, Q1
  • สูตร Attention

    • คะแนน attention คำนวณเป็นสี่ขั้นตอน
      • คำนวณ dot product ระหว่าง query กับ key แต่ละตัว
      • หารด้วยรากที่สองของมิติ key
      • แปลงด้วย softmax ให้เป็นน้ำหนักที่เป็นบวกและมีผลรวมเท่ากับ 1
      • ใช้น้ำหนักทำ weighted sum กับเวกเตอร์ value
    • กระบวนการนี้ถูกย่อเป็นสูตรในบทความต้นฉบับ
    • [
    • Attention(Q,K,V) = \text{softmax}\left(\frac{QK^\top}{\sqrt{d}}\right)V
    • ]
    • ในตัวอย่างนี้ เนื่องจากมิติเล็กและค่าเริ่มต้นแบบสุ่ม ผลลัพธ์ softmax จึงเอนเอียงไปใกล้ 0 กับ 1 มาก
    • ค่า dot product ขนาดใหญ่อาจถูกขยายแรงขึ้นใน softmax จึงจำเป็นต้องมีการ scale ด้วยการหารด้วยรากที่สองของมิติ key
    • เพื่อการอธิบาย มีการใช้รูปแบบดัดแปลงที่หารด้วย 30 แทน sqrt(3) ชั่วคราว แต่ไม่ใช่วิธีแก้ระยะยาว
  • ผลลัพธ์ของ multi-head attention

    • นำผล attention ของแต่ละหัวมา concatenate กัน แล้วคูณด้วยเมทริกซ์น้ำหนักที่ถูกเรียนรู้ เพื่อแปลงกลับไปเป็นมิติ embedding
    • ในตัวอย่างนี้รวมผลของสองหัวเป็นเมทริกซ์ 6 มิติ แล้วแปลงเป็นผลลัพธ์ 4 มิติ
    • ผลลัพธ์นี้ถูกส่งต่อไปยังขั้นตอนถัดไปของ encoder block คือชั้น feedforward

ชั้น feedforward และ encoder block

  • ชั้น feedforward

    • หลัง self-attention จะมี feedforward neural network (FFN) อยู่
    • FFN ประกอบด้วยการแปลงเชิงเส้นสองครั้ง และ ReLU activation อยู่ระหว่างกลาง
    • ชั้นเชิงเส้นแรกขยายมิติ และชั้นเชิงเส้นที่สองลดมิติกลับเป็นขนาดเดิม
    • ReLU ทำให้ค่าติดลบกลายเป็น 0 และคงค่าบวกไว้ตามเดิม เพื่อเพิ่มความไม่เป็นเชิงเส้น
    • ในตัวอย่างนี้ขยายอินพุต 4 มิติเป็น 8 มิติ แล้วลดกลับเป็น 4 มิติ
    • [
    • \text{FFN}(x) = \text{ReLU}(xW_1 + b_1)W_2 + b_2
    • ]
  • Encoder block

    • encoder block หนึ่งประกอบด้วย multi-head attention และ FFN
    • บทความต้นฉบับซ้อน encoder 6 ตัว และโค้ดตัวอย่างก็ทำซ้ำ encoder ด้วย n=6
    • หากส่งค่าผ่าน encoder block หลายตัวแบบตรง ๆ ค่าอาจใหญ่เกินไปจนเกิด overflow ในการคำนวณ softmax และได้ nan

Residual connection และ layer normalization

  • ปัญหาค่าพุ่งสูง

    • ในตัวอย่าง เมื่อผ่าน encoder 6 ตัว จะเกิดคำเตือน overflow encountered in exp และ invalid value encountered in divide และผลลัพธ์กลายเป็น nan
    • ปรากฏการณ์ที่ค่ามีขนาดใหญ่เกินไปและยิ่งใหญ่ขึ้นในชั้นถัดไปเป็นปัญหาที่พบได้บ่อยใน deep neural network
    • กรณีที่ gradient ใหญ่เกินไประหว่าง backpropagation เรียกว่า gradient explosion
  • Residual connection

    • residual connection คือการนำอินพุตของชั้นไปบวกกับเอาต์พุตของชั้นนั้น
    • [
    • \text{Residual}(x) = x + \text{Layer}(x)
    • ]
    • ในตัวอย่างนี้ใช้ residual connection กับทั้งผลลัพธ์ attention และผลลัพธ์ FFN
    • residual connection ใช้เพื่อบรรเทาปัญหา vanishing gradient
  • Layer normalization

    • layer normalization ทำ normalization ให้แต่ละมิติของ embedding มีค่าเฉลี่ย 0 และส่วนเบี่ยงเบนมาตรฐาน 1
    • สูตรเป็นดังนี้
    • [
    • \text{LayerNorm}(x) = \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}} \times \gamma + \beta
    • ]
    • (\epsilon) คือค่าขนาดเล็กเพื่อหลีกเลี่ยงปัญหาการหารด้วย 0 เมื่อส่วนเบี่ยงเบนมาตรฐานเป็น 0
    • (\gamma) และ (\beta) เป็นพารามิเตอร์ที่เรียนรู้ได้เพื่อควบคุม scaling และ shifting
    • หลังเพิ่ม residual connection และ layer normalization แล้ว แม้ผ่าน encoder 6 ตัวก็ได้ค่าปกติโดยไม่มี nan

โครงสร้างของ decoder

  • อินพุตของ decoder และวิธีการสร้าง

    • decoder รับผลลัพธ์จาก encoder และลำดับเอาต์พุตที่สร้างมาแล้วจนถึงตอนนี้เป็นอินพุต
    • ระหว่างการอนุมาน จะเริ่มจาก token SOS(start-of-sequence)
    • decoder สร้าง token ทีละตัวแบบ autoregressive
      • รอบที่ 1: รับ SOS เป็นอินพุตแล้วสร้าง "hola"
      • รอบที่ 2: รับ SOS + hola เป็นอินพุตแล้วสร้าง "mundo"
      • รอบที่ 3: รับ SOS + hola + mundo เป็นอินพุตแล้วสร้าง EOS
    • เมื่อสร้าง token EOS(end-of-sequence) แล้วจะหยุด decoding
    • encoder สามารถสร้าง representation ได้ด้วย forward pass เพียงครั้งเดียว แต่ decoder ต้องทำ forward pass หลายครั้ง จึงช้ากว่า
  • องค์ประกอบของ decoder block

    • decoder block ซับซ้อนกว่า encoder block และประกอบด้วยลำดับต่อไปนี้
      • masked self-attention
      • residual connection และ layer normalization
      • encoder-decoder attention
      • residual connection และ layer normalization
      • ชั้น feedforward
      • residual connection และ layer normalization
    • ในตัวอย่างการอนุมาน ใช้ [1, 1, 0, 1] ซึ่งได้จากการบวก positional encoding เข้ากับ embedding ของ SOS
    • ระหว่างการฝึก ใช้ masked self-attention ที่ mask attention score เป็น -inf เพื่อไม่ให้มองเห็น token ในอนาคต

Encoder-decoder attention

  • encoder-decoder attention เป็นขั้นตอนที่ทำให้ decoder โฟกัสกับส่วนที่เกี่ยวข้องของประโยคอินพุต
  • วิธีคำนวณเหมือน self-attention แต่แหล่งอินพุตสำหรับสร้าง Q/K/V ต่างกัน
    • query คำนวณจากผลลัพธ์ของชั้น decoder ก่อนหน้า
    • key และ value คำนวณจาก ผลลัพธ์ของ encoder
  • โครงสร้างนี้ทำให้แต่ละตำแหน่งของ decoder อ้างอิงทุกตำแหน่งในลำดับอินพุตได้
  • มีประโยชน์กับงานที่ token เอาต์พุตต้องขึ้นกับตำแหน่งที่เกี่ยวข้องในประโยคอินพุต เช่น การแปล

การสร้าง token เอาต์พุต

  • Linear layer และ softmax

    • ผลลัพธ์ของ decoder ยังไม่ใช่คำโดยตรง จึงนำ embedding สุดท้ายผ่านชั้นเชิงเส้นเพื่อแปลงเป็นเวกเตอร์ logits ที่มีขนาดเท่ากับ vocabulary
    • ขนาด vocabulary ในตัวอย่างคือ 10 และตัวเลือก token ถัดไปมีดังนี้
      • hello, mundo, world, how, ?, EOS, SOS, a, hola, c
    • logits ผ่าน softmax เพื่อกลายเป็นการแจกแจงความน่าจะเป็นของแต่ละ token
    • ในความน่าจะเป็นของตัวอย่าง "hola" มีค่าสูงสุด จึงถูกเลือกเป็น token ถัดไป
    • วิธีเลือก token ที่มีความน่าจะเป็นสูงสุดเสมอเรียกว่า greedy decoding และไม่ได้ดีที่สุดเสมอไป
    • อ่านรายละเอียดเพิ่มเติมเกี่ยวกับเทคนิคการสร้างได้ใน บทความของ Hugging Face
  • ลูปการสร้างทั้งหมด

    • ขั้นตอนการสร้างทั้งหมดเป็นไปตามลำดับดังนี้
      • แปลงลำดับอินพุตเป็น embedding
      • encoder สร้าง representation เชิงบริบทของอินพุตทั้งหมด
      • decoder เริ่มจาก SOS และใช้ทั้ง token ที่สร้างก่อนหน้าและผลลัพธ์จาก encoder
      • ใช้ linear layer และ softmax กับ embedding สุดท้ายของ decoder
      • เลือก token ถัดไปที่มีความเป็นไปได้สูงสุดแล้วเพิ่มเข้าในลำดับ
      • ทำซ้ำจนกว่า EOS จะออกมาหรือถึงความยาวสูงสุด
    • การรันตัวอย่างสร้าง SOS hola mundo world สำหรับอินพุต hello world
    • เนื่องจากน้ำหนักและ embedding ทั้งหมดถูกใช้แบบสุ่ม ผลลัพธ์จึงไม่ใช่การแปลที่ดี และนี่เป็นพฤติกรรมที่คาดไว้

สรุปและขอบเขต

  • ตัวอย่างนี้เชื่อมองค์ประกอบหลักของ Transformer ได้แก่ embedding, positional encoding, self-attention, multi-head attention, FFN, residual connection, layer normalization, encoder-decoder attention และเอาต์พุต softmax ให้เป็นลำดับเดียว
  • สถาปัตยกรรม Transformer สมัยใหม่เพิ่มเทคนิคต่าง ๆ เข้ามาอีกหลายอย่าง แต่คณิตศาสตร์หลักอิงกับโครงสร้างที่กล่าวถึงในตัวอย่างนี้
  • stack ที่ใช้สามารถแตกต่างกันได้ตามประเภทงาน
    • งานที่เน้นความเข้าใจ เช่น classification อาจวาง linear layer ไว้บน encoder stack
    • งานที่เน้นการสร้าง เช่น translation อาจใช้ทั้ง encoder stack และ decoder stack ร่วมกัน
    • งานสร้างข้อความแบบอิสระอย่าง ChatGPT หรือ Mistral อาจใช้เฉพาะ decoder stack
  • ไม่ครอบคลุมกระบวนการฝึก แต่โฟกัสที่การทำความเข้าใจ คณิตศาสตร์ของการอนุมาน เมื่อนำโมเดลที่มีอยู่มาใช้
  • สำหรับเนื้อหาคณิตศาสตร์ที่เป็นทางการมากขึ้น สามารถดูได้ที่ PDF นี้

1 ความคิดเห็น

 
GN⁺ 2024-01-04
ความคิดเห็นบน Hacker News
  • “ความลึกลับ” ของ Transformer อยู่ตรงที่ แทนที่จะเอาน้ำหนักและค่าคงที่ในแต่ละชั้นมาคูณกันตามลำดับเชิงเส้น มันสร้าง เมทริกซ์ 3 ตัว จากการเอาอินพุตเดียวกันไปคูณกับน้ำหนักที่เรียนรู้มา แล้วเอาเมทริกซ์เหล่านั้นมาคูณกันเอง
    วิธีนี้เพิ่มความขนานและทำงานได้ดี แต่ตัว สูตร attention เองถูกกำหนดตายตัว จึงมีข้อจำกัดมาก
    ถ้าจะพัฒนาต่อไป ดูเหมือนต้องมีวิธีทำให้กราฟการคำนวณเองกลายเป็นพารามิเตอร์ที่เรียนรู้ได้ ผมไม่แน่ใจว่าวิธี gradient แบบดั้งเดิมจะทำได้ไหม เพราะผลแบบ chaotic ที่การเปลี่ยนแปลงเล็ก ๆ นำไปสู่ความต่างของประสิทธิภาพอย่างมาก และภายในอาจต้องใช้รูปแบบอย่าง genetic algorithm หรือ particle swarm optimization

    • คำอธิบายนั้นไม่ถูกเลย จุดพิเศษของ Transformer คือทำให้องค์ประกอบแต่ละตัวในลำดับเลือกส่วนที่สำคัญต่อตัวเองจากองค์ประกอบอื่นทั้งหมด แล้วดึงส่วนนั้นมาคำนวณได้
      ข้อได้เปรียบเชิงทฤษฎีใหญ่เมื่อเทียบกับ RNN คือมันรองรับสิ่งนี้ได้ โดยไม่สูญเสียข้อมูล เพราะแต่ละองค์ประกอบเข้าถึงข้อมูลทั้งหมดขององค์ประกอบอื่นในลำดับ หรือในกรณีตามลำดับเวลา ก็เข้าถึงข้อมูลทั้งหมดขององค์ประกอบก่อนหน้าได้
      ในทางกลับกัน RNN และ “Linear Transformer” จะบีบอัดค่าจากอดีต ดังนั้นโดยทั่วไปองค์ประกอบสุดท้ายของลำดับยาว ๆ จึงเข้าถึงข้อมูลทั้งหมดขององค์ประกอบแรกได้ยาก และเป็นไปไม่ได้ เว้นแต่ internal state จะใหญ่มากจนไม่ทิ้งข้อมูลใดเลย
    • การบอกว่า “ต้องทำให้กราฟการคำนวณทั่วไปขึ้นเป็นพารามิเตอร์ที่เรียนรู้ได้จึงจะพัฒนาต่อไป” เป็นคำพูดที่ค่อนข้างกล้า เพราะที่ผ่านมาเราก็ก้าวหน้าไปมหาศาลแล้ว โดยไม่ต้องเรียนรู้กราฟการคำนวณ
    • วิธีนี้โดยพื้นฐานสามารถเรียนรู้ที่จะละเว้นบางเส้นทางและขยายสิ่งที่สำคัญกว่า จากนั้นก็ตัดเส้นทางที่ทำให้คุณภาพลดลงไม่มากออกได้
      ปัญหาคือสิ่งที่ได้จากตรงนี้มีไม่มากนัก โอเปอเรชันที่ไม่ใช่การคูณเมทริกซ์ มีแนวโน้มว่าจะช้ากว่า หรือเร็วพอ ๆ กันเท่านั้น
    • ผมเห็นด้วยกับประเด็นเรื่องการทำให้กราฟการคำนวณทั่วไปขึ้นเป็นพารามิเตอร์ที่เรียนรู้ได้ มันดูคล้ายกับวิธีที่กระบวนการคิดของมนุษย์ใช้แก้ปัญหาที่อยากให้ LLM แก้ได้ นั่นคือปัญหาที่ใกล้กับการ reasoning จริง ๆ มากกว่า “การประมวลผลภาษา” ที่ Transformer ทำได้ดี
      แต่ถ้าใส่ flow control เข้าไป ก็เสี่ยงจะกลายเป็น Turing machine ในทางปฏิบัติ และเมื่อเป็นแบบนั้น การเรียนรู้ก็จะกลายเป็นปัญหาอย่างที่พูดไว้ ถึงอย่างนั้นก็อาจไม่ใช่ปัญหาที่รับมือไม่ได้ทั้งหมด
    • การจูนไฮเปอร์พารามิเตอร์ ก็เดินไปในทิศทางของการเรียนรู้กราฟการคำนวณอยู่บ้างเช่นกัน เพียงแต่ยังจำกัดมากและต้องใช้การเรียนรู้มากกว่านี้มาก
  • ถ้าต้องการคำอธิบายที่แห้งกว่า เป็นทางการกว่า และกระชับกว่า มี “The Transformer Model in Equations” ของ John Thickstun [0]
    ทั้งหมดใส่ได้ใน หน้าเดียว ด้วยสัญกรณ์คณิตศาสตร์มาตรฐาน
    [0] https://johnthickstun.com/docs/transformers.pdf

    • ดีใจที่ในที่สุดก็มีคำอธิบายแบบนี้ออกมา ผมว่า 7 บรรทัด ของสัญกรณ์คณิตศาสตร์ดีกว่าการคุยเชิงคุณภาพหลายหน้าเยอะ
      บ่อยครั้งนักวิจัย machine learning ดูเหมือนไม่เคยเรียนคณิตศาสตร์มาเลย
    • ระหว่างอ่านเปเปอร์ ผมต้องตัดแปะเนื้อหาแบบนี้ลงโน้ตส่วนตัวอยู่หลายครั้ง และมักไม่เคยมั่นใจว่าไม่ได้พลาดอะไรไป
  • คำอธิบายที่ว่า “เกิด NaN ค่าใหญ่เกินไปจนระเบิดเมื่อส่งต่อไปยัง encoder ถัดไป นี่คือ gradient explosion” เท่าที่ผมเข้าใจนั้นผิด
    ตรงนี้ไม่มีจุดไหนที่คำนวณ gradient เลย ดังนั้นจึงไม่ใช่ gradient explosion
    ปัญหาดูเหมือนอยู่ที่การ implement softmax และวิธี implement softmax ให้เสถียรเชิงตัวเลขอธิบายไว้ที่นี่ [0]
    [0]: https://jaykmody.com/blog/stable-softmax/

    • ใช่ ผมพยายามเชื่อมปัญหาการฝึกที่พบบ่อยอย่าง gradient explosion และ gradient vanishing เข้ากับปัญหาที่ softmax ไวต่อค่าขนาดใหญ่ แต่เห็นด้วยว่ามันทำให้เข้าใจผิดหรือไม่แม่นยำ เลยจะเขียนส่วนนั้นใหม่
      อย่างไรก็ตาม neural network ทั้งระบบก็ไวต่อค่าขนาดใหญ่ ดังนั้น softmax ที่เสถียรเชิงตัวเลขอย่างเดียวแก้ไม่ได้ normalization เป็นหัวใจสำคัญเพื่อให้เครือข่ายทำงานได้
  • บทเรียน Transformer อาจกลายเป็น บทเรียน Monad แบบใหม่ก็ได้ เป็นแนวคิดที่เข้าใจยาก แต่เป็นประเภทที่ต้องฝึกทำตัวอย่างและคลุกคลีกับมันถึงจะเข้าใจ
    เหมือนกับหลาย ๆ เรื่องในวิทยาการคอมพิวเตอร์

    • ทันทีที่คุณเข้าใจ Transformer คุณก็จะอธิบายมันไม่ได้อีกต่อไป
    • Monad เป็นแนวคิดที่ยากเหรอ? Monad ก็แค่ monoid ใน category ของ endofunctor เท่านั้นเอง มีปัญหาอะไร?
    • กำลังรอบล็อกโพสต์ชื่อ “You could have invented transformers” อยู่
  • อ่านไปแค่หกย่อหน้าก็มีคำถามแล้ว
    ใน Hello -> [1,2,3,4] World -> [2,3,4,5] บอกว่าเวกเตอร์เป็นแบบสุ่ม แต่ดูเหมือนมีแพตเทิร์นอยู่ อยากรู้ว่า 2 ที่อยู่ในทั้งสองเวกเตอร์มีความหมายอะไรไหม หรือว่าชุดทั้งหมดเป็นตัวสร้างความเป็นเอกลักษณ์กันแน่

    • การใช้ตัวเลขซ้ำเป็นแค่ผู้เขียนค่อนข้างขี้เกียจมากกว่า คุณสามารถดูว่าเวกเตอร์สองตัวชี้ไปในทิศทางใกล้กันไหม หรือคำนวณมุมเพื่อประเมินความคล้ายกันได้
      ตรงนี้ห่างกันประมาณ 60 องศา และไปในทิศทางเดียวกันอยู่บ้าง แต่เพราะพยายามไม่ใส่เลขลบในตัวอย่าง จึงทำให้เวกเตอร์ดูคล้ายกันกว่าความเป็นจริง
      ข้อเท็จจริงที่ว่าตัวเลขถูกใช้ซ้ำเองไม่มีความหมาย 1 ในตำแหน่งแรกแทบไม่เกี่ยวกับ 1 ในตำแหน่งที่สองเลย เพราะเราไม่ได้ทำ convolution บนเวกเตอร์นี้
    • ไม่ใช่ตัวอย่างที่ดี เวกเตอร์ของแต่ละ token จะถูก สุ่มกำหนดค่าเริ่มต้น โดยแต่ละองค์ประกอบสุ่มจาก normal distribution
      หลังฝึกแล้ว คำที่คล้ายกันจะมี cosine similarity ในระดับหนึ่ง แต่แทบไม่มีกรณีที่ cosine similarity จะสูงเท่า [1,2,3,4] กับ [2,3,4,5]
  • แม้จะไม่ใช่คำถามที่เกี่ยวข้องโดยตรงทั้งหมด แต่กำลังมองหาบทความหรือเปเปอร์ที่อธิบายว่าทำไม Transformer ซึ่งดูเหมือนทำงานเป็นเพียง “ตัวทำนายโทเค็นถัดไป” ถึงสามารถจัดการคำถามแบบต่อไปนี้ได้

    1. กรณีที่ต้องจัดการคำ คำย่อย หรือโทเค็นที่ไม่รู้จัก ซึ่งไม่เคยเห็นในชุดข้อมูลฝึก เช่น การสร้างตารางใน pandas ที่มี "sdsfs_ff", "fsdf_value" เป็นคอลัมน์
    2. กรณีที่สร้างตัวอย่างที่ไม่มีในข้อมูลฝึก แล้วขอให้ LLM ให้เอาต์พุตที่คล้ายกัน
      น่าจะเป็นคำถามที่พบบ่อย แต่หาไม่เจอว่าควรใช้คีย์เวิร์ดอะไรค้นหา ถ้ามีลิงก์ที่ลงลึกเรื่อง positional embedding ด้วยก็ดี และยังไม่ได้คำตอบที่น่าพอใจว่าทำไมถึงใช้ไซน์/โคไซน์ รวมถึงเรื่องการคูณเทียบกับการบวก
    • เดาว่าแม้ตัวอักษรเดี่ยวก็สามารถเข้ารหัสเป็นโทเค็นได้ แต่ในการประมวลผลภายในโมเดลจะใช้ แบนด์วิดท์ มากกว่า และมีความหมายโดยพื้นฐานที่ฝังมาน้อยกว่าเมื่อเทียบกับโทเค็นคำเฉพาะ
      ถ้าโมเดลเห็นว่าจำเป็น ก็สามารถทำซ้ำลำดับที่ไม่รู้จักโดยคัดลอกโทเค็นตัวอักษรเดี่ยว หรือสร้างขึ้นใหม่ได้ถ้าเข้ากับบริบท
    • P(X_1=x_1, X_2=x_2, X_3=x_3) = P(X_3=x_3 | X_1=X_1, X_2=x_2) • P(X_1=x_1, X_2=x_2)
      = P(X_3=x_3 | X_1=X_1, X_2=x_2) • P(X_2=x_2 | X_1=x_1) • P(X_1=x_1)
      กล่าวคือ หากมี การแจกแจงความน่าจะเป็นแบบมีเงื่อนไข ที่ถูกต้องสำหรับโทเค็นถัดไป เมื่อกำหนดโทเค็นก่อนหน้าไว้แล้ว ก็จะได้การแจกแจงความน่าจะเป็นที่ถูกต้องสำหรับลำดับโทเค็นทั้งหมดด้วย
      “การแจกแจงความน่าจะเป็นที่ถูกต้องสำหรับลำดับโทเค็น” หรือการแจกแจงความน่าจะเป็นแบบมีเงื่อนไขที่ถูกต้องของลำดับโทเค็นเมื่อมีเงื่อนไขบางอย่างกำหนดไว้ แทบจะสามารถใช้อธิบายพฤติกรรมอินพุต/เอาต์พุตได้เกือบทุกประเภท
      ดังนั้น การบอกว่า “ทำงานโดยทำนายโทเค็นถัดไป” โดยหลักการแล้วจึงไม่ใช่ข้อจำกัดใหญ่ต่อพฤติกรรมอินพุต/เอาต์พุตที่มันสามารถทำได้
      ไม่ว่ามันจะทำสิ่งที่น่าประทับใจแค่ไหน เอาต์พุตนั้นก็มาจาก P(X_{n+1}=x_{n+1} | X_1=x_1, ..., X_n=x_n) หรือก็คือข้อเท็จจริงที่ว่าเป็น “การทำนายโทเค็นถัดไป” ซึ่งไม่ได้ขัดกัน
    • มันไม่ได้สร้างสตริงที่ตรงเป๊ะจากข้อมูลฝึกขึ้นมาใหม่ แต่สร้าง แพตเทิร์นและแพตเทิร์นของแพตเทิร์น ขึ้นมาใหม่
      การทำนายโทเค็นถัดไปเป็นงานที่มีความฉลาดมากกว่าที่ฟังดู
  • เห็นด้วยกับคำกล่าวที่ว่า “ความซับซ้อนมาจากจำนวนขั้นตอนและจำนวนพารามิเตอร์”
    โมเดล Transformer ที่เรียบง่ายพอให้เราเข้าใจนั้นทำสิ่งที่น่าสนใจไม่ได้ ส่วน Transformer ที่ซับซ้อนพอจะทำสิ่งที่น่าสนใจได้ก็ดูซับซ้อนเกินกว่าที่เราจะเข้าใจ
    อยากลองศึกษา โมเดลขนาดกลาง ที่เรียบง่ายพอให้เข้าใจ แต่ก็ซับซ้อนพอจะทำสิ่งที่น่าสนใจได้

    • ถ้ายังไม่คุ้นอยู่แล้ว งานวิจัยในสาขา mechanistic interpretability อาจน่าสนใจ Neel Nanda ได้รวบรวม/โพสต์แหล่งข้อมูลที่เข้าถึงง่ายเกี่ยวกับหัวข้อนี้ไว้มากมาย: https://www.neelnanda.io/mechanistic-interpretability
    • คิดว่าขอบเขตทั้งสองฝั่งในความเป็นจริงน่าจะมีลักษณะประมาณนี้ พื้นที่ตรงกลางอาจเป็นบริเวณที่ซับซ้อนเกินกว่ามนุษย์จะเข้าใจได้ดีแล้ว แต่ในขณะเดียวกันก็ยังเล็กเกินไปที่จะทำสิ่งที่น่าสนใจได้
  • ถ้าใช้แนวคิดโดยไม่ได้นิยามหรือแนะนำก่อนก็เข้าใจยาก ส่วน Encoder เริ่มต้นทันทีโดยไม่อธิบายว่ามันคืออะไร หรืออยู่ตรงไหนในกระบวนการทั้งหมด
    เข้าใจว่าผู้เขียนพยายามทำอะไร แต่ขาดโครงสร้างพื้นฐานของบทความที่ควรแนะนำไอเดียก่อน อธิบาย แล้วค่อยนำไปใช้
    ถ้าไม่ใช่คนที่กำลังศึกษาเรื่องนี้อยู่แล้วและเข้าใจไปได้ครึ่งหนึ่ง บทความทั้งชิ้นจะรู้สึกสับสน

  • เคยเขียน ANN ตั้งแต่ศูนย์และไม่ได้ใช้ TensorFlow แต่คำอธิบายนี้ก็ยังทำให้สับสนอยู่ดี
    ลองขอให้ ChatGPT อธิบายวิธีเปลี่ยน ANN พื้นฐานให้ไป implement self-attention โดยไม่ใช้คำว่า Matrix หรือ Vector ก็ได้คำอธิบายที่ค่อนข้างเรียบง่ายมา ยังไม่ได้ลอง implement เอง
    ชอบคิดทุกอย่างในมุมของโหนด น้ำหนัก และเลเยอร์มากกว่า เมทริกซ์กับเวกเตอร์ทำให้เชื่อมโยงกับสิ่งที่เกิดขึ้นจริงภายใน ANN ได้ยากขึ้น
    ในวิธีเขียน ANN ที่คุ้นเคย อินพุตแต่ละโหนดเป็นสเกลาร์ แต่อัลกอริทึม forward propagation จะคูณน้ำหนักกับอินพุตทุกโหนดแล้วนำมาบวกกัน จึงดูเหมือนการคูณเวกเตอร์-เมทริกซ์ รู้สึกเหมือนกำลังเข้าหาคำอธิบายเหล่านี้ด้วยกรอบคิดที่ผิด และอาจเป็นเพราะขาดพื้นฐานที่จำเป็นอยู่ก็ได้