Lab 3: Logistic Regression and Perceptron

วัตถุประสงค์การเรียนรู้

  1. เข้าใจหลักการทำงานของ Logistic Regression
  2. เข้าใจหลักการทำงานของ Perceptron
  3. เข้าใจความจำเป็นและวิธีการทำ One-Hot Encoding
  4. สามารถใช้ Scikit-learn ในการสร้างโมเดลจำแนกประเภท
  5. สามารถเปรียบเทียบประสิทธิภาพของทั้งสองอัลกอริทึม

ทฤษฎีเบื้องต้น

1. Logistic Regression

Logistic Regression เป็นอัลกอริทึมการจำแนกประเภท (Classification) ที่ใช้ฟังก์ชัน Sigmoid ในการแปลงค่าเชิงเส้นให้เป็นความน่าจะเป็น

Linear Function:

z = w0 + w1 x1 + w2 x2 + + wn xn = 𝐰T 𝐱

Sigmoid Function (Logistic Function):

σ ( z ) = 1 1 + e z

ความน่าจะเป็นของคลาส:

P ( y = 1 | 𝐱 ) = σ ( 𝐰T 𝐱 )

Cross-Entropy Loss Function:

J ( 𝐰 ) = 1 m i=1 m [ y(i) log ( y^(i) ) + ( 1 y(i) ) log ( 1 y^(i) ) ]

Gradient Descent Update:

wj := wj α J wj

คุณสมบัติของ Logistic Regression

คุณสมบัติ รายละเอียด
Output ค่าความน่าจะเป็น (0 ถึง 1)
Decision Boundary เชิงเส้น (Linear)
การเรียนรู้ ใช้ Gradient Descent
การจัดการ Multi-class One-vs-Rest หรือ Softmax

2. Perceptron

Perceptron เป็นโมเดล Neural Network แบบง่ายที่สุด ประกอบด้วย input layer และ output layer เพียงชั้นเดียว

Linear Combination:

z = i=1 n wi xi + b = 𝐰T 𝐱 + b

Activation Function (Step Function):

