2 คะแนน โดย GN⁺ 2024-07-02 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • โปรแกรมดึงข้อมูลที่กำกวมมีแนวโน้มจะกลายเป็น spaghetti code ได้ง่ายเมื่อกฎข้อยกเว้นสะสมมากขึ้น และสามารถย้ายตรรกะแบบอิงสถานะเช่นนี้ไปคิดในรูปของโครงข่ายประสาทแบบเวียนกลับ (RNN) ได้
  • ตัวอย่างการค้นหาการอ้างอิงโค้ด C ในข้อความ code review ถูกสร้างเป็นตัวจำแนกแบบเขียนด้วยมือที่ติดตาม รูปแบบโทเค็น เช่น identifieropen_parenclose_paren ในรูปของสถานะ
  • กฎนี้แสดง precision 100% ในตัวอย่าง แต่พลาดกรณีอย่าง if (err) goto cleanup; ทำให้ recall อยู่ที่ 50% และยิ่งเพิ่มกฎ State กับคำสั่งแตกแขนงก็ยิ่งซับซ้อนขึ้น
  • state machine เดียวกันสามารถเข้ารหัสเป็น hidden state และการคำนวณของเลเยอร์ใน RNN ได้ และหากต้องการให้เรียนรู้ได้ จำเป็นต้องใช้ ReLU·sigmoid รวมถึง weight·bias ที่เรียนรู้ได้ แทนฟังก์ชันชี้วัดแบบไบนารี
  • การใช้งานอย่าง Elman RNN, GRU, LSTM ใน PyTorch และปัญหา vanishing gradient ของลำดับโทเค็นยาว ๆ กลายเป็นข้อจำกัดของการเรียนรู้จริง และกระบวนการกำหนดชุดข้อมูล·label·loss function เองก็ช่วยในการออกแบบกฎแบบเขียนมือด้วย

กระบวนการที่การดึงข้อมูลกำกวมกลายเป็น spaghetti code

  • โปรแกรมเพื่อการวิจัยที่ดึงข้อมูลจากข้อมูลดิบจะมีกฎที่ซับซ้อนขึ้นอย่างรวดเร็ว เมื่อข้อมูลไม่ได้ทำตามสเปกที่ชัดเจนหรือมีรูปแบบเฉพาะตัว
  • ตัวอย่างงานมีทั้งการระบุบริษัทและผู้บริหารจากบทความข่าว, การติด label สัญญาจัดซื้อจัดจ้างภาครัฐตามประเภทบริการ, และการตัดสินว่าข้อความของวิศวกรมีโค้ดโปรแกรมอยู่หรือไม่
  • หากต้องการผลลัพธ์ที่สมบูรณ์แบบ อาจตรวจสอบแต่ละ observation อย่างละเอียดและเขียน unit test สำหรับกรณีตัวแทนได้
    • ทั้ง R และ Python ต่างก็มีไลบรารีทดสอบสำหรับสิ่งนี้
  • ในสถานการณ์ที่ต้องใช้ กฎการตัดสินที่ซับซ้อน เช่น ชื่อเล่น, คำพ้องความหมาย, หรือเส้นแบ่งระหว่างภาษาอังกฤษกับโค้ด กฎแบบเขียนมือจะสั่นคลอนได้ง่าย
  • อัลกอริทึมการฝึกโครงข่ายประสาทเปลี่ยนปัญหาให้เป็นการค้นหาการผสมผสานของกฎเหล่านี้จากข้อมูล แทนที่มนุษย์จะต้องคอยปรับด้วยมือเรื่อย ๆ

