Timeseries LSTM Dashboard
สร้าง Django dashboard สำหรับทำนายข้อมูลอนุกรมเวลาด้วย LSTM
1. ข้อกำหนดโครงงาน
2. โครงสร้าง Django project
3. สิ่งที่ต้องทำใน ml/train.py
4. หน้า landing page
5. วิธีรันและตรวจสอบ
6. การส่งงาน
- โมเดล: LSTM สำหรับทำนายอุณหภูมิ (หรือข้อมูลอนุกรมเวลาอื่น)
- ข้อมูล: ใช้ sliding window — เปลี่ยนข้อมูลอนุกรมเวลาเป็น supervised learning
- Train/Val split: แบ่งข้อมูลฝึกสอนและตรวจสอบ
- Dashboard: SSE streaming แสดง loss, ผลทำนายแบบ real-time
- หน้า landing: แสดง รหัสนักศึกษา และ ชื่อ-นามสกุล (hardcoded)
[สำคัญ] ใช้ Django + PyTorch LSTM เท่านั้น ห้ามใช้ TensorFlow
# ผลลัพธ์ที่คาดหวัง: 1. เริ่ม server แล้วเห็นหน้า landing page ที่มีรหัสนักศึกษาและชื่อ-นามสกุล 2. กดปุ่ม "เริ่มฝึกสอน" แล้วเห็น - ค่า loss ลดลงแบบ real-time - กราฟ training loss อัปเดตทุก epoch 3. หลังฝึกสอนเสร็จ แสดงผลลัพธ์ - กราฟ predicted vs actual values - ค่า MSE/RMSE บน validation set 4. หน้า landing page แสดงรหัสและชื่อ ของนักศึกษาที่ทำโครงงาน
DL69/wk11/ ├── 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
- data/: ใส่ข้อมูลอนุกรมเวลา (เช่น CSV อุณหภูมิ)
[สำคัญ] ห้ามลบหรือแก้ไขไฟล์ที่ไม่ได้ระบุว่าต้องแก้ — ใช้ไฟล์เดิมที่ให้มา
def train(on_progress=None):
"""
on_progress(epoch, loss, val_loss) → เรียกทุก epoch
"""
import torch
import torch.nn as nn
# 1. โหลดข้อมูลอนุกรมเวลา
# data = read_csv('data/temperature.csv')
# 2. Sliding window → supervised learning
# window_size = 24 (เช่น 24 ชั่วโมงย้อนหลัง)
# X[i] = data[i:i+window_size]
# y[i] = data[i+window_size]
# 3. Train/Val split (80/20)
# 4. สร้างโมเดล LSTM
class LSTMModel(nn.Module):
def __init__(self):
super().__init__()
self.lstm = nn.LSTM(input_size=1,
hidden_size=64,
num_layers=2,
batch_first=True)
self.fc = nn.Linear(64, 1)
def forward(self, x):
out, _ = self.lstm(x)
return self.fc(out[:, -1, :])
# 5. Training loop
for epoch in range(num_epochs):
# forward, loss, backward, step
# เรียก on_progress(epoch, loss, val_loss)
pass
# 6. บันทึกผลลัพธ์
# - predicted vs actual plot → PNG
# - training loss curve → PNG
- ข้อ 1: โหลดข้อมูล CSV แล้วแปลงเป็น sliding window
- ข้อ 2: สร้าง LSTM model ด้วย nn.LSTM
- ข้อ 3: Training loop พร้อม train/val split
- ข้อ 4: เรียก on_progress(epoch, loss, val_loss) ทุก epoch
- ข้อ 5: บันทึกกราฟ predicted vs actual เป็น PNG
[เคล็ดลับ] ดู code ตัวอย่างจาก wk11.html slides เป็นแนวทาง
<!-- dashboard/templates/dashboard/index.html -->
<!DOCTYPE html>
<html lang="th">
<head>
<title>Timeseries LSTM 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, valLoss: 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>Val Loss: <span x-text="valLoss"></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);
valLoss = m.val_loss.toFixed(4);
drawChart(m.epoch, m.loss, m.val_loss);
};
}
</script>
</body>
</html>
- รหัสนักศึกษา: เปลี่ยน 69000000 เป็นรหัสจริง
- ชื่อ-นามสกุล: เปลี่ยน ชื่อ นามสกุล เป็นชื่อจริง
- ปุ่ม "เริ่มฝึกสอน" เชื่อมกับ SSE endpoint
- แสดงทั้ง training loss และ validation loss
- ใช้ Canvas หรือ Chart.js สำหรับกราฟ
[สำคัญ] ห้ามลบ student ID และชื่อออกจากหน้า — ต้องเห็นชัดเจนเมื่อเปิดหน้า
# 1. Clone repo และ checkout branch git clone <DL69-repo> cd DL69 git checkout wk11 # 2. ติดตั้ง dependencies uv sync # 3. รัน server uv run manage.py runserver # 4. เปิดเบราว์เซอร์ # http://127.0.0.1:8000/ # → เห็นรหัสนักศึกษาและชื่อ # → กด "เริ่มฝึกสอน" # → เห็น loss, val_loss อัปเดตแบบ real-time # → หลังฝึกเสร็จ เห็น predicted vs actual plot # 5. ตรวจสอบไฟล์ผลลัพธ์ ls dashboard/static/dashboard/ # → loss_curve.png # → prediction_plot.png
- ขั้นตอนที่ 1: Clone repo แล้ว checkout branch wk11
- ขั้นตอนที่ 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: wk11
- Repo: DL69 (GitHub repository ของนักศึกษา)
- สร้าง branch ใหม่จาก main
- Commit โค้ดทั้งหมดลง branch wk11
- Push ขึ้น GitHub
- แจ้ง URL ของ repo ให้อาจารย์
[สำคัญ] ห้าม commit ไฟล์ data ขนาดใหญ่ (>10MB) — ใช้ .gitignore
# สร้างและ push branch
git checkout -b wk11
git add .
git commit -m "wk11: Timeseries LSTM Dashboard"
git push origin wk11
# โครงสร้างไฟล์ที่ต้องมี
DL69/wk11/
├── pyproject.toml
├── manage.py
├── mysite/
├── dashboard/
│ ├── views.py
│ ├── ml/train.py ← โค้ดที่เขียน
│ └── templates/
│ └── dashboard/
│ └── index.html ← ใส่รหัส+ชื่อ
└── data/
└── temperature.csv ← ข้อมูล
# ตรวจสอบก่อนส่ง
uv sync
uv run manage.py runserver
# → หน้า landing แสดงรหัสและชื่อ
# → กดเริ่มฝึกสอน → SSE ทำงาน
# → ได้ prediction_plot.png
- โมเดลถูกต้อง (30%): LSTM + sliding window ทำงานได้
- SSE Streaming (20%): ฝึกสอนแบบ real-time ได้
- หน้า landing (15%): แสดงรหัสและชื่อชัดเจน
- ผลลัพธ์ (15%): predicted vs actual plot, MSE/RMSE
- โค้ดสะอาด (10%): โครงสร้างดี, มี docstring
- รันได้จริง (10%): uv sync + runserver ไม่ error
[คะแนนรวม] 100% = คะแนนการบ้านสัปดาห์ที่ 11
# ตรวจสอบก่อนส่ง: # 1. uv sync สำเร็จ? uv sync # 2. server รันได้? uv run manage.py runserver # 3. หน้า landing แสดงรหัส+ชื่อ? # เปิด http://127.0.0.1:8000/ # 4. SSE ทำงาน? # กด "เริ่มฝึกสอน" แล้วเห็น # epoch, loss, val_loss อัปเดต # 5. ผลลัพธ์ครบถ้วน? # - loss_curve.png มีอยู่ # - prediction_plot.png มีอยู่ # 6. Branch ชื่อ wk11? git branch # → * wk11