y^ = { 1 if z0 0 if z<0

Perceptron Learning Rule:

wi := wi + η ( y y^ ) xi

โดยที่:

คุณสมบัติของ Perceptron

คุณสมบัติ รายละเอียด
Output ค่า Binary (0 หรือ 1)
Decision Boundary เชิงเส้น (Linear)
การเรียนรู้ Perceptron Learning Rule
ข้อจำกัด ทำงานได้ดีเฉพาะข้อมูลที่ Linearly Separable

3. เปรียบเทียบ Logistic Regression vs Perceptron

หัวข้อ Logistic Regression Perceptron
Activation Function Sigmoid (ต่อเนื่อง) Step Function (ไม่ต่อเนื่อง)
Output ความน่าจะเป็น (0-1) Binary (0 หรือ 1)
Loss Function Cross-Entropy Perceptron Loss
การ Converge รับประกันการ Converge Converge เฉพาะข้อมูล Linearly Separable
Probability Estimate ให้ค่าความน่าจะเป็น ไม่ให้ค่าความน่าจะเป็นโดยตรง
การจัดการ Noise จัดการได้ดีกว่า อ่อนไหวต่อ Noise

One-Hot Encoding: ทำไมต้องมี?

ปัญหาของข้อมูล Categorical

ข้อมูลที่เราใช้มี features เป็นข้อความ เช่น:

ปัญหา: อัลกอริทึม Machine Learning ส่วนใหญ่ทำงานกับ ตัวเลข เท่านั้น ไม่สามารถประมวลผลข้อความได้โดยตรง

วิธีที่ 1: Label Encoding (ไม่แนะนำสำหรับกรณีนี้)

แปลงข้อความเป็นตัวเลข เช่น:

"มาก" → 2
"ปานกลาง" → 1  
"น้อย" → 0

ปัญหาของ Label Encoding:

โมเดลอาจตีความว่า "มาก" (2) มีค่ามากกว่า "น้อย" (0) ถึง 2 เท่า หรือ "มาก" - "ปานกลาง" = "ปานกลาง" - "น้อย" ซึ่งไม่สมเหตุสมผลสำหรับข้อมูล Categorical ที่ไม่มีลำดับความสัมพันธ์ทางคณิตศาสตร์

วิธีที่ 2: One-Hot Encoding (แนะนำ)

แปลงแต่ละค่าเป็น Binary Vector โดยมีขนาดเท่ากับจำนวนค่าที่เป็นไปได้

ตัวอย่าง: เมฆ (Cloud)

ค่าเดิม cloud_มาก cloud_ปานกลาง cloud_น้อย
มาก 1 0 0
ปานกลาง 0 1 0
น้อย 0 0 1

ตัวอย่าง: การแปลงข้อมูล 1 แถว

ข้อมูลเดิม:

เมฆ: มาก, อากาศ: เย็น, ความชื้น: มาก

หลัง One-Hot Encoding:

cloud_มาก=1, cloud_ปานกลาง=0, cloud_น้อย=0,
temp_ร้อน=0, temp_อบอุ่น=0, temp_เย็น=1,
humidity_มาก=1, humidity_ปานกลาง=0, humidity_น้อย=0

Vector: [1, 0, 0, 0, 0, 1, 1, 0, 0]

ทำไม One-Hot Encoding ถึงดีกว่า?

  1. ไม่สร้างลำดับเทียม: แต่ละค่าเป็นอิสระต่อกัน ไม่มีความสัมพันธ์ทางคณิตศาสตร์ระหว่างค่า

  2. ระยะห่างเท่ากัน: ทุกค่ามีระยะห่างเท่ากันในมิติ Euclidean

    distance ( "มาก" , "น้อย" ) = distance ( "มาก" , "ปานกลาง" ) = 2
  3. โมเดลเรียนรู้ได้ถูกต้อง: น้ำหนัก (weights) ของแต่ละ feature แยกจากกัน ทำให้โมเดลเรียนรู้ความสำคัญของแต่ละค่าได้อย่างอิสระ

ภาพประกอบ One-Hot Encoding

ข้อมูลดิบ                    One-Hot Encoding
┌─────────┐                 ┌───┬───┬───┐
│  มาก    │  ───────────►   │ 1 │ 0 │ 0 │
└─────────┘                 └───┴───┴───┘
                             มาก ปาน น้อย

┌─────────┐                 ┌───┬───┬───┐
│ ปานกลาง │  ───────────►   │ 0 │ 1 │ 0 │
└─────────┘                 └───┴───┴───┘
                             มาก ปาน น้อย

┌─────────┐                 ┌───┬───┬───┐
│  น้อย   │  ───────────►   │ 0 │ 0 │ 1 │
└─────────┘                 └───┴───┴───┘
                             มาก ปาน น้อย

คำสั่ง

ให้นักศึกษาเขียนโปรแกรมภาษา Python เพื่อทำนายสภาพอากาศว่าฝนจะตกหรือไม่ โดยใช้ Logistic Regression และ Perceptron จากข้อมูลที่กำหนดให้ แล้วเปรียบเทียบผลลัพธ์

สิ่งที่ต้องทำ

  1. อ่านข้อมูล Training Set จากไฟล์ weather_data.csv

  2. ทำ One-Hot Encoding สำหรับ features ทั้งหมด

  3. แปลง Class Labels เป็นตัวเลข:

  4. สร้างและ Train โมเดล 2 แบบ:

  5. ทดสอบกับ Test Cases ที่กำหนดให้

  6. เปรียบเทียบผลลัพธ์ ระหว่างสองโมเดล


ข้อกำหนด

Features (ตัวแปรอิสระ)

Feature ค่าที่เป็นไปได้ คำอธิบาย
เมฆ (Cloud) มาก, ปานกลาง, น้อย ปริมาณเมฆบนท้องฟ้า
อากาศ (Temperature) ร้อน, อบอุ่น, เย็น อุณหภูมิของอากาศ
ความชื้น (Humidity) มาก, ปานกลาง, น้อย ระดับความชื้นในอากาศ

Class (ตัวแปรตาม)

Class Label คำอธิบาย
ฝนไม่ตก 0 ไม่มีฝนตก
ฝนตกเล็กน้อย 1 มีฝนตกเบาๆ หรือฝนปรอย
ฝนตกหนัก 2 มีฝนตกหนักมาก

ข้อกำหนดทางเทคนิค

  1. ภาษา: Python 3.x
  2. Library ที่อนุญาต:
  3. ใช้ One-Hot Encoding ด้วย pd.get_dummies() หรือ OneHotEncoder
  4. แสดงค่าความน่าจะเป็น (สำหรับ Logistic Regression)
  5. แสดง Accuracy ของทั้งสองโมเดล
  6. ปัดทศนิยม 6 ตำแหน่ง

ชุดข้อมูล Training Set (50 รายการ)

id,cloud,temperature,humidity,rain
1,มาก,เย็น,มาก,ฝนตกหนัก
2,มาก,อบอุ่น,มาก,ฝนตกหนัก
3,ปานกลาง,อบอุ่น,ปานกลาง,ฝนตกเล็กน้อย
4,น้อย,ร้อน,น้อย,ฝนไม่ตก
5,น้อย,ร้อน,ปานกลาง,ฝนไม่ตก
6,มาก,เย็น,ปานกลาง,ฝนตกเล็กน้อย
7,ปานกลาง,ร้อน,มาก,ฝนตกเล็กน้อย
8,น้อย,อบอุ่น,น้อย,ฝนไม่ตก
9,มาก,อบอุ่น,ปานกลาง,ฝนตกเล็กน้อย
10,ปานกลาง,เย็น,มาก,ฝนตกหนัก
11,น้อย,เย็น,น้อย,ฝนไม่ตก
12,มาก,ร้อน,มาก,ฝนตกหนัก
13,ปานกลาง,อบอุ่น,น้อย,ฝนไม่ตก
14,มาก,เย็น,มาก,ฝนตกหนัก
15,น้อย,ร้อน,น้อย,ฝนไม่ตก
16,ปานกลาง,เย็น,ปานกลาง,ฝนตกเล็กน้อย
17,มาก,อบอุ่น,มาก,ฝนตกหนัก
18,น้อย,อบอุ่น,ปานกลาง,ฝนไม่ตก
19,ปานกลาง,ร้อน,ปานกลาง,ฝนตกเล็กน้อย
20,มาก,เย็น,ปานกลาง,ฝนตกเล็กน้อย
21,น้อย,ร้อน,มาก,ฝนตกเล็กน้อย
22,มาก,อบอุ่น,ปานกลาง,ฝนตกเล็กน้อย
23,ปานกลาง,เย็น,มาก,ฝนตกหนัก
24,น้อย,เย็น,ปานกลาง,ฝนไม่ตก
25,มาก,ร้อน,ปานกลาง,ฝนตกเล็กน้อย
26,ปานกลาง,อบอุ่น,มาก,ฝนตกเล็กน้อย
27,น้อย,อบอุ่น,น้อย,ฝนไม่ตก
28,มาก,เย็น,มาก,ฝนตกหนัก
29,ปานกลาง,ร้อน,น้อย,ฝนไม่ตก
30,มาก,อบอุ่น,มาก,ฝนตกหนัก
31,น้อย,เย็น,มาก,ฝนตกเล็กน้อย
32,ปานกลาง,เย็น,ปานกลาง,ฝนตกเล็กน้อย
33,มาก,ร้อน,มาก,ฝนตกหนัก
34,น้อย,ร้อน,ปานกลาง,ฝนไม่ตก
35,ปานกลาง,อบอุ่น,ปานกลาง,ฝนตกเล็กน้อย
36,มาก,เย็น,ปานกลาง,ฝนตกเล็กน้อย
37,น้อย,อบอุ่น,มาก,ฝนตกเล็กน้อย
38,มาก,อบอุ่น,น้อย,ฝนไม่ตก
39,ปานกลาง,เย็น,มาก,ฝนตกหนัก
40,น้อย,ร้อน,น้อย,ฝนไม่ตก
41,มาก,เย็น,มาก,ฝนตกหนัก
42,ปานกลาง,ร้อน,ปานกลาง,ฝนตกเล็กน้อย
43,น้อย,อบอุ่น,ปานกลาง,ฝนไม่ตก
44,มาก,อบอุ่น,มาก,ฝนตกหนัก
45,ปานกลาง,เย็น,น้อย,ฝนไม่ตก
46,น้อย,เย็น,ปานกลาง,ฝนตกเล็กน้อย
47,มาก,ร้อน,ปานกลาง,ฝนตกเล็กน้อย
48,ปานกลาง,อบอุ่น,มาก,ฝนตกเล็กน้อย
49,น้อย,ร้อน,มาก,ฝนตกเล็กน้อย
50,มาก,เย็น,มาก,ฝนตกหนัก

สรุปการกระจายของข้อมูล

Class จำนวน สัดส่วน
ฝนไม่ตก 15 30%
ฝนตกเล็กน้อย 20 40%
ฝนตกหนัก 15 30%

ตัวอย่าง Input และ Output

Test Case 1

Input:

เมฆ: มาก
อากาศ: เย็น
ความชื้น: มาก

Output:

===============================================================
         Logistic Regression vs Perceptron Comparison
===============================================================

Input Features:
  - เมฆ: มาก
  - อากาศ: เย็น
  - ความชื้น: มาก

One-Hot Encoded: [1, 0, 0, 0, 0, 1, 1, 0, 0]

---------------------------------------------------------------
                    Logistic Regression
---------------------------------------------------------------
Probabilities:
  P(ฝนไม่ตก)      = 0.021543
  P(ฝนตกเล็กน้อย) = 0.147892
  P(ฝนตกหนัก)     = 0.830565

Prediction: ฝนตกหนัก

---------------------------------------------------------------
                        Perceptron
---------------------------------------------------------------
Prediction: ฝนตกหนัก

---------------------------------------------------------------
                        Comparison
---------------------------------------------------------------
Logistic Regression: ฝนตกหนัก
Perceptron:          ฝนตกหนัก
Agreement:           ✓ ทั้งสองโมเดลให้ผลลัพธ์ตรงกัน
===============================================================

Test Case 2

Input:

เมฆ: น้อย
อากาศ: ร้อน
ความชื้น: น้อย

Output:

===============================================================
         Logistic Regression vs Perceptron Comparison
===============================================================

Input Features:
  - เมฆ: น้อย
  - อากาศ: ร้อน
  - ความชื้น: น้อย

One-Hot Encoded: [0, 0, 1, 1, 0, 0, 0, 0, 1]

---------------------------------------------------------------
                    Logistic Regression
---------------------------------------------------------------
Probabilities:
  P(ฝนไม่ตก)      = 0.892341
  P(ฝนตกเล็กน้อย) = 0.095123
  P(ฝนตกหนัก)     = 0.012536

Prediction: ฝนไม่ตก

---------------------------------------------------------------
                        Perceptron
---------------------------------------------------------------
Prediction: ฝนไม่ตก

---------------------------------------------------------------
                        Comparison
---------------------------------------------------------------
Logistic Regression: ฝนไม่ตก
Perceptron:          ฝนไม่ตก
Agreement:           ✓ ทั้งสองโมเดลให้ผลลัพธ์ตรงกัน
===============================================================

Test Case 3

Input:

เมฆ: ปานกลาง
อากาศ: อบอุ่น
ความชื้น: ปานกลาง

Output:

===============================================================
         Logistic Regression vs Perceptron Comparison
===============================================================

Input Features:
  - เมฆ: ปานกลาง
  - อากาศ: อบอุ่น
  - ความชื้น: ปานกลาง

One-Hot Encoded: [0, 1, 0, 0, 1, 0, 0, 1, 0]

---------------------------------------------------------------
                    Logistic Regression
---------------------------------------------------------------
Probabilities:
  P(ฝนไม่ตก)      = 0.198765
  P(ฝนตกเล็กน้อย) = 0.654321
  P(ฝนตกหนัก)     = 0.146914

Prediction: ฝนตกเล็กน้อย

---------------------------------------------------------------
                        Perceptron
---------------------------------------------------------------
Prediction: ฝนตกเล็กน้อย

---------------------------------------------------------------
                        Comparison
---------------------------------------------------------------
Logistic Regression: ฝนตกเล็กน้อย
Perceptron:          ฝนตกเล็กน้อย
Agreement:           ✓ ทั้งสองโมเดลให้ผลลัพธ์ตรงกัน
===============================================================

Test Case 4

Input:

เมฆ: มาก
อากาศ: ร้อน
ความชื้น: น้อย

Output:

===============================================================
         Logistic Regression vs Perceptron Comparison
===============================================================

Input Features:
  - เมฆ: มาก
  - อากาศ: ร้อน
  - ความชื้น: น้อย

One-Hot Encoded: [1, 0, 0, 1, 0, 0, 0, 0, 1]

---------------------------------------------------------------
                    Logistic Regression
---------------------------------------------------------------
Probabilities:
  P(ฝนไม่ตก)      = 0.412345
  P(ฝนตกเล็กน้อย) = 0.398765
  P(ฝนตกหนัก)     = 0.188890

Prediction: ฝนไม่ตก

---------------------------------------------------------------
                        Perceptron
---------------------------------------------------------------
Prediction: ฝนตกเล็กน้อย

---------------------------------------------------------------
                        Comparison
---------------------------------------------------------------
Logistic Regression: ฝนไม่ตก
Perceptron:          ฝนตกเล็กน้อย
Agreement:           ✗ สองโมเดลให้ผลลัพธ์ต่างกัน
===============================================================

Test Case 5

Input:

เมฆ: น้อย
อากาศ: เย็น
ความชื้น: มาก

Output:

===============================================================
         Logistic Regression vs Perceptron Comparison
===============================================================

Input Features:
  - เมฆ: น้อย
  - อากาศ: เย็น
  - ความชื้น: มาก

One-Hot Encoded: [0, 0, 1, 0, 0, 1, 1, 0, 0]

---------------------------------------------------------------
                    Logistic Regression
---------------------------------------------------------------
Probabilities:
  P(ฝนไม่ตก)      = 0.187654
  P(ฝนตกเล็กน้อย) = 0.512346
  P(ฝนตกหนัก)     = 0.300000

Prediction: ฝนตกเล็กน้อย

---------------------------------------------------------------
                        Perceptron
---------------------------------------------------------------
Prediction: ฝนตกเล็กน้อย

---------------------------------------------------------------
                        Comparison
---------------------------------------------------------------
Logistic Regression: ฝนตกเล็กน้อย
Perceptron:          ฝนตกเล็กน้อย
Agreement:           ✓ ทั้งสองโมเดลให้ผลลัพธ์ตรงกัน
===============================================================

สรุปผลการเปรียบเทียบ (ตัวอย่าง)

===============================================================
                    Summary Report
===============================================================

Training Data: 50 samples
Test Cases: 5 samples

Model Performance on Training Data:
  - Logistic Regression Accuracy: 0.860000
  - Perceptron Accuracy:          0.780000

Agreement on Test Cases:
  - Total Test Cases: 5
  - Agreements:       4
  - Disagreements:    1
  - Agreement Rate:   80.00%

===============================================================

โครงสร้างโปรแกรมที่แนะนำ

import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression, Perceptron
from sklearn.preprocessing import LabelEncoder

def load_data(filename):
    """
    Load training data from CSV file
    """
    # TODO: Implement data loading
    pass

def one_hot_encode(df, columns):
    """
    Perform One-Hot Encoding on specified columns
    """
    # TODO: Implement One-Hot Encoding
    pass

def encode_labels(y):
    """
    Encode class labels to numeric values
    ฝนไม่ตก → 0, ฝนตกเล็กน้อย → 1, ฝนตกหนัก → 2
    """
    # TODO: Implement label encoding
    pass

def decode_label(label_num):
    """
    Decode numeric label back to Thai text
    """
    label_map = {0: 'ฝนไม่ตก', 1: 'ฝนตกเล็กน้อย', 2: 'ฝนตกหนัก'}
    return label_map[label_num]

def prepare_test_input(cloud, temperature, humidity, feature_columns):
    """
    Prepare test input with One-Hot Encoding
    """
    # TODO: Create One-Hot Encoded vector for test input
    pass

def print_results(features, lr_pred, lr_proba, perc_pred):
    """
    Print formatted results
    """
    # TODO: Implement result printing
    pass

def main():
    # Load data
    df = load_data('weather_data.csv')
    
    # Prepare features and labels
    X = one_hot_encode(df, ['cloud', 'temperature', 'humidity'])
    y = encode_labels(df['rain'])
    
    # Create models
    lr_model = LogisticRegression(max_iter=1000, random_state=42)
    perc_model = Perceptron(max_iter=1000, random_state=42)
    
    # Train models
    lr_model.fit(X, y)
    perc_model.fit(X, y)
    
    # Calculate training accuracy
    lr_accuracy = lr_model.score(X, y)
    perc_accuracy = perc_model.score(X, y)
    
    print(f"Logistic Regression Training Accuracy: {lr_accuracy:.6f}")
    print(f"Perceptron Training Accuracy: {perc_accuracy:.6f}")
    
    # Test cases
    test_cases = [
        {'cloud': 'มาก', 'temperature': 'เย็น', 'humidity': 'มาก'},
        {'cloud': 'น้อย', 'temperature': 'ร้อน', 'humidity': 'น้อย'},
        {'cloud': 'ปานกลาง', 'temperature': 'อบอุ่น', 'humidity': 'ปานกลาง'},
        {'cloud': 'มาก', 'temperature': 'ร้อน', 'humidity': 'น้อย'},
        {'cloud': 'น้อย', 'temperature': 'เย็น', 'humidity': 'มาก'},
    ]
    
    # Make predictions and compare
    agreements = 0
    for test in test_cases:
        X_test = prepare_test_input(
            test['cloud'], 
            test['temperature'], 
            test['humidity'],
            X.columns
        )
        
        # Logistic Regression prediction
        lr_pred = lr_model.predict(X_test)[0]
        lr_proba = lr_model.predict_proba(X_test)[0]
        
        # Perceptron prediction
        perc_pred = perc_model.predict(X_test)[0]
        
        # Print results
        print_results(test, lr_pred, lr_proba, perc_pred)
        
        # Count agreements
        if lr_pred == perc_pred:
            agreements += 1
    
    # Print summary
    print(f"\nAgreement Rate: {agreements}/{len(test_cases)} = {agreements/len(test_cases)*100:.2f}%")

if __name__ == "__main__":
    main()

คำถามท้าย Lab

  1. One-Hot Encoding: ถ้าเพิ่ม feature "ลม" ที่มี 4 ค่า (แรง, ปานกลาง, เบา, ไม่มี) จะทำให้มี features ทั้งหมดกี่ตัวหลังทำ One-Hot Encoding?

  2. Logistic Regression vs Perceptron: จาก Test Case ที่ทดสอบ โมเดลใดให้ผลลัพธ์ที่น่าเชื่อถือกว่า? เพราะเหตุใด?

  3. Probability Output: ทำไม Logistic Regression จึงให้ค่าความน่าจะเป็นได้ แต่ Perceptron ไม่สามารถให้ได้โดยตรง?

  4. Decision Boundary: ถ้าข้อมูลไม่ได้เป็น Linearly Separable โมเดลใดจะมีปัญหามากกว่า?

  5. Multi-class Classification: Scikit-learn ใช้วิธีใดในการจัดการ Multi-class สำหรับ Logistic Regression และ Perceptron?


ภาคผนวก: สูตรคณิตศาสตร์

Softmax Function (Multi-class Logistic Regression)

P ( y = k | 𝐱 ) = e 𝐰kT 𝐱 j=1 K e 𝐰jT 𝐱

Multi-class Cross-Entropy Loss

J ( 𝐖 ) = 1 m i=1 m k=1 K yk(i) log ( y^k(i) )

Perceptron Multi-class (One-vs-All)

สำหรับ K คลาส สร้าง K Perceptrons:

y^ = arg max k{1,,K} 𝐰kT 𝐱

Euclidean Distance (One-Hot Vectors)

d ( 𝐯1 , 𝐯2 ) = i=1 n ( v1i v2i ) 2

สำหรับ One-Hot Vectors ของค่าต่างกัน:

d = 12 + (1)2 = 2