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

Multilayer Perceptron

ประกอบฟังก์ชันเล็ก ๆ ให้เรียนรู้รูปทรงซับซ้อน

LEARNING LEVEL2
ต่อยอดโดยตรงควรรู้มาก่อน · Perceptron, Linear Regression และ gradient descent
ลองใน Playground

01Overall Concept

OVERALL CONCEPT

ไอเดียหลัก — Multilayer Perceptron หรือ MLP เป็นโครงข่ายของเครื่องคิดเลขเล็ก ๆ หลายชั้น แต่ละตัวรับตัวเลข คูณน้ำหนัก แล้วส่งผลต่อไป ชั้นแรกเรียนรู้รูปแบบง่าย ๆ และชั้นถัดไปนำรูปแบบเหล่านั้นมาประกอบเป็นสิ่งที่ซับซ้อนขึ้น

ลองนึกภาพว่า — เหมือนทีมวาดภาพ ชั้นแรกสังเกตเส้นและมุม ชั้นต่อมารวมเส้นเป็นรูปตาและหู แล้วชั้นสุดท้ายรวมส่วนต่าง ๆ เพื่อเดาว่าเป็นแมวหรือสุนัข ทุกคนค่อย ๆ ปรับงานจากคำตอบที่ผิด

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

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

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

MLP คือ Neural Network แบบพื้นฐาน

ให้คิดว่าข้อมูลเดินผ่านคนหลายแถว

แถวแรกดูข้อมูลดิบ เช่น

อายุ รายได้ จำนวนครั้งที่ซื้อ จำนวนครั้งที่เข้าเว็บ

แต่ละคนในแถวแรกพยายามจับ pattern บางอย่าง

แล้วส่งผลให้แถวถัดไป

แถวถัดไปอาจเริ่มมอง pattern ที่ซับซ้อนขึ้น เช่น

“คนรายได้สูง + เข้าเว็บบ่อย”

อีกชั้นอาจมองว่า

“ลูกค้าที่ Engagement สูงและมีกำลังซื้อ”

สุดท้ายจึงตอบว่า

มีโอกาสซื้อสินค้า 87%

สิ่งสำคัญของ Neural Network คือเราไม่จำเป็นต้องกำหนดความสัมพันธ์ทุกอย่างด้วยมือ มันสามารถเรียน representation ภายในของมันเอง

ข้อดีคือจับความสัมพันธ์ซับซ้อนได้มาก

ข้อเสียคืออธิบายยากกว่า Regression หรือ Decision Tree และมักต้องการข้อมูลและการปรับแต่งมากกว่า

และนี่เป็นต้นตระกูลเดียวกับ Deep Learning เพียงแต่ Neural Network สมัยใหม่มักใหญ่และซับซ้อนกว่า MLP ธรรมดามาก

ภาพจำ: ข้อมูลผ่านทีมวิเคราะห์หลายชั้น แต่ละชั้นตีความต่อจากชั้นก่อน

03How it works

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

  1. เริ่มจากลูกค้าหนึ่งคนต่อหนึ่งแถว

    X อาจเป็นจำนวนเข้าเว็บ จำนวนซื้อ และรายได้ ส่วน y เป็นซื้อ/ไม่ซื้อสำหรับ MLPClassifier หรือยอดใช้จ่ายสำหรับ MLPRegressor โค้ดในหน้านี้สาธิตแบบ regression ด้วยข้อมูลตัวเลขจำลอง เมื่อนำไปใช้ให้เลือกชนิดโมเดลตามคำตอบที่ต้องการ แบ่ง train/test และปรับสเกล X ภายใน Pipeline

  2. ข้อมูลเดินผ่านห้องคำนวณหลายชั้น

    แต่ละ neuron รับค่าหลายทาง คูณด้วยน้ำหนัก บวก bias แล้วผ่าน activation เช่น ReLU ก่อนส่งต่อ เช่น hidden_layer_sizes=(32, 16) หมายถึงชั้นซ่อนสองชั้นขนาด 32 และ 16 ไม่ใช่จำนวนคอลัมน์ข้อมูล ชั้นรับข้อมูลมีขนาดตามจำนวน feature ส่วนชั้นซ่อนเราเป็นคนกำหนด

  3. ทายก่อนแล้วไล่แก้ย้อนกลับ

    forward pass สร้างคำทำนาย จากนั้นคำนวณ loss เทียบ y จริง และใช้ backpropagation หาว่าน้ำหนักแต่ละตัวควรขยับทิศไหน optimizer เช่น Adam ใช้ข้อมูลนี้ปรับน้ำหนัก ทำซ้ำหลาย epoch ซึ่งหนึ่ง epoch คือการผ่านชุดฝึกหนึ่งรอบ กลไกนี้ทำให้ชั้นต่างๆ ค่อยๆ เรียนรูปแบบร่วมกัน

  4. เริ่มเครือข่ายเล็กแล้วค่อยเพิ่ม

    สำหรับยอดใช้จ่ายลอง make_pipeline(StandardScaler(), MLPRegressor(hidden_layer_sizes=(32,), learning_rate_init=0.001, max_iter=1000, early_stopping=True, random_state=42)) แล้ว fit(X_train, y_train) hidden_layer_sizes คุมความจุ learning_rate_init คุมขนาดก้าว alpha คุมค่าปรับน้ำหนัก ส่วน max_iter จำกัดจำนวน epoch และ early_stopping กันข้อมูลฝึกบางส่วนมาดูว่าควรหยุดหรือยัง

  5. ดูการเรียนและการทำนายคู่กัน

    predict ให้ตัวเลขหรือคลาสตามรุ่น และ MLPClassifier มี predict_proba ตรวจ loss_curve_ ว่าการเรียนยังแกว่งหรือไม่ พร้อมเทียบ MAE/RMSE หรือ confusion matrix บน test ถ้า train ดีแต่ test แย่ ลองลดขนาดเครือข่ายหรือเพิ่ม alpha ก่อน ถ้ามีคำเตือนยังไม่ลู่เข้า ตรวจสเกลและ learning rate แทนการเพิ่มจำนวนชั้นทันที

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

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