ค้นหาการอ้างอิงโค้ดในข้อความ code review

  • เป้าหมายคือการตรวจจับว่าข้อความที่ส่งระหว่าง code review อ้างอิงถึง โค้ดโปรแกรม อย่างชัดเจนหรือไม่
  • สมมติว่า codebase ที่สังเกตเขียนด้วยภาษา C
  • ข้อความตัวอย่างมีการอ้างอิงโค้ดเช่นต่อไปนี้
    • render_ipa_alloc()
    • FTPSACK
    • debug_error()
    • NULL
    • IS_ERROR()
    • aarch64, amd64
    • if (err) goto cleanup;
  • กฎง่าย ๆ ที่เป็นตัวเลือกแต่ละแบบล้มเหลวต่างกันไป
    • กฎที่มองว่าเป็นโค้ดเมื่อมีวงเล็บตามหลังคำ จะจับกรณีอย่าง render_ipa_alloc() ได้ แต่พลาด if (err) goto cleanup;
    • กฎที่มองว่าคำที่เป็นตัวพิมพ์ใหญ่ทั้งหมดคือโค้ด จะจับ FTPSACK และ IS_ERROR() ได้ แต่ false positive กับคำย่ออย่าง AFAICT
    • กฎที่มองว่าคำที่ไม่ใช่ภาษาอังกฤษคือโค้ด อาจ false positive ว่าศัพท์วิศวกรรมหรือชื่อสถาปัตยกรรมเป็นโค้ดได้
  • หากจะปรับปรุงกฎ 2 และกฎ 3 จำเป็นต้องมีรายการคำย่อ·ศัพท์เฉพาะ เช่น AFAICT, LGTM, USD, COVID, aarch64, amd64

ตัวจำแนกที่สร้างด้วย state machine แบบเขียนมือ

  • อัลกอริทึมง่าย ๆ ตัดสินว่าข้อความมีโค้ดหรือไม่ในสองขั้นตอน
    • การเตรียมข้อมูลล่วงหน้า: แปลงข้อความเป็นลำดับโทเค็นที่สะท้อนองค์ประกอบไวยากรณ์ของโค้ด C
    • การอนุมาน: ตรวจสอบว่าลำดับโทเค็นเป็นไปตามกฎหรือไม่
  • Rule 1 ตัดสินว่ารูปแบบ underscore_identifieropen_parenclose_paren เป็นการอ้างอิงโค้ด
  • การใช้งานใน Python เก็บสถานะโทเค็นก่อนหน้าไว้ด้วย data class State
    • previous_was_identifier
    • previous_was_open_paren
    • previous_previous_was_identifier
    • seen_code
  • contains_code วนผ่านโทเค็นและเรียก process จากนั้นคืนค่า state.seen_code ในตอนท้าย
  • process ตั้งค่า seen_code เป็น True หากโทเค็นปัจจุบันคือ close_paren และตัวก่อนหน้าคือ open_paren ส่วนตัวก่อนหน้านั้นเป็น identifier
  • ตัวจำแนกนี้ในตัวอย่าง ไม่มี false positive และมี precision 100% แต่พลาดหลายกรณี ทำให้ recall ค้างอยู่ที่ 50%
  • เมื่อเพิ่ม Rule 2 ฟิลด์ของ State และการแตกแขนง if/elif/else จะเพิ่มขึ้น และยิ่งปรับแต่งกฎมากเท่าไร การบำรุงรักษาก็ยิ่งยากขึ้น

ย้าย state machine ไปเป็น RNN

  • contains_code และ process คือ state machine และ state machine สามารถเข้ารหัสเป็นโครงข่ายประสาทแบบเวียนกลับ (RNN) ได้
  • RNN ประมวลผลลำดับโทเค็นทีละตัว และประมาณความน่าจะเป็นแบบมีเงื่อนไขว่าข้อความมีโค้ดอยู่
  • ค่าที่เทียบได้กับ State ใน Python ถูกแทนด้วย hidden state ของ RNN
    • State_0 คือสถานะเริ่มต้น
    • State_t แต่ละตัวคำนวณโดยป้อนโทเค็นปัจจุบันและสถานะก่อนหน้าเข้าไปในฟังก์ชัน f
    • สถานะสุดท้ายผ่าน output layer g แล้วกลายเป็นผลการจำแนก
  • RNN ตัวอย่างใช้ hidden layer สามชั้น
    • ชั้นแรกเก็บหรือคัดลอกโทเค็นปัจจุบันและสถานะก่อนหน้า
    • ชั้นที่สองตรวจสอบรูปแบบที่สอดคล้องกับ Rule 1
    • ชั้นที่สามจดจำว่าเคยเห็นรูปแบบโค้ดหรือไม่
  • โทเค็นถูกแทนเป็นเวกเตอร์ไบนารีแบบ one-hot
  • หากต้องการเลียนแบบอัลกอริทึมแบบเขียนมือตรง ๆ สามารถใช้ฟังก์ชันชี้วัดแบบไบนารี 1{x > 0} ได้
    • สามารถคง hidden layer ให้เป็นค่าไบนารีได้
    • แต่แทบทุกจุดมีอนุพันธ์เป็น 0 จึงไม่เหมาะกับการเรียนรู้
  • อาจตรวจสอบรูปแบบด้วยผลคูณของ identifier, open_paren, close_paren ก็ได้ แต่ใน hidden layer แบบไบนารีสามารถแสดงการตรวจสอบแบบเดียวกันได้ด้วยผลรวม
  • Giles et al. (1992) ถูกเชื่อมโยงในฐานะกรณีที่ใช้ second-order RNN เพื่อค้นพบ state machine

