ml/ library Learn by doing
ALGORITHM 47 · PYTHON / JAVASCRIPT

Elastic Net

ผสมข้อดีของ Ridge และ Lasso

LEARNING LEVEL3
ผสานหลายแนวคิดควรรู้มาก่อน · Ridge Regression และ Lasso Regression
ลองใน Playground

01Overall Concept

OVERALL CONCEPT

ไอเดียหลัก — Elastic Net รวมกติกาของ Ridge และ Lasso ไว้ด้วยกัน จึงทั้งคุมไม่ให้น้ำหนักใหญ่เกินไปและตัดตัวแปรบางตัวออกได้ วิธีนี้เหมาะเมื่อมีตัวแปรจำนวนมากและหลายตัวเล่าเรื่องคล้ายกัน

ลองนึกภาพว่า — เหมือนจัดทีมฟุตบอลภายใต้งบจำกัด เราต้องเลือกผู้เล่นที่จำเป็นเหมือน Lasso และยังต้องแบ่งหน้าที่ไม่ให้คนใดคนหนึ่งแบกทั้งทีมเหมือน Ridge

ตัวอย่างการนำไปใช้ — เลือกคำจากเอกสารจำนวนมาก วิเคราะห์ข้อมูลยีน หรือพยากรณ์จากตารางที่มี feature เป็นกลุ่มและสัมพันธ์กันสูง

02อธิบายภาษาคนเข้าใจง่ายๆ

เล่าแบบไม่ใช้ศัพท์ยาก

Elastic Net คือการพยายามเอาข้อดีของ Ridge กับ Lasso มารวมกัน

มันคิดประมาณว่า

“บางตัวไม่สำคัญก็ตัดออก แต่ตัวที่เหลือก็อย่าให้อิทธิพลแรงเกินไป”

สมมติเรามีข้อมูลจากลูกค้า 200 ตัวแปร และหลายตัวมีความสัมพันธ์กัน เช่น จำนวนครั้งที่เข้าเว็บไซต์ จำนวนครั้งที่เปิดแอป จำนวนวันที่ใช้งานต่อเดือน สิ่งเหล่านี้อาจสะท้อนเรื่องเดียวกันคือ “ระดับ Engagement”

ถ้าใช้ Lasso อย่างเดียว บางครั้งมันอาจเลือกมาแค่หนึ่งตัวแล้วตัดที่เหลือหมด แต่ Elastic Net สามารถเก็บกลุ่มของตัวแปรที่เกี่ยวข้องกันไว้บ้าง พร้อมกับลดตัวที่ไม่สำคัญออก

เพราะแบบนี้ Elastic Net มักเหมาะกับข้อมูลยุคปัจจุบันที่มีฟีเจอร์จำนวนมากและฟีเจอร์เหล่านั้นมักเกี่ยวข้องกัน

ภาพจำ: Lasso เป็นฝ่ายคัดคนออก ส่วน Ridge เป็นฝ่ายควบคุมไม่ให้ใครเสียงดังเกินไป Elastic Net มีทั้งสองฝ่ายอยู่ในห้องเดียวกัน

03How it works

ค่อยๆ ทำไปด้วยกัน ตั้งแต่ข้อมูลแถวแรกจนถึงการตรวจคำตอบ

  1. เริ่มจากคอลัมน์ลูกค้าที่พูดเรื่องคล้ายกัน

    สมมติ X มีจำนวนเข้าเว็บ จำนวนเปิดแอป จำนวนวันที่ใช้งาน และราคาเฉลี่ยที่ซื้อ ส่วน y เป็นยอดใช้จ่ายเดือนถัดไป ใช้ข้อมูลก่อนเดือนที่ต้องการทำนาย แบ่งชุดฝึกและทดสอบตามเวลา แล้วปรับสเกลตัวเลขด้วย StandardScaler ภายใน Pipeline

  2. มีทั้งฝ่ายคัดออกและฝ่ายคุมเสียง

    โมเดลทำนายแบบเส้นตรงเหมือนเดิม แต่ค่าปรับมีทั้งผลรวม |w| แบบ Lasso และผลรวม w² แบบ Ridge ส่วนแรกช่วยให้น้ำหนักบางตัวเป็นศูนย์ ส่วนหลังช่วยคุมน้ำหนักเมื่อหลายคอลัมน์เกี่ยวข้องกัน โมเดลหาน้ำหนักที่ประนีประนอมระหว่างทายให้ใกล้กับไม่ใช้สูตรที่แรงเกินไป

  3. แยกสองปุ่มให้ชัด

    alpha คุมความแรงรวมของค่าปรับ ส่วน l1_ratio คุมสัดส่วนฝั่ง Lasso เช่น 0.2 เอนไปทาง Ridge, 0.8 เอนไปทาง Lasso และ 1 คือ Lasso เริ่มด้วย ElasticNet(alpha=0.1, l1_ratio=0.5, max_iter=10000) ค่าทั้งหมดนี้ยังต้องปรับกับข้อมูลจริง ไม่ควรเปลี่ยน l1_ratio แล้วคิดว่าได้ทดสอบทุกระดับความแรงแล้ว

  4. ฝึกแล้วลองปรับเป็นตาราง

    ใช้ make_pipeline(StandardScaler(), ElasticNet(...)) แล้ว fit ด้วย X_train, y_train ลอง alpha หลายระดับร่วมกับ l1_ratio เช่น 0.2, 0.5, 0.8 โดย cross-validation ภายในชุดฝึก สำหรับข้อมูลตามเวลาให้แบ่ง fold ตามลำดับเวลา จากนั้นนำคู่ค่าที่เหมาะที่สุดไป predict(X_test)

  5. ดูทั้งยอดขายที่ทายและสูตรที่เหลือ

    เปรียบเทียบ RMSE กับ Ridge และ Lasso โดยใช้การแบ่งข้อมูลเดียวกัน พร้อมนับ coef_ ที่ไม่เป็นศูนย์ ถ้าโมเดลเล็กลงมากแต่ error เพิ่มนิดเดียว อาจเหมาะกับงานที่ต้องดูแลระยะยาว แต่ถ้าตัวแปรสำคัญถูกบีบจนทายลูกค้ากลุ่มใหญ่ผิด ลองลด alpha และตรวจข้อมูลแยกตามกลุ่มลูกค้า

