แผนการเรียนรู้
/

การบ้านสัปดาห์ที่ 9

PyTorch Perceptron Dashboard

สร้าง Django dashboard สำหรับฝึกสอนเพอร์เซปตรอนแบบ real-time

1. ข้อกำหนดโครงงาน

2. โครงสร้าง Django project

3. สิ่งที่ต้องทำใน ml/train.py

4. หน้า landing page

5. วิธีรันและตรวจสอบ

6. การส่งงาน

ข้อกำหนดโครงงาน

- โมเดล: เพอร์เซปตรอนชั้นเดียว (Linear + Sigmoid) สำหรับ binary classification

- Training loop: forward, loss, backward, update ด้วยมือ (ไม่ใช้ optimizer)

- ทดลอง learning rate: 3 ค่า (0.001, 0.1, 1.0) เปรียบเทียบผลลัพธ์

- Dashboard: SSE streaming แสดง loss, accuracy แบบ real-time ขณะฝึกสอน

- หน้า landing: แสดง รหัสนักศึกษา และ ชื่อ-นามสกุล (hardcoded)

[สำคัญ] ใช้ Django + PyTorch + SSE เท่านั้น ห้ามใช้ Flask หรือ FastAPI

# ผลลัพธ์ที่คาดหวัง:

1. เริ่ม server แล้วเห็นหน้า landing page
   ที่มีรหัสนักศึกษาและชื่อ-นามสกุล

2. กดปุ่ม "เริ่มฝึกสอน" แล้วเห็น
   - ค่า loss ลดลงแบบ real-time
   - ค่า accuracy เพิ่มขึ้นแบบ real-time
   - กราฟ loss curve อัปเดตทุก epoch

3. หลังฝึกสอนเสร็จ แสดงผลลัพธ์สุดท้าย
   - Loss curve บันทึกเป็นไฟล์ PNG
   - ตารางเปรียบเทียบ 3 learning rates

4. หน้า landing page แสดงรหัสและชื่อ
   ของนักศึกษาที่ทำโครงงาน

โครงสร้าง Django Project

DL69/wk09/
├── pyproject.toml           # uv project, Python 3.13
├── manage.py
├── mysite/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── dashboard/
│   ├── __init__.py
│   ├── apps.py
│   ├── views.py             # SSE streaming endpoint
│   ├── urls.py              # / → index, /train/ → SSE
│   ├── ml/
│   │   ├── __init__.py
│   │   └── train.py         # ★ นักศึกษาเขียนโค้ดตรงนี้
│   ├── templates/
│   │   └── dashboard/
│   │       └── index.html    # ★ ใส่รหัสและชื่อตรงนี้
│   └── static/
│       └── dashboard/
│           └── (ผลลัพธ์จาก train.py)
└── data/                     # ข้อมูล (ถ้ามี)

- pyproject.toml: กำหนด dependencies สำหรับ uv sync

- dashboard/ml/train.py: ไฟล์หลักที่นักศึกษาต้องเขียน

- dashboard/templates/dashboard/index.html: หน้า landing page

- dashboard/views.py: SSE endpoint ที่เรียก ml.train()

[สำคัญ] ห้ามลบหรือแก้ไขไฟล์ที่ไม่ได้ระบุว่าต้องแก้ — ใช้ไฟล์เดิมที่ให้มา

สิ่งที่ต้องทำใน ml/train.py

def train(on_progress=None):
    """
    on_progress(epoch, loss, acc) → เรียกทุก epoch
    เพื่อส่งข้อมูลผ่าน SSE ไปยังเบราว์เซอร์
    """
    import torch

    # 1. สร้างข้อมูล (binary classification)
    #    ข้อมูลเส้นตรง: X = torch.randn(200, 2)
    #    y = ((X[:,0]*1.5 + X[:,1] - 0.5) > 0)

    # 2. สร้างโมเดล (perceptron)
    #    Linear(2, 1) + Sigmoid

    # 3. Training loop
    for epoch in range(num_epochs):
        # forward
        y_hat = model(X)
        loss = loss_fn(y_hat, y)

        # backward
        loss.backward()

        # update weights (手動)
        with torch.no_grad():
            for p in model.parameters():
                p -= lr * p.grad
            model.zero_grad()

        # คำนวณ accuracy
        acc = ...

        # ส่งข้อมูลผ่าน SSE
        if on_progress:
            on_progress(epoch, loss.item(), acc)

    # 4. บันทึกผลลัพธ์
    #    - loss curve → static/dashboard/loss_curve.png
    #    - ตารางเปรียบเทียบ lr

- ข้อ 1: สร้างข้อมูล binary classification ด้วย torch.randn

- ข้อ 2: สร้าง perceptron ด้วย nn.Linear(2,1) + Sigmoid

- ข้อ 3: Training loop ด้วยมือ — forward, loss, backward, update

- ข้อ 4: เรียก on_progress(epoch, loss, acc) ทุก epoch

- ข้อ 5: บันทึก loss curve เป็น PNG

[เคล็ดลับ] ดู code ตัวอย่างจาก wk09-hw.py เป็นแนวทาง

หน้า Landing Page

<!-- dashboard/templates/dashboard/index.html -->
<!DOCTYPE html>
<html lang="th">
<head>
  <title>Perceptron Dashboard</title>
  <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
  <script src="https://cdn.tailwindcss.com"></script>
