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

Logistic Regression

เปลี่ยนคะแนนให้เป็นความน่าจะเป็น

LEARNING LEVEL2
ต่อยอดโดยตรงควรรู้มาก่อน · Linear Regression และความน่าจะเป็น
ลองใน Playground

01Overall Concept

OVERALL CONCEPT

ไอเดียหลัก — Logistic Regression ใช้ตอบคำถามแบบเลือกกลุ่ม เช่น อีเมลนี้เป็นสแปมหรือไม่ โมเดลรวมข้อมูลเป็นคะแนน แล้วเปลี่ยนคะแนนนั้นให้เป็นความน่าจะเป็นตั้งแต่ 0 ถึง 1 เราจึงเห็นทั้งคำตอบและระดับความมั่นใจ

ลองนึกภาพว่า — เหมือนถังคะแนน หลักฐานที่สนับสนุนคำตอบจะเติมลูกแก้ว ส่วนหลักฐานที่ค้านจะหยิบลูกแก้วออก เมื่อคะแนนผ่านเส้นที่กำหนด โมเดลจึงเลือกอีกฝั่งหนึ่ง

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

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

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

ชื่อทำให้หลายคนงง เพราะมี Regression อยู่ในชื่อ แต่ใช้แยกประเภท

สมมติเราต้องการทำนายว่า

ลูกค้าคนนี้จะซื้อสินค้าไหม?

Logistic Regression จะดูข้อมูล เช่น อายุ รายได้ จำนวนครั้งที่เข้าเว็บ สินค้าที่เคยซื้อ แล้วคำนวณออกมาเป็น ความน่าจะเป็น

เช่น

มีโอกาสซื้อ 78%

จากนั้นเราอาจตั้งกฎว่า

ถ้า > 50% → ซื้อ ถ้า ≤ 50% → ไม่ซื้อ

หรือในระบบจริงอาจตั้ง >70% เพื่อเลือกเฉพาะ Lead ที่มีคุณภาพสูง

ข้อดีของ Logistic Regression คือเรียบง่าย เร็ว และอธิบายได้ดี เช่นเราสามารถดูได้ว่า

การเป็นลูกค้าเก่าเพิ่มโอกาสซื้อ ราคาสูงลดโอกาสซื้อ เข้าเว็บไซต์บ่อยเพิ่มโอกาสซื้อ

เพราะเหตุนี้ แม้จะเป็นโมเดลเก่า แต่มันยังถูกใช้เยอะมาก โดยเฉพาะธุรกิจ การแพทย์ เครดิต และงานวิเคราะห์ที่ต้องอธิบายเหตุผล

ภาพจำ: ให้คะแนนความน่าจะเป็นก่อน แล้วค่อยตัดสินว่าอยู่ฝั่งไหน

03How it works

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

  1. เปลี่ยนคำถามซื้อไหมให้เป็น 0 กับ 1

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

  2. จากหลักฐานไปเป็นโอกาส

    โมเดลรวม feature เป็นคะแนน z = b + w₁x₁ + w₂x₂ + … แล้วใช้ sigmoid เปลี่ยนคะแนนเป็นค่าระหว่าง 0 กับ 1 เช่น z=0 ให้ 0.5 ส่วน z ที่เป็นบวกมากจะเข้าใกล้ 1 ตอนฝึกมันเปรียบเทียบโอกาสที่ทายกับ y จริงผ่าน log loss โดยการมั่นใจมากแต่ตอบผิดจะถูกลงโทษมาก

  3. ฝึกด้วยสูตรเริ่มต้นที่อ่านง่าย

    ใช้ make_pipeline(StandardScaler(), LogisticRegression(C=1.0, max_iter=1000)) แล้ว fit(X_train, y_train) แปลงหมวดหมู่ด้วย encoder เพิ่มเมื่อมีชื่อประเภทลูกค้า ค่า C เล็กเพิ่มแรง regularization ส่วน C ใหญ่ยอมตามข้อมูลฝึกมากขึ้น max_iter ให้เวลาหาค่าน้ำหนัก ไม่ใช่จำนวนลูกค้าที่เรียน

  4. แยกการทายโอกาสออกจากการตัดสินใจ

    predict_proba(X_test) ให้ความน่าจะเป็นแยกคลาส ดู classes_ ก่อนเลือกคอลัมน์ของคลาส 1 จากนั้นตั้งเกณฑ์เอง เช่นโอกาสซื้อ ≥ 0.7 จึงส่งต่อเป็น lead คุณภาพสูง การเปลี่ยนเกณฑ์นี้ไม่ต้องฝึกโมเดลใหม่ แต่จะเปลี่ยนจำนวนคนที่ถูกเลือกและจำนวนคนที่เราพลาด

  5. ตรวจสิ่งที่ธุรกิจต้องการจริง

    ใช้ confusion matrix ดูจำนวนที่ทายซื้อถูก ทายซื้อผิด และพลาดคนที่จะซื้อ ถ้าอยากลดการส่ง lead ผิด ดู precision ถ้าอยากเก็บคนซื้อให้ครบ ดู recall ปรับ C และ threshold บน validation แล้ววัดผลสุดท้ายบน test ที่กันไว้ เมื่อจะนำตัวเลข 78% ไปตัดสินใจจริง ควรตรวจว่าความน่าจะเป็นสอดคล้องกับความถี่ที่เกิดขึ้นด้วย

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

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