เปลี่ยนให้เป็นเครือข่ายที่เรียนรู้ได้

  • หากต้องการให้เรียนรู้ได้ ให้ใช้ ReLU แทนฟังก์ชันชี้วัดแบบไบนารี
  • ค่าคงที่ตัวเลขถูกแทนด้วย weight และ bias และ gradient descent จะประมาณพารามิเตอร์เหล่านี้
  • output layer คำนวณค่าความน่าจะเป็นสุดท้ายด้วย sigmoid activation function
  • รูปแบบนี้สามารถป้อนเข้า PyTorch เพื่อฝึกได้ แต่หากฝึกตามเดิม ประสิทธิภาพจะไม่ได้ยอดเยี่ยม
  • หนึ่งในเหตุผลที่ประสิทธิภาพไม่พอคือสถาปัตยกรรมไม่ใช่แบบทั่วไป ทำให้ส่วนที่มากขึ้นของขั้นตอนการฝึกรันอยู่ในโค้ดเชื่อมต่อของ Python และใช้ประโยชน์จากการใช้งานไลบรารี C++ ของ PyTorch ได้น้อยลง

การใช้งาน PyTorch และข้อจำกัดของข้อความยาว

  • torch.nn.RNN ของ PyTorch ให้การใช้งานที่อิงกับ Elman RNN
  • สถาปัตยกรรมตัวอย่างกับ Elman RNN มีวิธีเชื่อมต่อ hidden layer ต่างกัน
    • ในสถาปัตยกรรมตัวอย่าง ชั้นแรกของโทเค็น t รับชั้นที่สามของโทเค็น t-1 เป็นอินพุต และแต่ละชั้นรับอินพุตจากชั้นก่อนหน้าเท่านั้น
    • ใน Elman RNN แต่ละ hidden layer จะรับสถานะจากเวลก่อนหน้าของชั้นเดียวกันเป็นอินพุตด้วย
    • hidden layer ชั้นแรกของ Elman RNN ไม่ได้รับชั้นสุดท้ายจากเวลก่อนหน้าเป็นอินพุต
  • ข้อความ code review จริงอาจยาวได้ และข้อความยาวจะนำไปสู่ลำดับโทเค็นที่ยาว
  • สำหรับลำดับยาว แม้ gradient descent จะทำงานได้ในเชิงทฤษฎี แต่อาจเกิดปัญหาเสถียรภาพเชิงตัวเลขเนื่องจาก vanishing gradient
  • Elman RNN ก็อาจเปราะบางต่อปัญหานี้เช่นกัน และ GRU หรือ LSTM อาจให้ประสิทธิภาพที่ดีกว่าในงานตรวจจับโค้ด