</head>
<body x-data="{ training: false, epoch: 0, loss: 0, acc: 0 }">

  <!-- ★ ใส่รหัสนักศึกษาและชื่อ-นามสกุลตรงนี้ -->
  <h1>รหัสนักศึกษา: 69000000</h1>
  <h2>ชื่อ-นามสกุล: ชื่อ นามสกุล</h2>

  <button @click="startTraining()">
    เริ่มฝึกสอน
  </button>

  <p>Epoch: <span x-text="epoch"></span></p>
  <p>Loss: <span x-text="loss"></span></p>
  <p>Accuracy: <span x-text="acc"></span></p>

  <canvas id="chart"></canvas>

  <script>
  function startTraining() {
    training = true;
    const es = new EventSource('/train/');
    es.onmessage = function(e) {
      const m = JSON.parse(e.data);
      epoch = m.epoch;
      loss = m.loss.toFixed(4);
      acc = m.accuracy.toFixed(4);
      drawChart(m.epoch, m.loss, m.accuracy);
    };
  }
  </script>
</body>
</html>

- รหัสนักศึกษา: เปลี่ยน 69000000 เป็นรหัสจริง

- ชื่อ-นามสกุล: เปลี่ยน ชื่อ นามสกุล เป็นชื่อจริง

- ปุ่ม "เริ่มฝึกสอน" เชื่อมกับ SSE endpoint

- EventSource('/train/') รับข้อมูลแบบ real-time

- ใช้ Canvas หรือ Chart.js สำหรับกราฟ

[สำคัญ] ห้ามลบ student ID และชื่อออกจากหน้า — ต้องเห็นชัดเจนเมื่อเปิดหน้า

วิธีรันและตรวจสอบ

# 1. Clone repo และ checkout branch
git clone <DL69-repo>
cd DL69
git checkout wk09

# 2. ติดตั้ง dependencies
uv sync

# 3. รัน server
uv run manage.py runserver

# 4. เปิดเบราว์เซอร์
#    http://127.0.0.1:8000/
#    → เห็นรหัสนักศึกษาและชื่อ
#    → กด "เริ่มฝึกสอน"
#    → เห็น loss, accuracy อัปเดตแบบ real-time
#    → หลังฝึกเสร็จ เห็น loss curve PNG

# 5. ตรวจสอบไฟล์ผลลัพธ์
ls dashboard/static/dashboard/
#    → loss_curve.png
#    → (ไฟล์อื่น ๆ ที่สร้าง)

- ขั้นตอนที่ 1: Clone repo แล้ว checkout branch wk09

- ขั้นตอนที่ 2: รัน uv sync เพื่อติดตั้ง dependencies

- ขั้นตอนที่ 3: รัน uv run manage.py runserver

- ขั้นตอนที่ 4: เปิด http://127.0.0.1:8000/

- ขั้นตอนที่ 5: ตรวจสอบว่าหน้า landing แสดงรหัสและชื่อ

[สำคัญ] ต้องรันได้ด้วย uv sync + uv run manage.py runserver เท่านั้น

การส่งงาน

- Branch name: wk09

- Repo: DL69 (GitHub repository ของนักศึกษา)

- สร้าง branch ใหม่จาก main

- Commit โค้ดทั้งหมดลง branch wk09

- Push ขึ้น GitHub

- แจ้ง URL ของ repo ให้อาจารย์

[สำคัญ] ห้าม commit ไฟล์ data ขนาดใหญ่ (>10MB) — ใช้ .gitignore

# สร้างและ push branch
git checkout -b wk09
git add .
git commit -m "wk09: Perceptron Dashboard"
git push origin wk09

# โครงสร้างไฟล์ที่ต้องมี
DL69/wk09/
├── pyproject.toml
├── manage.py
├── mysite/
├── dashboard/
│   ├── views.py
│   ├── ml/train.py       ← โค้ดที่เขียน
│   └── templates/
│       └── dashboard/
│           └── index.html ← ใส่รหัส+ชื่อ
└── data/

# ตรวจสอบก่อนส่ง
uv sync
uv run manage.py runserver
# → หน้า landing แสดงรหัสและชื่อ
# → กดเริ่มฝึกสอน → SSE ทำงาน
# → ได้ loss_curve.png

เกณฑ์การให้คะแนน

- โมเดลถูกต้อง (30%): Perceptron + training loop ทำงานได้

- SSE Streaming (20%): ฝึกสอนแบบ real-time ได้

- หน้า landing (15%): แสดงรหัสและชื่อชัดเจน

- ผลลัพธ์ (15%): loss curve, ตารางเปรียบเทียบ lr

- โค้ดสะอาด (10%): โครงสร้างดี, มี docstring

- รันได้จริง (10%): uv sync + runserver ไม่ error

[คะแนนรวม] 100% = คะแนนการบ้านสัปดาห์ที่ 9

# ตรวจสอบก่อนส่ง:

# 1. uv sync สำเร็จ?
uv sync

# 2. server รันได้?
uv run manage.py runserver

# 3. หน้า landing แสดงรหัส+ชื่อ?
#    เปิด http://127.0.0.1:8000/

# 4. SSE ทำงาน?
#    กด "เริ่มฝึกสอน" แล้วเห็น
#    epoch, loss, accuracy อัปเดต

# 5. ผลลัพธ์ครบถ้วน?
#    - loss_curve.png มีอยู่
#    - ตาราง lr เปรียบเทียบ

# 6. Branch ชื่อ wk09?
git branch
#    → * wk09