Courses
ฟังก์ชันกระตุ้น (Activation functions) เป็นตัวตัดสินว่าสัญญาณใดจะผ่านเครือข่ายประสาทและสัญญาณใดจะไม่ผ่าน หากเลือกผิด โมเดลจะเรียนรู้ช้าเกินไปหรือทั่วไปไม่ดีนัก ตลอดหลายปี ReLU เป็นตัวเลือกเริ่มต้นที่สมเหตุสมผลเพราะทำงานเร็วและดีพอสำหรับงานส่วนใหญ่
GELU (Gaussian Error Linear Unit) เข้ามาเปลี่ยนสมมติฐานนั้น ปัจจุบันเป็นฟังก์ชันกระตุ้นที่อยู่เบื้องหลังโมเดลทรงประสิทธิภาพมากที่สุดบางรุ่น รวมถึง BERT และ GPT
ในบทความนี้ จะอธิบายสัญชาตญาณเบื้องหลัง GELU สูตร การเปรียบเทียบกับฟังก์ชันกระตุ้นอื่น ๆ และกรณีการใช้งานจริง
หากเป็นมือใหม่ด้านฟังก์ชันกระตุ้นในแมชชีนเลิร์นนิง แนะนำให้อ่านบล็อกโพสต์ คู่มือสำหรับผู้เริ่มต้นเรื่อง Rectified Linear Unit (ReLU) ของเรา
GELU คืออะไร?
GELU หรือ Gaussian Error Linear Unit เป็นฟังก์ชันกระตุ้นที่ถ่วงน้ำหนักอินพุตตามขนาดของมันด้วยแนวทางที่ลื่นไหลและเชิงความน่าจะเป็น
ฟังก์ชันกระตุ้นส่วนใหญ่มักตัดสินใจแบบปล่อยผ่านหรือบล็อกสัญญาณ ReLU ตัวอย่างเช่น จะตัดค่าติดลบให้เป็นศูนย์และปล่อยค่าที่เหลือผ่านโดยไม่เปลี่ยนแปลง GELU ทำงานต่างออกไป แทนที่จะตัดแบบแข็ง มันจะสเกลอินพุตอย่างลื่นไหลตามความใหญ่หรือเล็กของค่า นั่นหมายความว่าแม้ค่าติดลบเล็ก ๆ ก็ยังมีส่วนต่อผลลัพธ์ได้
ความแตกต่างจาก ReLU คือ GELU มีความลื่นไหลและต่อเนื่องทุกจุด ไม่มีมุมแหลมที่ศูนย์และไม่มีการเปลี่ยนผ่านแบบฉับพลัน ความลื่นไหลนี้มีผลในระหว่างการฝึก เพราะช่วยให้ตัวปรับเหมาะ (optimizer) ได้ข้อมูลเกรเดียนต์ที่สะอาดขึ้นในการทำงาน
สัญชาตญาณเบื้องหลัง GELU
มองว่า GELU เป็นตัวกรองที่ไม่ปฏิบัติต่ออินพุตทุกค่าเหมือนกัน
ReLU ค่อนข้างตรงไปตรงมา — ค่าติดลบใด ๆ ถูกตัดเป็นศูนย์ทุกครั้ง ในทางตรงข้าม GELU จะถามว่า “อินพุตค่านี้มีโอกาสจะเป็นประโยชน์แค่ไหน?” ค่าที่ใหญ่และบวกชัดเจนจะผ่านแทบไม่เปลี่ยนแปลง ค่าที่เล็กหรือติดลบจะถูกสเกลลง ไม่ได้ถูกตัดทิ้งทั้งหมด
ผลลัพธ์คือโค้งลื่นไหลที่กดทับสัญญาณที่ไม่เกี่ยวข้องลง โดยไม่ทิ้งไปเสียทีเดียว
ลองนึกภาพว่ากำลังคัดใบสมัครงานกองหนึ่ง ตัวกรองที่เข้มงวดจะตัดผู้ที่ไม่มีวุฒิการศึกษาออกทั้งหมดโดยไม่มีข้อยกเว้น ตัวกรองที่ฉลาดกว่าจะยังพิจารณาผู้สมัครที่ใกล้เคียง เพราะอาจมีประสบการณ์ที่ชดเชยได้ GELU ทำงานเหมือนตัวกรองที่ฉลาดกว่า มันไม่ตัดแบบแข็ง แต่ชั่งน้ำหนักอินพุตแต่ละค่าโดยดูจากขนาด แล้วตัดสินใจว่าจะให้ผ่านมากน้อยเพียงใด
การสเกลแบบค่อยเป็นค่อยไปและเชิงความน่าจะเป็นนี้คือสิ่งที่ทำให้ GELU แตกต่าง ไม่มีการเปลี่ยนผ่านที่คม และไม่มีนิวรอนตาย — มีเพียงการตัดสินใจแบบลื่นไหลว่าจะปล่อยหรือกดทับสำหรับทุกค่าอินพุต
สูตรของ GELU
สูตรที่แน่นอนของ GELU สร้างบนฟังก์ชันการแจกแจงสะสมแบบเกาสเซียน (Gaussian CDF) เขียนได้ว่า:

ฟังก์ชันการแจกแจงสะสมแบบเกาสเซียน
โดยที่ x คือค่าอินพุต และ Φ(x) คือความน่าจะเป็นที่ตัวแปรสุ่มจากการแจกแจงปกติมาตรฐานจะมีค่าน้อยกว่าหรือเท่ากับ x พูดแบบเข้าใจง่าย Φ(x) บอกว่าค่าอินพุต “ปกติ” หรือคาดหมายได้มากน้อยเพียงใด — และความน่าจะเป็นนั้นเองที่ GELU ใช้ในการสเกลค่าอินพุต
ยิ่งค่าอินพุตสูง Φ(x) ยิ่งเข้าใกล้ 1 หมายความว่าค่าอินพุตผ่านแทบไม่เปลี่ยนแปลง ยิ่งค่าต่ำ Φ(x) ยิ่งเข้าใกล้ 0 หมายความว่าค่าอินพุตจะถูกกดทับลง
ค่าใกล้เคียงที่ใช้ในทางปฏิบัติ
ปัญหาของสูตรที่แน่นอนคือการคำนวณ Φ(x) มีต้นทุนสูง เพราะเกี่ยวข้องกับฟังก์ชัน error function ซึ่งไม่มีรูปปิดที่เรียบง่ายและคำนวณช้าเมื่อทำในสเกลใหญ่
เฟรมเวิร์กดีปเลิร์นนิงจึงใช้ค่าใกล้เคียงนี้แทน:

สูตรค่าใกล้เคียงของ GELU
ค่าใกล้เคียงนี้ใช้ tanh ซึ่งทำงานเร็วและได้รับการสนับสนุนอย่างดีบนฮาร์ดแวร์สมัยใหม่ ผลลัพธ์แทบไม่ต่างจากสูตรจริงในช่วงค่าอินพุตที่สำคัญในทางปฏิบัติ นั่นจึงเป็นเหตุผลที่เฟรมเวิร์กอย่าง PyTorch และ TensorFlow ใช้เป็นค่าเริ่มต้น
แน่นอนว่าไม่จำเป็นต้องท่องจำทั้งสองสูตร แต่การรู้ว่ามีค่าใกล้เคียง — และเพราะเหตุใด — ช่วยให้เข้าใจสิ่งที่เกิดขึ้นจริงเมื่อเรียก GELU ในโค้ด
GELU เทียบกับฟังก์ชันกระตุ้นอื่น
ฟังก์ชันกระตุ้นแต่ละตัวจัดการอินพุตต่างกัน และความแตกต่างเหล่านั้นสะท้อนออกมาในการฝึกโมเดลว่าจะเรียนรู้ได้ดีเพียงใด
ต่อไปนี้คือภาพให้เห็นความแตกต่างก่อนอธิบายด้วยข้อความ:

กราฟเปรียบเทียบ GELU กับฟังก์ชันกระตุ้นอื่น
Sigmoid
Sigmoid บีบค่าอินพุตทั้งหมดให้อยู่ในช่วง 0 ถึง 1 มีความลื่นไหล แต่มีปัญหาที่รู้กันดีคือเกรเดียนต์หาย (vanishing gradients) เมื่ออินพุตมีค่ามากหรือน้อยเกินไป เกรเดียนต์จะเข้าใกล้ศูนย์ ทำให้เลเยอร์ลึก ๆ หยุดเรียนรู้ GELU ไม่มีปัญหานี้เพราะเกรเดียนต์ยังคงมีความหมายในช่วงค่าอินพุตที่กว้างกว่า
Tanh
Tanh คล้าย Sigmoid แต่ศูนย์กลางอยู่ที่ศูนย์ ให้เอาต์พุตระหว่าง -1 ถึง 1 จัดการค่าติดลบได้ดีกว่า Sigmoid แต่ยังเจอปัญหาเกรเดียนต์หายที่ปลายช่วง GELU ให้โค้งเอาต์พุตที่ลื่นไหลกว่าและเอื้อให้การไหลของเกรเดียนต์ดีขึ้นในเครือข่ายลึก
ReLU
ReLU เร็วและเรียบง่าย: ค่าบวกผ่านโดยไม่เปลี่ยน ค่าติดลบถูกตัดเป็นศูนย์ การตัดที่ศูนย์อย่างคมทำให้เกิดปัญหานิวรอนตาย — นิวรอนที่ได้รับค่าติดลบตลอดเวลาจะหยุดอัปเดตโดยสิ้นเชิง GELU หลีกเลี่ยงปัญหานี้ด้วยการสเกลค่าติดลบแทนการตัดทิ้ง
Leaky ReLU
Leaky ReLU แก้ปัญหานิวรอนตายด้วยการปล่อยให้ส่วนเล็ก ๆ ของค่าติดลบผ่าน ถือว่าดีกว่า ReLU แต่การเปลี่ยนผ่านที่ศูนย์ยังคงคม GELU ให้โค้งที่ลื่นไหลกว่าโดยรวม ซึ่งมักทำงานได้ดีกว่าในสถาปัตยกรรมลึกที่คุณภาพของเกรเดียนต์สำคัญกว่า
สรุปแล้ว ความแตกต่างระหว่างฟังก์ชันกระตุ้นทั้งห้านี้มีดังนี้:

ตารางเปรียบเทียบ GELU กับฟังก์ชันกระตุ้นอื่น
เหตุใดจึงใช้ GELU ในทรานส์ฟอร์เมอร์
ทรานส์ฟอร์เมอร์ก็คือเครือข่ายประสาทลึก และยิ่งเครือข่ายลึกมากเท่าไร คุณภาพของเกรเดียนต์ยิ่งสำคัญมากขึ้น
โมเดลอย่าง BERT และ GPT ซ้อนเลเยอร์หลายสิบชั้น ที่ความลึกระดับนั้น ปัญหาเล็ก ๆ ของการไหลของเกรเดียนต์จะทบกัน หากฟังก์ชันกระตุ้นให้เกรเดียนต์ที่ไม่นิ่งหรือเกือบศูนย์ในบางช่วง เลเยอร์แรก ๆ ของเครือข่ายจะแทบไม่อัปเดตระหว่างการฝึก นั่นหมายถึงเรียนรู้ได้น้อย
GELU หลีกเลี่ยงสิ่งนี้ด้วยการทำให้เกรเดียนต์ลื่นไหลและไม่เป็นศูนย์ในช่วงค่าอินพุตที่กว้างกว่า ไม่มีจุดตัดแบบขอบศูนย์ของ ReLU ทำให้ตัวปรับเหมาะได้รับสัญญาณที่สะอาดขึ้นในทุกเลเยอร์ ไม่ใช่แค่ใกล้เอาต์พุต
ยังมีเหตุผลเพิ่มเติมที่ GELU เหมาะกับสถาปัตยกรรมทรานส์ฟอร์เมอร์
ทรานส์ฟอร์เมอร์ประมวลผลอินพุตผ่านกลไก Attention ที่สร้างค่าแอคติเวชันหลากหลายช่วง ทั้งบวกและลบ ฟังก์ชันกระตุ้นที่ลื่นไหลจะรับมือกับช่วงค่าเหล่านี้ได้ดีกว่าฟังก์ชันที่มีการเปลี่ยนผ่านคม
เมื่อมีการตีพิมพ์งาน BERT ครั้งแรก ผู้เขียนเลือกใช้ GELU แทน ReLU และรายงานผลลัพธ์ที่ดีกว่าในชุดวัดผล GPT ก็เลือกทางเดียวกัน ตั้งแต่นั้นมา GELU จึงกลายเป็นฟังก์ชันกระตุ้นเริ่มต้นในสถาปัตยกรรมทรานส์ฟอร์เมอร์ส่วนใหญ่ ไม่ใช่เพราะใหม่ แต่เพราะทำงานได้ดีกว่าในสเกลของโมเดลเหล่านี้
การใช้ GELU ในทางปฏิบัติ
การใช้ GELU ในโมเดลทำได้ง่ายพอ ๆ กับฟังก์ชันกระตุ้นอื่น ๆ ทั้ง PyTorch และ TensorFlow มีรองรับในตัว
PyTorch
ใน PyTorch สามารถใช้ GELU เป็นโมดูลเดี่ยวหรือแทรกในนิยามโมเดล ต่อไปนี้คือตัวอย่างบล็อกฟีดฟอร์เวิร์ดง่าย ๆ ที่ใช้ GELU:
import torch
import torch.nn as nn
class FeedForwardBlock(nn.Module):
def __init__(self, input_dim, hidden_dim):
super().__init__()
self.fc1 = nn.Linear(input_dim, hidden_dim)
self.act = nn.GELU()
self.fc2 = nn.Linear(hidden_dim, input_dim)
def forward(self, x):
return self.fc2(self.act(self.fc1(x)))
block = FeedForwardBlock(input_dim=512, hidden_dim=2048)
x = torch.randn(8, 512)
output = block(x)
nn.GELU() อยู่ระหว่างเลเยอร์เชิงเส้นสองชั้น ตำแหน่งเดียวกับที่พบในซับเลเยอร์ฟีดฟอร์เวิร์ดของทรานส์ฟอร์เมอร์ แอคติเวชันทำงานหลังการฉายครั้งแรกและก่อนครั้งที่สอง
TensorFlow
ใน TensorFlow มี GELU ให้ใช้ผ่าน Keras API:
import tensorflow as tf
from tensorflow import keras
model = keras.Sequential([
keras.layers.Dense(2048, input_shape=(512,)),
keras.layers.Activation("gelu"),
keras.layers.Dense(512)
])
x = tf.random.normal((8, 512))
output = model(x)
ยังสามารถส่งเป็นสตริงให้กับพารามิเตอร์ activation ของเลเยอร์ Dense โดยตรงได้ด้วย:
keras.layers.Dense(2048, activation="gelu")
ทั้งสองวิธีให้ผลลัพธ์เหมือนกัน
ตำแหน่งที่ GELU เหมาะในเครือข่าย
GELU ควรอยู่ตำแหน่งเดียวกับฟังก์ชันกระตุ้นอื่น ๆ — ทันทีหลังการแปลงเชิงเส้นและก่อนเลเยอร์ถัดไป ในทรานส์ฟอร์เมอร์หมายถึงภายในซับเลเยอร์ฟีดฟอร์เวิร์ด ระหว่างการฉายแบบ Dense สองชั้น ในเครือข่ายลึกแบบอื่น ให้วางไว้หลังเลเยอร์เชิงเส้นหรือคอนโวลูชัน แล้วปล่อยให้มันสเกลเอาต์พุตก่อนส่งต่อ
ข้อดีของ GELU
หากอ่านมาถึงตรงนี้ คงทราบจุดเด่นหลักของ GELU เมื่อเทียบกับฟังก์ชันกระตุ้นอื่น ต่อไปนี้คือสรุปสั้น ๆ:
- แอคติเวชันที่ลื่นไหล: GELU ให้โค้งที่ต่อเนื่อง แตกต่างย่อยได้ (differentiable) โดยไม่มีการเปลี่ยนผ่านคม ช่วยให้ตัวปรับเหมาะได้รับข้อมูลที่สะอาดขึ้นในทุกก้าว
- การไหลของเกรเดียนต์ที่ดีกว่า: GELU ไม่ตัดค่าติดลบให้เป็นศูนย์ ทำให้เกรเดียนต์ยังส่งผ่านผ่านนิวรอนที่ได้รับค่าติดลบได้ ลดความเสี่ยงของนิวรอนตายในระหว่างฝึก
- ประสิทธิภาพที่ดีกว่าในโมเดลลึก: ในสถาปัตยกรรมลึกอย่างทรานส์ฟอร์เมอร์ ผลสะสมของเกรเดียนต์ที่ลื่นไหลมักแปลเป็นผลการฝึกที่ดีกว่าเมื่อเทียบกับฟังก์ชันกระตุ้นที่ง่ายกว่า
ข้อจำกัดของ GELU
GELU ไม่ใช่ตัวเลือกที่เหมาะในทุกสถานการณ์ ต่อไปนี้คือข้อจำกัดที่ควรรู้:
-
มีต้นทุนคำนวณสูงกว่า ReLU: GELU เกี่ยวข้องกับทั้ง error function หรือสูตรประมาณด้วย
tanhซึ่งมีต้นทุนมากกว่าการเปรียบเทียบเกณฑ์ง่าย ๆ ของ ReLU ในโมเดลขนาดใหญ่ที่มีหลายเลเยอร์ ต้นทุนนี้อาจเพิ่มขึ้นมาก -
ทำความเข้าใจได้ยากกว่า: ฟังก์ชันอย่าง ReLU เข้าใจง่าย — ค่าบวกผ่าน ค่าติดลบไม่ผ่าน การสเกลเชิงความน่าจะเป็นของ GELU ตีความได้ยากกว่า
-
ไม่จำเป็นเสมอไป: สำหรับเครือข่ายตื้นหรืองานที่ง่ายกว่า GELU มักไม่ให้ข้อได้เปรียบที่มีนัยสำคัญ ReLU หรือ Leaky ReLU มักให้ผลลัพธ์ดีพอด้วยต้นทุนคำนวณที่ต่ำกว่า
สรุปคือ หากสร้างทรานส์ฟอร์เมอร์หรือสถาปัตยกรรมลึกอื่น ๆ GELU เป็นตัวเลือกเริ่มต้นที่แข็งแรง สำหรับกรณีอื่น ควรทำเบนช์มาร์กก่อนจะตัดสินใจใช้
สรุป
GELU ไม่ใช่การอัปเกรดสากล และไม่ใช่คำตอบเดียวที่มาแทน ReLU แต่มันคือการเลือกเชิงออกแบบที่คุ้มค่าในบริบทจำเพาะ — นึกถึงเครือข่ายลึกและโมเดลทรานส์ฟอร์เมอร์
หากทำงานกับ BERT, GPT หรือโมเดลที่อิงทรานส์ฟอร์เมอร์อยู่แล้ว ก็มักใช้ GELU อยู่โดยไม่รู้ตัว ตอนนี้ก็ทราบเหตุผลว่าทำไมมันถึงอยู่ตรงนั้น
สำหรับกรณีอื่น การเลือกฟังก์ชันกระตุ้นคือการชั่งน้ำหนักข้อดีข้อเสีย ไม่มีฟังก์ชันใดชนะทุกครั้ง การเข้าใจว่าแต่ละตัวทำอะไรคือหนทางตัดสินใจด้วยความมั่นใจแทนที่จะทำตามความเคยชิน
หากยังสับสนกับความแตกต่างของฟังก์ชันกระตุ้น ลองลงทะเบียนเรียนใน เส้นทางอาชีพ Machine Learning Engineer ของเรา เพื่อเตรียมความพร้อมสู่อาชีพด้านแมชชีนเลิร์นนิงและ MLOps
FAQs
GELU คือฟังก์ชันกระตุ้นแบบใด?
GELU หรือ Gaussian Error Linear Unit เป็นฟังก์ชันกระตุ้นที่ใช้ในเครือข่ายประสาท แตกต่างจาก ReLU ตรงที่ GELU สเกลอินพุตอย่างลื่นไหลตามขนาดด้วยแนวทางเชิงความน่าจะเป็น ทำให้เหมาะกับสถาปัตยกรรมลึกที่คุณภาพของเกรเดียนต์มีความสำคัญ
GELU แตกต่างจาก ReLU อย่างไร?
ReLU ตัดค่าติดลบทั้งหมดให้เป็นศูนย์ด้วยการตัดที่ศูนย์แบบแข็ง ซึ่งอาจทำให้นิวรอนหยุดเรียนรู้หรือที่เรียกว่านิวรอนตาย GELU หลีกเลี่ยงปัญหานี้ด้วยการค่อย ๆ สเกลค่าติดลบลงแทนการตัดทิ้ง ส่งผลให้การไหลของเกรเดียนต์ลื่นไหลกว่าและประสิทธิภาพดีกว่าในเครือข่ายลึก
ควรใช้ GELU แทนฟังก์ชันกระตุ้นอื่นเมื่อใด?
GELU ทำงานได้ดีที่สุดในสถาปัตยกรรมลึก โดยเฉพาะโมเดลทรานส์ฟอร์เมอร์อย่าง BERT และ GPT สำหรับเครือข่ายตื้นหรืองานที่ง่ายกว่า ต้นทุนคำนวณมักไม่คุ้มกับการเปลี่ยนจาก ReLU เริ่มจาก ReLU เป็นเกณฑ์มาตรฐาน แล้วค่อยทดสอบตัวเลือกอื่นได้เสมอ
ความแตกต่างระหว่างสูตร GELU ที่แท้จริงกับสูตรประมาณคืออะไร?
สูตร GELU ที่แน่นอนใช้ฟังก์ชันการแจกแจงสะสมแบบเกาสเซียน ซึ่งต้องคำนวณ error function — การดำเนินการที่ช้าเมื่อทำในสเกลใหญ่ สูตรประมาณจึงแทนที่ด้วยนิพจน์ที่อิง tanh ซึ่งเร็วกว่าและได้รับการสนับสนุนบนฮาร์ดแวร์สมัยใหม่ ในทางปฏิบัติ ทั้งสองให้ผลลัพธ์แทบเหมือนกัน นั่นจึงเป็นเหตุผลที่เฟรมเวิร์กส่วนใหญ่ใช้สูตรประมาณเป็นค่าเริ่มต้น
GELU ใช้ได้ทั้งใน PyTorch และ TensorFlow หรือไม่?
มีรองรับทั้งสองเฟรมเวิร์ก ใน PyTorch สามารถใช้ nn.GELU() เป็นโมดูลภายในนิยามโมเดลได้ ใน TensorFlow สามารถส่งสตริง "gelu" ให้กับอาร์กิวเมนต์ activation ของเลเยอร์ใดก็ได้ หรือใช้ keras.layers.Activation("gelu")