วินัยที่ขับเคลื่อนด้วยข้อมูล

  • RNN เปลี่ยนการผสมผสานกฎที่จัดการด้วยมือได้ยากให้กลายเป็นเป้าหมายของการเรียนรู้ และบังคับให้กำหนดปัญหาให้ชัดเจนขึ้น
  • หากต้องการฝึกเครือข่าย จำเป็นต้องมีสิ่งต่อไปนี้
    • การเลือก ชุดข้อมูลฝึก และชุดข้อมูลตรวจสอบความถูกต้อง
    • การติด label ล่วงหน้า
    • loss function ที่ระบุว่าสิ่งใดที่ตัวจำแนกต้องบรรลุและสิ่งใดที่ต้องหลีกเลี่ยง
  • กระบวนการนี้เผยให้เห็นพื้นที่สีเทาที่ไม่คาดคิด และทำให้เกณฑ์การตัดสินชัดเจนขึ้น
  • วินัยที่ขับเคลื่อนด้วยข้อมูล เช่นนี้มีประโยชน์แม้กับปัญหาที่แก้ด้วยอัลกอริทึมแบบเขียนมือ ไม่ใช่โครงข่ายประสาท

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

 
GN⁺ 2024-07-02
ความคิดเห็นใน Hacker News
  • บทความนี้แทบไม่ได้พูดถึงเรื่อง การทดสอบ หรือการเตรียมข้อมูลฝึกมากนัก ทั้งที่ส่วนนั้นดูจะเป็นแกนสำคัญ
    โค้ดที่เรารู้สึกว่าเข้าใจ คือโค้ดที่เราได้พิสูจน์กับตัวเองแล้วไม่ทางใดก็ทางหนึ่งว่ามันมีคุณสมบัติในการทำให้เป็นทั่วไปกับทุกอินพุตได้ เช่น อัลกอริทึมเรียงลำดับไม่ได้เรียงได้แค่รายการที่เราทดสอบ แต่เรียงรายการใด ๆ ก็ได้
    จุดที่ไม่แน่นอนของโครงข่ายประสาทคือเราไม่รู้ว่ามันจะทำให้เป็นทั่วไปอย่างไร ถ้าอินพุตที่ไม่เคยเห็นต่างไปเพียงเล็กน้อย ก็ไม่มีคุณสมบัติที่รับประกันได้ และอาจเป็นปัญหาที่ตั้งแต่แรกก็ยากจะระบุคุณสมบัติที่ต้องการในเชิงคณิตศาสตร์
    ถ้าสามารถนิยามคุณสมบัติอะไรสักอย่างได้ชัดพอที่จะเขียนเป็น การทดสอบเชิงคุณสมบัติ แบบ QuickCheck ได้ ก็สามารถใช้ความสุ่มสร้างการทดสอบจำนวนมากหรือข้อมูลฝึกจำนวนมากได้
    เริ่มจากตัวอย่างที่ต้องการเพียงหนึ่งตัว แล้วเขียนการทดสอบที่สร้างรูปแบบแปรผันที่เป็นไปได้ของตัวอย่างเชิงบวก/เชิงลบ
    มันไม่ใช่การพิสูจน์ แต่เป็นจุดเริ่มต้น อย่างน้อยถ้าพิสูจน์ได้ เราก็จะรู้ว่าต้องพิสูจน์อะไร
    ถ้ามีสิ่งนี้อยู่ การพึ่งพาโค้ดสปาเกตตีก็ดูคล้ายกับการพึ่งพาโครงข่ายประสาทอยู่พอสมควร ถ้าอยากให้มันมีคุณสมบัติอื่นเพิ่ม ก็แค่เขียนการทดสอบเชิงคุณสมบัติอีกตัวหนึ่ง โครงข่ายประสาทอาจฝึกได้แทนการแก้ด้วยมือ แต่การแก้โค้ดก็มี AI ช่วยได้เหมือนกัน
    ถึงอย่างนั้นก็น่าจะยังเชื่อโค้ดมากกว่า อย่างน้อยก็ยัง ดีบัก ได้

  • ถ้าอ่านในฐานะวิธีสร้างโครงข่ายประสาทเพื่อทำงานเชิงปฏิบัติ ก็เป็นบทความที่น่าสนใจ แต่ถ้าจะทำตามแนวทางนี้ตรง ๆ ในครั้งหน้าที่ต้อง parse อินพุต บอกตามตรงก็ไม่รู้จะพูดว่าอย่างไร
    ผู้เขียนหยิบปัญหายากอย่างการ parse อินพุตตามอำเภอใจที่มีแพตเทิร์นกำหนดแบบหลวม ๆ ขึ้นมา และก็พูดได้ถูกว่ามันมีโอกาสสูงที่จะกลายเป็น โค้ดสปาเกตตี ที่อ่านยาก
    แต่ทางเลือกที่เสนอคือโค้ดที่อ่านยากยิ่งกว่า ถึงขั้นเรายังศึกษากลไกการทำงานของมันกันอยู่ นั่นคือ โครงข่ายประสาท
    เข้าใจได้ แต่ก็ไม่ควรประเมินสิ่งที่ตีความไม่ได้เลยว่าสูงกว่าสิ่งที่แค่ “ไม่สวย” งานบางอย่างอาจเหมาะกับโมเดลแมชชีนเลิร์นนิง แต่ในหลายกรณี ทางเลือกที่ยังอ่านและตรวจสอบได้ว่ามันทำงานอย่างไร แม้จะต้องลงแรงมากกว่า ก็ยังดีกว่าสิ่งที่เป็นไปไม่ได้จะตีความ

    • ผมมองว่าการที่ผู้เขียนยก โค้ดสปาเกตตี ขึ้นมานั้นค่อนข้างเบี่ยงประเด็น ถ้าผลลัพธ์ของอัลกอริทึมไม่ได้ถูกนิยามอย่างแม่นยำเป็นฟังก์ชันของอินพุต แต่เรามีตัวอย่างให้ชี้ได้ นั่นแหละคือจุดที่แมชชีนเลิร์นนิงมีประโยชน์
      สุดท้ายแล้วแมชชีนเลิร์นนิงก็แค่เพิ่มอีกหนึ่งทางเลือก ความเหมาะสมขึ้นอยู่กับผลการประเมิน และระดับของความเป็นกำหนดแน่นอนกับความอธิบายได้ที่ต้องการสำหรับอัลกอริทึมที่เลือก
      จุดที่น่าสังเกตคือ RNN เป็นตัวเลือกที่เหมาะหรือไม่ มันต้องมีการฝึก และอาจต้องใช้ตัวอย่างมากกว่าที่มีอยู่มากทีเดียว แต่ก็ดูพอเป็นไปได้ที่จะสร้างข้อมูลสังเคราะห์ของกรณีบวก/ลบจากกฎที่เรารู้อยู่แล้ว
    • แนวทางโค้ดสปาเกตตีโดยพื้นฐานแล้วคือ ระบบผู้เชี่ยวชาญ จะมองว่าเป็น AI เชิงอัลกอริทึมแบบเก่าก็ได้ นอกเหนือจากโดเมนที่จำกัดแล้ว ระบบแบบนี้แทบไม่เคยทำงานได้ดีจริง เพราะโลกความจริงมันยุ่งเหยิงเกินไป
      ระบบที่เรามองเห็นได้ว่าทำไมมันถึงทำงานแบบนั้นเป็นเรื่องดี แต่ถ้ามันตอบผิดอยู่เรื่อย ๆ ก็ไม่ได้ช่วยอะไร ในการใช้งานจริง หลายครั้งการได้ คำตอบที่ถูกต้อง สำคัญกว่าการรู้ว่ามันไปถึงคำตอบนั้นอย่างไร
    • ฟังดูเหมือนข้อเสนอว่าให้เอาโค้ดสปาเกตตีที่ดูน่าเกลียดไปซ่อนไว้หลัง เมทริกซ์เลขทศนิยมลอยตัว 1000x1000 ที่ดูสะอาดแทน
  • โครงข่ายประสาทมี ทฤษฎีบทการประมาณฟังก์ชันสากล อยู่ ซึ่งบอกว่าสามารถแทนหรือเข้ารหัสฟังก์ชันใด ๆ ได้จนถึงระดับความแม่นยำที่ต้องการ[0]
    แต่ไม่มีทฤษฎีบทที่บอกว่าเราจะเรียนรู้การประมาณแบบนั้นได้ หรือเรียนรู้อย่างไร
    [0] https://en.m.wikipedia.org/wiki/Universal_approximation_theo...

    • แม้การพิสูจน์นั้นจะถูกยกมาพูดถึงบ่อย แต่สิ่งที่มันแสดงจริง ๆ ก็ประมาณว่าโครงข่ายประสาทเทียบเท่ากับ ตารางค้นหา ตารางค้นหาที่มีหน่วยความจำมากพอสามารถประมาณฟังก์ชันใด ๆ ก็ได้
      แต่นั่นยังห่างไกลจากการอธิบายว่าโครงข่ายประสาทที่ใช้งานได้จริงและมีประโยชน์ เช่น convolutional neural network, transformer, LSTM ทำงานอย่างไรในทางปฏิบัติ
    • จริง ๆ แล้วมีอัลกอริทึมมากมายที่ได้รับการพิสูจน์ว่าเป็น ตัวประมาณฟังก์ชันสากล มาตั้งแต่ก่อนโครงข่ายประสาทนานมาก โครงข่ายประสาทไม่ใช่ทั้งสิ่งเดียวหรือสิ่งแรก และในหลายกรณีก็มีวิธีที่เหมาะกว่าโครงข่ายประสาทอย่างมากอยู่ด้วย
    • ไม่ใช่ว่าจะเป็นฟังก์ชันอะไรก็ได้ ยังมีข้อจำกัดกับ ประเภทของฟังก์ชัน ที่ทฤษฎีบทการประมาณสากลใช้ได้
      ที่น่าสนใจคือทฤษฎีบทนี้พูดถึงโครงข่ายชั้นเดียว แต่ในทางปฏิบัติการมีหลายชั้นกลับทำงานได้ดีกว่ามาก
    • มันจำลองได้เฉพาะฟังก์ชันต่อเนื่อง และให้แม่นกว่านั้นคือ ฟังก์ชันต่อเนื่องใด ๆ บนสับเซตกะทัดรัดของ ℝⁿ สามารถถูกประมาณได้ด้วยความแม่นยำตามต้องการ หากมีนิวรอนมากพอ
    • ถ้าอย่างนั้นก็ชวนให้สงสัยว่า การเรียนรู้ หมายถึงอะไรกันแน่
  • เป็นบทความที่ดีมาก และแม้ผมจะยังไม่เข้าใจแนวคิดคณิตศาสตร์ที่ลึกกว่านั้นรอบ ๆ RNN ได้ทั้งหมด แต่มันก็จุดประกายความคิดหลายอย่าง
    มันให้ความรู้สึกคล้ายสิ่งที่กำลังสำรวจอยู่ช่วงนี้ คือการสร้างแอปโดยผูกเข้ากับ อัลกอริทึมอนุมานแบบเดินหน้า ผู้เขียนใช้ RNN ส่วนผมกำลังทำโดยใส่เข้าไปในอัลกอริทึม Rete
    ผมคิดว่ามุมมองที่ให้อินพุตสตริงถูกย่อยทีละตัวอักษรก็ทรงพลังมาก แบบนั้นเราปล่อยให้ตรรกะการอนุมานเป็นหน้าที่ของอัลกอริทึม และเราเขียนเพียงตรรกะอินพุต/เอาต์พุตบาง ๆ ที่เหลือให้อัลกอริทึมจัดการ

  • สิ่งที่ทำให้บทความนี้ดีคือมันอธิบายจากประสบการณ์ตรงในการเรียนรู้ว่า การแปลงฟังก์ชันหนึ่งให้เป็น RNN จริง ๆ แล้วหมายถึงอะไร และเปรียบเทียบสิ่งนั้นกับ RNN แบบ “มีทุกอย่างพร้อมใช้” ที่มากับ PyTorch
    คำถามคือมีการบอกว่าหากต้องการจำลองสถานะ ต้องเพิ่มชั้นซ่อนสามชั้นเข้าไปในเครือข่าย แล้วทำไมต้องสามชั้น เป็นผลจากกฎเฉพาะที่พยายามจะอิมพลีเมนต์ หรือโดยทั่วไปแล้วจำนวนชั้นที่ใช้กับสถาปัตยกรรมนี้เพื่ออิมพลีเมนต์กฎลักษณะนี้มักเป็นเท่านี้อยู่แล้ว อยากรู้ด้วยว่าถ้าเป็นสถาปัตยกรรม Elman จะทำได้ด้วยชั้นที่น้อยกว่านี้หรือไม่

    • สำหรับคำถามแรก การใช้ ชั้นซ่อนสามชั้น ทำให้ชัดขึ้นเล็กน้อยว่าเครือข่ายกำลังทำอะไร แต่ละชั้นทำหน้าที่เป็นหนึ่งขั้นของการคำนวณ
      ชั้นแรกจะรวบรวมสิ่งที่รู้ได้จากโทเค็นปัจจุบันกับสิ่งที่รู้จากการคำนวณของโทเค็นก่อนหน้า ชั้นที่สองจะตรวจว่าตรงตามกฎการตัดสินใจหรือไม่ เพื่อพิจารณาว่าโทเค็นปัจจุบันดูเหมือนโค้ดโปรแกรมหรือเปล่า ชั้นที่สามจะนำการตัดสินใจนั้นไปเปรียบเทียบกับการตัดสินใจเกี่ยวกับโทเค็นก่อนหน้า
      ผมคิดว่าสิ่งนี้น่าจะบีบรวมลงเป็นชั้นซ่อนเดียวได้ด้วย ReLU น่าจะเพียงพอสำหรับจับความไม่เป็นเชิงเส้นนั้น ส่วนเรื่องความสอดคล้องกับสถาปัตยกรรม Elman ผมยังดูไม่มากพอจึงตอบไม่ได้
  • RNN ถูกทรานส์ฟอร์เมอร์ดูดกลืนไปหมดแล้วหรือ? สงสัยว่าควรลืมวิธีจัดการ RNN ไปเลยแล้วโฟกัสแค่ทรานส์ฟอร์เมอร์หรือไม่

    • ถ้าจะทำให้คำถามนี้ซับซ้อนขึ้นอีก ลองดูงานวิจัย “Transformers are RNNs: Fast Autoregressive Transformers with Linear Attention” - https://arxiv.org/pdf/2006.16236
      งานนี้แสดงให้เห็นว่าทรานส์ฟอร์เมอร์ในนิยามแคบแบบหนึ่ง คือทรานส์ฟอร์เมอร์ที่มี causal masking นั้นเทียบเท่ากับ RNN และในทางกลับกันก็ได้
      ในทำนองเดียวกัน Mamba(https://arxiv.org/abs/2312.00752) ซึ่งเป็นสถาปัตยกรรมที่กำลังร้อนแรงในช่วงนี้ ก็มีหน่วยที่เทียบเท่ากับ RNN แบบมีเกต เท่าที่เข้าใจคือด้วยเหตุผลด้านประสิทธิภาพ ตอนเทรนจะใช้ CNN ที่สมมูลกัน และตอนอนุมานจะใช้ RNN
    • ทรานส์ฟอร์เมอร์มี บริบทจำกัด แต่ RNN ไม่มี ในทางปฏิบัติ สัญญาณกราดิเอนต์ของ RNN ถูกจำกัดและลดทอนลงเพราะการย้อนแพร่ผ่านเวลา
      นี่แหละคือข้อได้เปรียบสำคัญของทรานส์ฟอร์เมอร์จริง ๆ ความสัมพันธ์ระยะใกล้กับระยะไกลไม่ได้ยากหรือง่ายต่างกัน แต่ในทางทฤษฎี RNN สามารถจดจำอดีตที่ไกลออกไปได้ไม่สิ้นสุด
    • ถ้าคุณอยากเป็นนักเรียนปริญญาเอกด้านแมชชีนเลิร์นนิงหรือนักวิจัย คำตอบคือไม่ใช่ แต่ถ้าไม่ใช่ก็ใช่
      ตลอด 7 ปีที่ผ่านมา ฉันทำงานเป็นวิศวกรวิจัยด้านแมชชีนเลิร์นนิง/LLM และเคยทำงานในแล็บวิจัยของ FAANG ด้วย แต่แม้จะคิดมาตลอดว่าควรเรียน RNN ก็ไม่เคยได้เรียนจริง ๆ และไม่เคยมีความจำเป็นต้องใช้มัน
  • ถ้าสนใจ ก็น่าลองดู genetic programming ถือเป็นแนวทางที่ง่ายกว่าสำหรับปัญหาแบบเดียวกัน และไม่ต้องใช้คณิตศาสตร์
    มันจะนำโปรแกรมมาผสมใหม่ตามต้นไม้ไวยากรณ์นามธรรม และถ้าให้ฮิวริสติกบางอย่างไว้ ก็จะปรับโปรแกรมให้เหมาะตามเกณฑ์นั้น มนตร์จริง ๆ อยู่ที่ฟังก์ชันฮิวริสติก ซึ่งคุณเลือกได้ว่าจะปรับให้เหมาะกับความเร็ว ความยาวของโปรแกรม การลดโครงสร้างซับซ้อนหรือการเรียกฟังก์ชัน ประสิทธิภาพเครือข่าย หรือการผสมกันของสิ่งเหล่านี้
    https://youtu.be/tTMpKrKkYXo

    • อยากเสริม Humies Awards ที่แสดงผลลัพธ์ระดับแข่งขันกับมนุษย์ด้วย แค่ไล่ดูงานที่ส่งเข้าประกวดก็ได้เรียนรู้มากแล้วว่าอะไรทำได้หรือทำไม่ได้ในสายนี้
      https://www.human-competitive.org/
  • ไม่นานมานี้ฉันเขียนบล็อกโพสต์สำรวจแนวคิดการเชื่อมต่อกับ local LLM สำหรับงานกำกวมแบบนี้
    มันดูสมเหตุสมผลกว่าการไปเขียนโครงข่ายประสาทด้วยมือตรง ๆ ใช้ของอย่าง llama.cpp เพื่อประเมินว่าโมเดลเล็กแก้ปัญหาได้ตรง ๆ ไหม ถ้าไม่ได้ก็ค่อย fine-tune แล้วค่อยเชื่อม llama.cpp แบบโปรแกรมผ่าน wrapper ที่ต้องการ น่าจะใช้งานจริงได้มากกว่า

  • โครงข่ายประสาทแบบวนซ้ำ สามารถใช้กับการคำนวณแบบใดก็ได้ และมีการพิสูจน์ความสมมูลกับเครื่องทัวริงแล้ว แต่สำหรับงานนี้มันไม่สมจริงเลย
    วิธีในโพสต์นี้ดูคล้าย state machine ที่ถูกฝึกมาไม่ทางใดก็ทางหนึ่ง อยากให้โพสต์มีสรุปที่ยาวกว่านี้หน่อย และคำว่า “Python” ก็ดูไม่เกี่ยวอะไรเลย การเรียนรู้ semantic ของ Python จริง ๆ น่าจะค่อนข้างยากเพราะธรรมชาติของภาษา มันไม่ได้มีมาตรฐานชัดเจน แต่เป็นภาษาที่เป็นไปตามสิ่งที่ CPython ทำ

    • บทความ RNN ปี 2015 ของ Karpathy[1] แสดงให้เห็นว่า RNN ที่ฝึกกับงานของ Shakespeare ในระดับตัวอักษร สามารถสร้างข้อความสไตล์ Shakespeare ได้ แม้จะไม่มีความสอดคล้องเชิงเรื่องเล่าแบบ LLM
      ถ้าอย่างนั้นจะมีเหตุผลอะไรที่มันจะจัดการภาษาธรรมชาติที่เป็นทางการอย่างคอมเมนต์รีวิวโค้ดไม่ได้?
      ในกรณีนั้น การอนุมานทำโดยรันด้วยอินพุตสุ่มเพื่อสร้าง “Shakespeare” แบบสุ่ม แต่โครงสร้างและสไตล์ของภาษายังคงเป็นสิ่งที่ RNN เรียนรู้มา และอาจใช้กับงานจัดประเภทได้ด้วย
      1. https://karpathy.github.io/2015/05/21/rnn-effectiveness/
  • ขั้นแรกคอมไพล์ Python ให้เป็นโครงข่ายประสาทก่อน แล้วค่อยบิดมันไปวางทับบน โครงข่ายประสาทแบบทรานส์ฟอร์เมอร์
    จากนั้น Transformer Virtual Machine(TVM) ก็จะรันโปรแกรมใดก็ได้
    ถ้าใช้การถ่ายโอนการเรียนรู้ หรือก็คือเอาน้ำหนักมาวางทับกัน LLM ก็อาจ “เกิดมา” พร้อมกับการเข้ารหัสอัลกอริทึมไว้อย่างลึกซึ้งได้