DATA INX · featuresy · targetX = [เข้าเว็บ, จำนวนซื้อ, รายได้] · y = ยอดใช้จ่ายสำหรับ regression
CALCULATEMultilayer Perceptron
hidden_layer_sizesactivationlearning_rate_init
RESULTnumeric predictionMLPRegressor → ยอดใช้จ่าย · MLPClassifier → คลาส/โอกาส
เส้นทางของข้อมูล: จากค่าที่รับเข้า ผ่านการคำนวณด้วยพารามิเตอร์ ไปเป็นผลลัพธ์
INPUT

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

รับ X ตัวเลขที่ปรับสเกลแล้ว จำนวน feature กำหนดขนาดชั้นรับข้อมูล ส่วน hidden_layer_sizes กำหนดชั้นซ่อนแยกกัน เลือก y ตัวเลขสำหรับ Regressor หรือป้ายคลาสสำหรับ Classifier

X = [เข้าเว็บ, จำนวนซื้อ, รายได้] · y = ยอดใช้จ่ายสำหรับ regression
PARAMETERS

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

hidden_layer_sizes
จำนวนชั้นซ่อนและจำนวน neuron ในแต่ละชั้น
activation
ฟังก์ชันไม่เชิงเส้น เช่น relu หรือ tanh
learning_rate_init
ขนาดก้าวในการปรับน้ำหนักแต่ละครั้ง
OUTPUT

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

ได้ค่าทำนายหรือ probability พร้อมเมทริกซ์น้ำหนักของทุกชั้น ซึ่งรวมกันเป็นรูปแบบ nonlinear

MLPRegressor → ยอดใช้จ่าย · MLPClassifier → คลาส/โอกาส
CALCULATION

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

  1. 01

    ทำ forward pass: คูณ input ด้วยเมทริกซ์น้ำหนัก บวก bias และผ่าน activation ทีละชั้น

  2. 02

    คำนวณ loss ระหว่าง output กับ y แล้วใช้ backpropagation หา gradient ของน้ำหนักทุกชั้น

  3. 03

    optimizer เช่น Adam ใช้ gradient และ learning rate ปรับน้ำหนัก ทำซ้ำหลาย epoch จนถึงเงื่อนไขหยุด

ควรรู้อีกนิด — ต้องปรับสเกลข้อมูล เลือก architecture และ regularization; ผลอธิบายยากกว่าโมเดลเชิงเส้น

04Make it yours

Python · scikit-learn
# ติดตั้ง: pip install numpy scikit-learn matplotlibfrom sklearn.neural_network import MLPRegressorfrom 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 = MLPRegressor(hidden_layer_sizes=(8,), max_iter=3000, random_state=42)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

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

Sample dataset / Curved signal● คำนวณใหม่เมื่อปรับค่า
neuron มากขึ้นเพิ่มความสามารถในการสร้างเส้นโค้ง
ข้อมูลฝึกและผลการทำนายFeature xค่าจริง • / ค่าทำนาย —
RMSE0.257
พารามิเตอร์โดยประมาณ25
พารามิเตอร์ที่ลอง8

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