เปิดตัวอย่างโค้ดเพื่อลองทำตาม →ตัวอย่างตัวเลขในเรื่องใช้ช่วยอธิบาย ส่วนโค้ดและ Playground ใช้ชุดข้อมูลสาธิตของแต่ละหน้าอ่านเอกสารอ้างอิงของเทคนิคนี้ ↗

ข้อมูล พารามิเตอร์ และภาพรวมการคำนวณ

DATA INX · featuresy · targetX = [เข้าเว็บ, เปิดแอป, วันที่ใช้งาน, …] · y = ยอดใช้จ่าย
CALCULATEElastic Net
alphal1_ratiomax_iter
RESULTnumeric predictionalpha คุมแรงรวม · l1_ratio คุมสัดส่วน Lasso/Ridge
เส้นทางของข้อมูล: จากค่าที่รับเข้า ผ่านการคำนวณด้วยพารามิเตอร์ ไปเป็นผลลัพธ์
INPUT

ข้อมูลที่รับเข้ามา

รับตารางตัวเลข X และค่าเป้าหมาย y เหมาะกับข้อมูลมิติสูงที่ feature หลายตัวมีข้อมูลซ้ำหรือเคลื่อนไปด้วยกัน

X = [เข้าเว็บ, เปิดแอป, วันที่ใช้งาน, …] · y = ยอดใช้จ่าย
PARAMETERS

พารามิเตอร์ที่ใช้

alpha
ความแรงรวมของ regularization ทั้งหมด
l1_ratio
สัดส่วน Lasso ต่อ Ridge ตั้งแต่ 0 ถึง 1
max_iter
จำนวนรอบสูงสุดในการหาน้ำหนักที่ลงตัว
OUTPUT

ผลลัพธ์ที่ได้

ได้ค่าทำนายและ coefficients ที่บางตัวเป็นศูนย์ ขณะที่ feature ที่คล้ายกันยังแบ่งน้ำหนักกันได้

alpha คุมแรงรวม · l1_ratio คุมสัดส่วน Lasso/Ridge
CALCULATION

คำนวณทีละขั้น

  1. 01

    คำนวณ MSE ของคำทำนายจากสมการเส้นตรง

  2. 02

    เพิ่มค่าปรับ L1 สำหรับการตัด feature และ L2 สำหรับบีบน้ำหนักให้เสถียร

  3. 03

    ผสมค่าปรับตาม l1_ratio แล้วปรับ coefficients จน objective ต่ำที่สุด

ควรรู้อีกนิด — มี hyperparameter มากขึ้นและต้องเลือกด้วย cross-validation โดยเฉพาะเมื่อหน่วยของ feature ต่างกัน

04Make it yours

Python · scikit-learn
# ติดตั้ง: pip install numpy scikit-learn matplotlibfrom sklearn.linear_model import ElasticNetfrom sklearn.metrics import mean_squared_error import numpy as npfrom sklearn.model_selection import train_test_split rng = np.random.default_rng(42)X = np.linspace(-1, 1, 60).reshape(-1, 1)y = 0.1 + 0.55*X[:, 0] + 0.55*np.sin(3.4*X[:, 0])y += rng.normal(0, 0.14, len(y))X_train, X_test, y_train, y_test = train_test_split(    X, y, test_size=0.2, random_state=42) model = ElasticNet(alpha=0.12, l1_ratio=0.50, max_iter=10000)model.fit(X_train, y_train)pred = model.predict(X_test)print("RMSE:", mean_squared_error(y_test, pred) ** 0.5)

โค้ดเปลี่ยนตามค่าที่เลือกใน Playground · แต่ละภาษาใช้ข้อมูลตัวอย่างตามที่ระบุในโค้ด

05Learn by playing

ปรับ l1_ratio แล้วสังเกตรูปแบบคำทำนายและตัวชี้วัดที่คำนวณใหม่ทันที

Sample dataset / Curved signal● คำนวณใหม่เมื่อปรับค่า
0 เอนไปทาง Ridge · 1 เอนไปทาง Lasso
ข้อมูลฝึกและผลการทำนายFeature xค่าจริง • / ค่าทำนาย —
RMSE0.363
coefficient ที่ไม่เป็นศูนย์1 / 7
พารามิเตอร์ที่ลอง0.50

Playground เป็น implementation เพื่อการเรียนรู้ที่คำนวณในเบราว์เซอร์ ส่วนโค้ด Python ใช้ scikit-learn จึงอาจให้ค่าต่างกันเล็กน้อยจากรายละเอียดการ optimize และค่าเริ่มต้นของไลบรารี ผลนี้ไม่ใช่ benchmark บนข้อมูลจริง