DATA INX · featuresy · targetX = [เข้าเว็บ, ซื้อเดิม, ราคาสินค้า] · y = ซื้อ 1 / ไม่ซื้อ 0
CALCULATELogistic Regression
Cpenaltymax_iter
RESULT0.800.150.05class / probabilitypredict_proba → โอกาสซื้อ → เทียบ threshold ที่เลือก
เส้นทางของข้อมูล: จากค่าที่รับเข้า ผ่านการคำนวณด้วยพารามิเตอร์ ไปเป็นผลลัพธ์
INPUT

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

รับ X เป็นตารางตัวเลขและ y เป็นป้ายคลาส เช่น 0/1 หรือชื่อกลุ่มที่เข้ารหัสแล้ว หนึ่งแถวคือหนึ่งตัวอย่างพร้อมคำตอบ

X = [เข้าเว็บ, ซื้อเดิม, ราคาสินค้า] · y = ซื้อ 1 / ไม่ซื้อ 0
PARAMETERS

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

C
ค่ากลับด้านของ regularization; C สูงตามข้อมูลฝึกมากขึ้น
penalty
กติกา L1, L2 หรือแบบอื่นที่ใช้คุมน้ำหนัก
max_iter
จำนวนรอบสูงสุดในการปรับ coefficients
OUTPUT

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

predict ให้ป้ายคลาส ส่วน predict_proba ให้ความน่าจะเป็นของแต่ละคลาสต่อหนึ่งแถว

predict_proba → โอกาสซื้อ → เทียบ threshold ที่เลือก
CALCULATION

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

  1. 01

    คูณ feature ด้วยน้ำหนักและบวกเป็นคะแนน z = b + w·x

  2. 02

    ส่ง z ผ่าน sigmoid เพื่อเปลี่ยนเป็นความน่าจะเป็นระหว่าง 0 ถึง 1

  3. 03

    ใช้ log loss เปรียบเทียบกับคลาสจริง แล้วปรับน้ำหนักให้ความน่าจะเป็นของคำตอบจริงสูงขึ้น

ควรรู้อีกนิด — ขอบเขตการตัดสินใจเป็นเส้นตรงหากไม่สร้าง feature เพิ่ม และ probability ควรตรวจ calibration

04Make it yours

Python · scikit-learn
# ติดตั้ง: pip install numpy scikit-learn matplotlibfrom sklearn.linear_model import LogisticRegressionfrom sklearn.metrics import accuracy_score from sklearn.datasets import make_classificationfrom sklearn.model_selection import train_test_split X, y = make_classification(    n_samples=150, n_features=2, n_redundant=0,    n_informative=2, n_classes=3, n_clusters_per_class=1,    class_sep=1.4, random_state=42,)X_train, X_test, y_train, y_test = train_test_split(    X, y, test_size=0.2, random_state=42, stratify=y) model = LogisticRegression(C=1.0)model.fit(X_train, y_train)pred = model.predict(X_test)print("Accuracy:", accuracy_score(y_test, pred))

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

05Learn by playing

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

Sample dataset / Three classes● คำนวณใหม่เมื่อปรับค่า
ค่าสูงขึ้นลด regularization และยอมให้น้ำหนักใหญ่ขึ้น
พื้นที่สีคือคำทำนาย จุดคือคำตอบจริงFeature x → · Feature y ↑ · ขอบเข้ม = ชุดทดสอบ
Test accuracy93.3%
ชุดทดสอบ30 จุด
พารามิเตอร์ที่ลอง1.0

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