[แปล] MoD(Mixture-of-Depths): แนวทางเพื่อเพิ่มประสิทธิภาพการคำนวณของโมเดลภาษาแบบ Transformer และ MoDE(MoD+MoE)
(discuss.pytorch.kr)PyTorchKR
-
ช่วงหลังมานี้มีการใช้แนวทาง MoE(Mixture-of-Experts) กันมากขึ้น โดยเลือกบล็อก 'ผู้เชี่ยวชาญ' หนึ่งตัวหรือมากกว่านั้นจากหลายบล็อกเพื่อประมวลผลโทเคนอินพุต เช่น Jamba, Qwen1.5-MoE หรือ DBRX เป็นต้น แนวทาง MoE เหล่านี้แสดงประสิทธิภาพที่ดีกว่า พร้อมจัดสรรทรัพยากรการคำนวณได้อย่างมีประสิทธิภาพด้วยการควบคุมบางส่วนของ LLM ขนาดใหญ่อย่างไดนามิก
-
หาก MoE เป็นวิธีปรับ 'ความกว้าง(width)' ของโมเดลแบบไดนามิกด้วยการเลือกผู้เชี่ยวชาญบางส่วนจากหลายตัว MoD(Mixture-of-Depths) ที่จะพูดถึงในครั้งนี้คือแนวทางที่ปรับ 'ความลึก(depth)' ของโมเดลแบบไดนามิก กล่าวคือ สำหรับบางโทเคน โมเดลจะไม่คำนวณผ่านทุกเลเยอร์ทั้งหมด แต่จะคำนวณแบบไดนามิกด้วยการข้ามบางเลเยอร์ มาดูกันครับ
MoD(Mixture-of-Depths): แนวทางเพื่อเพิ่มประสิทธิภาพการคำนวณของโมเดลภาษาแบบ Transformer (Mixture-of-Depths: Dynamically allocating compute in transformer-based language models)
บทนำ
โดยทั่วไปแล้ว โมเดล Transformer จะจัดสรรทรัพยากรการคำนวณเท่ากันให้กับทุกส่วนของลำดับอินพุต แต่บทความวิจัย MoD(Mixture-of-Depth) Transformer ที่แนะนำในครั้งนี้พยายามจัดสรรทรัพยากรคอมพิวต์ให้กับตำแหน่งเฉพาะของลำดับใน Transformer แบบไดนามิก และเปลี่ยนการจัดสรรนั้นไปตามแต่ละเลเยอร์ เพื่อใช้กลยุทธ์ Mixture-of-Depths(MoD) นี้ ผู้เขียนใช้กลไก top-k routing ในการตัดสินใจว่าจะประมวลผลโทเคนใด เพื่อควบคุมปริมาณการคำนวณโดยรวม เทคนิคนี้ให้ประสิทธิภาพเทียบเท่าหรือดีกว่าโมเดลเดิม แต่ใช้ FLOPs น้อยกว่ามาก และให้ความเร็วเพิ่มขึ้นสูงสุด 50% ระหว่างการ sampling หลังการฝึก
สถาปัตยกรรม Transformer ที่แนะนำในบทความ Attention is All You Need
โมเดล Transformer และ LLM(Large Language Model) ในยุคหลังมีขนาดและความซับซ้อนเพิ่มขึ้นอย่างต่อเนื่อง โมเดลเหล่านี้ใช้พารามิเตอร์ระดับหลายพันล้านเพื่อเข้าใกล้ความสามารถในการเข้าใจและสร้างภาษาระดับมนุษย์ และด้วยเหตุนี้จึงแสดงประสิทธิภาพที่น่าทึ่ง อย่างไรก็ตาม ความก้าวหน้าเหล่านี้มาพร้อมกับต้นทุนการคำนวณและการใช้พลังงานที่สูงมาก และการเพิ่มขนาดโมเดลยังทำให้เวลาในการฝึกและเวลาในการอนุมานเพิ่มขึ้นอย่างรวดเร็ว
สาเหตุหนึ่งคือ Transformer ทำการคำนวณในปริมาณเท่ากันกับทุกโทเคนของลำดับอินพุต แต่แนวคิดนี้เริ่มต้นจากข้อสังเกตว่าโทเคนทุกตัวอาจไม่ได้ให้ข้อมูลในระดับเท่ากัน บางโทเคนมีบทบาทสำคัญต่อความเข้าใจบริบท ขณะที่บางโทเคนอาจมีความสำคัญน้อยกว่า
MoD Transformer ทำให้โมเดลสามารถโฟกัสทรัพยากรไปยังจุดที่จำเป็นได้ โดยการจัดสรรคำนวณให้แต่ละโทเคนแบบไดนามิก วิธีนี้ช่วยลดต้นทุนการคำนวณโดยรวมของโมเดล และในขณะเดียวกันก็เพิ่มประสิทธิภาพการประมวลผลข้อมูลด้วยการให้ความสนใจกับโทเคนสำคัญมากขึ้น โดยเฉพาะในโมเดลขนาดใหญ่อย่าง LLM แนวทางของ MoD อาจเป็นวิธีสำคัญที่ช่วยประหยัดเวลาและทรัพยากรทั้งในกระบวนการฝึกและการอนุมาน
แนะนำเทคนิค MoD(Mixture-of-Depths)
เทคนิค MoD ผสานกลไก top-k routing สำหรับเลือกแบบไดนามิกว่าในแต่ละเลเยอร์ของ Transformer จะประมวลผลโทเคนใดบ้าง ด้วยวิธีนี้ เฉพาะโทเคนบางส่วนที่ถูกเลือกเท่านั้นที่จะผ่านกระบวนการคำนวณเต็มรูปแบบ ส่วนโทเคนอื่นจะข้ามเลเยอร์นั้นหรือหลายเลเยอร์ไป
ภาพที่ 1 / ซ้าย: ภาพรวมของ MoD(Mixture-of-Depths) Transformer: เช่นเดียวกับโครงสร้าง MoE(Mixture-of-Experts) ระบบจะเลือกเส้นทางการคำนวณผ่านเราเตอร์ แต่ต่างจาก MoE ตรงที่มันตัดสินใจว่าจะคำนวณ standard block(Self-Attention และ MLP) หรือไม่ หากโทเคนอินพุต($X_i$) ไม่เปิดใช้งานการคำนวณเต็มรูปแบบตามการตัดสินใจของเราเตอร์ โทเคนนั้นก็จะไม่ผ่านการคำนวณของเลเยอร์ดังกล่าว
ภาพที่ 1 / ขวา: ผลการตัดสินใจ routing สำหรับลำดับสั้นที่ย่อเหลือ 64 โทเคน (แกน X: ลำดับ, แกน Y: เลเยอร์) สีม่วงหมายถึงมีการคำนวณทั้งหมดในเลเยอร์นั้น และสีส้มหมายถึงข้ามการคำนวณของเลเยอร์นั้น
ตามคำอธิบายในภาพด้านบน MoD ใช้ predictive router ภายในสถาปัตยกรรม Transformer เพื่อกำหนดสำหรับแต่ละโทเคนว่าจะให้ประมวลผลในเลเยอร์นั้นหรือไม่ วิธีนี้ทำให้สามารถรวมทรัพยากรการคำนวณไปที่โทเคนที่ “สำคัญ” กว่าได้
การฝึก MoD Transformer
กระบวนการฝึกของ MoD Transformer โดยพื้นฐานคล้ายกับ Transformer มาตรฐาน โดยลำดับอินพุตจะถูกป้อนเข้าสู่โมเดลและส่งผ่านแต่ละเลเยอร์เพื่อทำการคำนวณที่จำเป็น อย่างไรก็ตาม MoD Transformer มีขั้นตอนเพิ่มเติมคือใช้เราเตอร์เพื่อตัดสินใจว่าแต่ละโทเคนจะเดินตามเส้นทางการคำนวณใด
-
คำนวณค่าน้ำหนักของเราเตอร์: เราเตอร์จะคำนวณค่าน้ำหนักสำหรับแต่ละโทเคนในแต่ละเลเยอร์ของโมเดล ค่าน้ำหนักนี้แสดงปริมาณการคำนวณที่โทเคนนั้นควรได้รับ และอิงตามความสำคัญของโทเคน
-
เลือกโทเคนอันดับบนสุด: เราเตอร์จะเลือกโทเคนจำนวนหนึ่งที่มีค่าน้ำหนักสูงสุดสำหรับแต่ละเลเยอร์ โดยอิงจากค่าน้ำหนักที่คำนวณได้ โทเคนเหล่านี้จะถูกส่งไปยังเส้นทางที่ทำการคำนวณเต็มรูปแบบ
-
จัดสรรเส้นทางการคำนวณ: โทเคนที่ถูกเลือกจะถูกส่งไปยังเส้นทางที่ทำการคำนวณมาตรฐาน(Self-Attention และ MLP) ส่วนโทเคนที่เหลือจะถูกส่งผ่าน residual connection และข้ามไปยังเลเยอร์ถัดไปโดยไม่ต้องคำนวณเพิ่ม
-
คำนวณ loss และ backpropagation: เอาต์พุตของโมเดลจะถูกประเมินผ่านฟังก์ชัน loss สุดท้าย จากนั้น gradient จะถูกส่งย้อนกลับผ่านโมเดลเพื่ออัปเดตน้ำหนัก ในกระบวนการนี้เราเตอร์ก็จะถูกฝึกไปด้วย ทำให้สามารถตัดสินใจ routing ได้มีประสิทธิภาพขึ้นเมื่อเวลาผ่านไป
วิธีการ routing ของ MoD Transformer (Routing Schemes)
การทำ routing คือส่วนสำคัญของ MoD Transformer ผู้เขียนเปรียบเทียบวิธี routing 3 แบบ และพบว่า token routing แบบ Expert-Choice MoD ให้ประสิทธิภาพดีที่สุด ลองมาดูการเปรียบเทียบกับวิธีอื่นที่นำเสนอไว้
Token-choice routing
ใน token-choice routing แต่ละโทเคนจะเลือกเส้นทางที่ตัวเองจะผ่าน โมเดลจะสร้างการกระจายความน่าจะเป็นของเส้นทางการคำนวณต่าง ๆ สำหรับแต่ละโทเคน (เช่น เลเยอร์อื่นหรือบล็อกประมวลผลอื่น) และส่งโทเคนไปยังเส้นทางนั้นตามการกระจายดังกล่าว
ข้อดีของ token-choice routing คือแต่ละโทเคนสามารถเลือกเส้นทางการคำนวณที่เหมาะกับตนเองที่สุดได้ ทำให้มีความยืดหยุ่นสูง นอกจากนี้ โมเดลยังสามารถพิจารณาความสำคัญหรือบริบทของแต่ละโทเคนได้ละเอียดขึ้น จึงเหมาะกับการปรับให้เหมาะกับโทเคนรายตัว
Expert-choice routing
ใน expert-choice routing โมเดลจะเป็นฝ่ายเลือกโดยตรงว่าแต่ละเส้นทาง (หรือ “ผู้เชี่ยวชาญ”) จะประมวลผลโทเคนใด วิธีนี้ทำโดยใช้กลไก top-k เพื่อคัดเลือกโทเคนจำนวนหนึ่งอันดับบนสุดตามค่าน้ำหนักของเราเตอร์ของแต่ละโทเคน
เมื่อใช้ expert-choice routing โทเคนจะสามารถถูกกระจายไปยังแต่ละเส้นทางได้อย่างสมดุล ทำให้ภาระการคำนวณถูกกระจายอย่างสมดุลและใช้ทรัพยากรการคำนวณของโมเดลได้อย่างมีประสิทธิภาพมากขึ้น อีกทั้งเมื่อกำหนดโทเคนอันดับบนสุดได้อย่างชัดเจน ความสามารถในการคาดการณ์และความเสถียรของโมเดลก็จะดีขึ้นด้วย
Expert-choice MoD
Expert-choice MoD คือการนำแนวคิดของ expert-choice routing มาปรับใช้กับโครงสร้างของ MoD Transformer ในวิธีนี้ โมเดลจะเลือกโทเคนอันดับบนสุดสำหรับแต่ละเลเยอร์หรือแต่ละขั้นของการประมวลผล และจะมีเฉพาะโทเคนที่ถูกเลือกเท่านั้นที่ถูกประมวลผลตามเส้นทางที่มีการคำนวณ ส่วนโทเคนที่เหลือจะเดินตามเส้นทางต้นทุนต่ำผ่าน residual connection
แนวทางนี้ช่วยลดการใช้ FLOPs ของโมเดลโดยรวมลงอย่างมาก เพราะมีเพียงโทเคนที่ถูกเลือกเท่านั้นที่ต้องผ่านการคำนวณ อีกทั้งยังสามารถรักษาหรือปรับปรุงประสิทธิภาพของโมเดลได้ โดยรับประกันการคำนวณเต็มเลเยอร์สำหรับโทเคนสำคัญและลดการคำนวณที่ไม่จำเป็นให้น้อยที่สุด สุดท้าย การทำ dynamic routing ผ่านเราเตอร์ยังมีข้อดีที่ทำให้โมเดลจัดสรรทรัพยากรการคำนวณได้อย่างยืดหยุ่นตามลักษณะของลำดับอินพุต
วิธีการ implement routing
การ implement routing สามารถทำได้ผ่าน 3 ขั้นตอนหลักดังนี้:
-
กำหนด token embedding และค่าน้ำหนักของเราเตอร์: สำหรับแต่ละเลเยอร์ของโมเดล จะมีชุด token embedding ของลำดับที่กำหนดคือ $X^i$ สำหรับแต่ละ token embedding $x^l_i$ เราเตอร์จะคำนวณค่าน้ำหนักสเกลาร์ $r^l_i$ ผ่านการแปลงเชิงเส้น เพื่อแสดงความเป็นไปได้ที่โทเคนนั้นจะเข้าร่วมการคำนวณ
-
กำหนดค่าน้ำหนักอันดับบนสุด: จากชุดค่าน้ำหนักของเราเตอร์ของโทเคน $R^l$ จะค้นหาความน่าจะเป็นเปอร์เซ็นไทล์ของค่าน้ำหนักลำดับที่ $\beta$ คือ $P_\beta(R^l)$ โดย $\beta$ เป็นตัวกำหนดสัดส่วนของโทเคนที่โมเดลจะประมวลผลในแต่ละเลเยอร์ ดังนั้น โทเคนที่มีค่าน้ำหนักของเราเตอร์มากกว่า $P_\beta(R^l)$ จะได้เข้าร่วมการคำนวณ
-
เลือกเส้นทางการคำนวณ: แต่ละโทเคนจะถูกเปรียบเทียบค่าน้ำหนักของเราเตอร์ $r^l_i$ กับ $P_\beta(R^l)$ หากมากกว่าหรือเท่ากัน ก็จะผ่านการคำนวณของเลเยอร์นั้น แต่หากน้อยกว่าจะถูกส่งต่อไปยังเลเยอร์ถัดไปโดยตรง วิธีนี้ทำให้คำนวณเฉพาะโทเคนที่ถูกเลือก และให้โทเคนที่เหลือเดินตามเส้นทางที่ไม่ก่อให้เกิดต้นทุนการคำนวณ
เมื่อต้อง implement routing มีประเด็นสำคัญที่ควรคำนึงถึงดังนี้:
-
การตัดสินใจแบบไดนามิกโดยอิงจากค่าน้ำหนัก: กระบวนการ routing จะถูกกำหนดแบบไดนามิกจากค่าน้ำหนักของแต่ละโทเคน ซึ่งสะท้อนความสำคัญของโทเคนนั้น โทเคนสำคัญจะได้รับการคำนวณมากกว่าเพื่อเพิ่มประสิทธิภาพของโมเดล ส่วนโทเคนที่สำคัญน้อยกว่าจะลดต้นทุนผ่าน residual path
-
ประสิทธิภาพการคำนวณและการเพิ่มประสิทธิภาพของโมเดล: ด้วยกลไก routing นี้ MoD Transformer สามารถใช้ทรัพยากรการคำนวณได้อย่างมีประสิทธิภาพ พร้อมรักษาหรือเพิ่มประสิทธิภาพของโมเดล โดยเฉพาะการประมวลผลเฉพาะโทเคนสำคัญในเลเยอร์ที่มีต้นทุนสูงจะช่วยลดการใช้ FLOPs โดยรวม
-
ความเรียบง่ายและประสิทธิภาพของการ implement: เนื่องจาก routing ถูก implement ผ่านการแปลงเชิงเส้นและการคำนวณเปอร์เซ็นไทล์ จึงค่อนข้างเรียบง่ายและมีประสิทธิภาพ ทำให้สามารถจัดสรรทรัพยากรการคำนวณแบบไดนามิกได้ โดยไม่เพิ่มภาระการคำนวณมากนักทั้งในกระบวนการฝึกและการอนุมาน
ตัวอย่างการทำงานของ MoD Transformer
จากสิ่งที่อธิบายมาทั้งหมด ลองดูตัวอย่างการทำงานของ MoD Transformer
ตัวอย่างเช่น สมมติว่าลำดับอินพุตมี 100 โทเคน และเราเตอร์ตั้งค่า จำนวนโทเคนไว้ที่ 10 ในกรณีนี้ ในแต่ละเลเยอร์เราเตอร์จะเลือก 10 โทเคนที่สำคัญที่สุด และมีเพียงโทเคนเหล่านี้เท่านั้นที่จะถูกประมวลผลตามเส้นทางการคำนวณมาตรฐาน
โทเคนที่เหลืออีก 90 ตัวจะข้ามการคำนวณ และถูกส่งตรงไปยังเลเยอร์ถัดไปผ่าน residual connection ด้วยกระบวนการนี้ MoD Transformer จะลดการใช้ FLOPs โดยรวม ขณะเดียวกันก็ยังรับประกันได้ว่าโทเคนสำคัญจะได้รับการคำนวณที่จำเป็น
การเปรียบเทียบประสิทธิภาพของ MoD Transformer
ประสิทธิภาพในการฝึก
การปรับ hyperparameter ให้เหมาะสม: จากการทดลองฝึก MoD Transformer แบบแปรผันที่วาง routing block ความจุ 12.5% สลับกับ attention block เต็มรูปแบบ ผู้วิจัยพบการตั้งค่า hyperparameter ที่เหมาะสมที่สุด ซึ่งให้ประสิทธิภาพดีกว่า baseline ที่ดีที่สุดในการวิเคราะห์แบบ isoFLOP
- ประสิทธิภาพการคำนวณ: MoD บางรูปแบบสามารถทำประสิทธิภาพได้เท่ากันด้วย FLOP ที่น้อยกว่าเมื่อเทียบกับโมเดลเดิม และยังมีความเร็วในการประมวลผลมากขึ้น 66%
การวิเคราะห์ routing
ความ sparse ของการตัดสินใจ routing: เมื่อใช้ routing ที่ capacity 12.5% โทเคนส่วนใหญ่จะเลี่ยงบล็อก และมีเพียงโทเคนสำคัญจำนวนน้อยที่ผ่านบล็อก สิ่งนี้ยืนยันได้จากการกระจายของค่าน้ำหนักเราเตอร์ และยังพบว่าเครือข่ายอาจเลือก routing โดยให้ความสำคัญกับโทเคนบางตัวแตกต่างกันไปตามความลึกของเครือข่าย
ประสิทธิภาพในการอนุมาน
การอนุมานแบบ autoregressive: เมื่อตอนฝึกใช้ top-k routing แบบ non-causal แต่ตอนอนุมานเปลี่ยนเป็นแนวทางเชิงพยากรณ์แบบ causal กลับแทบไม่เกิดการลดลงของประสิทธิภาพ สาเหตุหนึ่งน่าจะเป็นเพราะปัญหาการพยากรณ์นี้เรียนรู้ได้ง่าย และตั้งแต่ช่วงต้นของการฝึกก็ทำความแม่นยำได้เกิน 97% แล้ว
Mixture-of-Depths-and-Experts(MoDE) = MoD + MoE
MoDE(Mixture-of-Depths-and-Experts) หมายถึงการผสานเทคนิค MoD(Mixture-of-Depths) เข้ากับเทคนิค MoE(Mixture of Experts) วิธีนี้มีเป้าหมายเพื่อรวมข้อดีของทั้งสองแนวทางเข้าด้วยกัน เพื่อเพิ่มทั้งประสิทธิภาพการคำนวณและประสิทธิภาพของโมเดล Transformer ไปพร้อมกัน ขณะที่แนวทาง MoD เลือกให้แต่ละโทเคนถูกคำนวณลึกมากหรือน้อย MoE จะประมวลผลโทเคนผ่าน “ผู้เชี่ยวชาญ” ที่เหมาะสมที่สุดจากหลายตัว MoDE จึงรวมสองแนวทางนี้เข้าด้วยกัน ทำให้โทเคนสามารถข้ามบางบล็อกหรือเลือกประมวลผลแบบลึกขึ้นได้อย่างเลือกสรร พร้อมทั้งเลือกวิธีประมวลผลที่เหมาะสมที่สุดจากผู้เชี่ยวชาญหลายราย
วิธีการ implement ของ MoDE
MoDE มีวิธี implement หลัก 2 แบบ: Staged MoDE และ Integrated MoDE
-
Staged MoDE(แบบเป็นขั้นตอน): Staged MoDE จะเริ่มจากใช้เทคนิค MoD เพื่อตัดสินใจเส้นทางการคำนวณของแต่ละโทเคนก่อน จากนั้นจึงใช้เทคนิค MoE เพื่อ route โทเคนที่อยู่บนเส้นทางที่ถูกเลือกไปยัง expert block แต่ละตัว วิธีนี้ทำให้โมเดลสามารถปรับความลึกของการคำนวณก่อน แล้วค่อยเลือกผู้เชี่ยวชาญที่เหมาะสมที่สุดในแต่ละขั้น
-
Integrated MoDE(แบบบูรณาการ): Integrated MoDE จะรวม MoD และ MoE เข้าไว้ในขั้นตอน routing เดียว กล่าวคือ เมื่อต้อง route โทเคน ระบบจะตัดสินใจในครั้งเดียวทั้งความลึกของเส้นทางการคำนวณและผู้เชี่ยวชาญที่จะใช้ประมวลผล วิธีนี้อาจทำให้การ implement เรียบง่ายและมีประสิทธิภาพมากขึ้น และมีข้อดีตรงที่สามารถเลือกทั้งเส้นทางการคำนวณและผู้เชี่ยวชาญที่เหมาะที่สุดให้แต่ละโทเคนได้พร้อมกัน
ข้อดีของ MoDE
- ประสิทธิภาพการคำนวณ: MoDE จัดการต้นทุนการคำนวณโดยรวมของโมเดลได้อย่างมีประสิทธิภาพ ด้วยการตัดสินใจแบบไดนามิกว่าต้องใช้การคำนวณมากน้อยเพียงใดและควรให้ผู้เชี่ยวชาญคนใดประมวลผลสำหรับแต่ละโทเคน
- การเพิ่มประสิทธิภาพของโมเดล: ด้วยการจัดสรรแต่ละโทเคนไปยังเส้นทางการคำนวณและผู้เชี่ยวชาญที่เหมาะสมที่สุด MoDE จึงช่วยเพิ่มประสิทธิภาพของโมเดลให้สูงสุด ซึ่งอาจเป็นประโยชน์อย่างมากเมื่อต้องแก้ปัญหาที่ซับซ้อนหรือจัดการข้อมูลหลายประเภท
- ความยืดหยุ่นและการขยายขนาด: MoDE มอบความยืดหยุ่นในการนำไปใช้กับโครงสร้างโมเดลและงานที่หลากหลาย พร้อมทั้งให้เฟรมเวิร์กที่ขยายต่อได้ ซึ่งช่วยเพิ่มทั้งประสิทธิภาพการคำนวณและประสิทธิภาพของโมเดลไปพร้อมกัน
MoDE ชี้ให้เห็นทิศทางการพัฒนาในอนาคตของโมเดล Transformer และมีส่วนสำคัญต่อการวิจัยที่มุ่งค้นหาวิธีทำให้ต้นทุนการคำนวณต่ำที่สุด ขณะเดียวกันก็เพิ่มประสิทธิภาพของโมเดลให้สูงที่สุด
อ่านเพิ่มเติม
https://arxiv.org/abs/2404.02258
บทความนี้เรียบเรียงจากข้อความที่สรุปด้วยโมเดล GPT ดังนั้นอาจมีบางส่วนที่สรุปต่างจากเนื้อหาหรือเจตนาของต้นฉบับ หากคุณสนใจหัวข้อนี้ ขอแนะนำให้อ่านต้นฉบับควบคู่กันไปด้วย! หากพบส่วนที่แปลกหรือไม่ถูกต้องระหว่างอ่าน รบกวนแจ้งผ่านคอมเมนต์ด้วย
⚠️โฆษณา⚠️: บทความนี้ที่สรุปโดย ชุมชนผู้ใช้ PyTorch เกาหลี มีประโยชน์ไหม? หาก สมัครสมาชิก เราจะส่งบทความสำคัญทางอีเมลให้คุณ! (ค่าเริ่มต้นคือ Weekly แต่ เปลี่ยนเป็น Daily ได้)
ยังไม่มีความคิดเห็น