วงรอบการฝึก: ค่าความสูญเสีย ตัวปรับปรุง และยุคการฝึก
ผู้เรียนจะเขียนวงรอบการฝึก PyTorch ได้แก่ zero_grad, forward คำนวณ CrossEntropyLoss, backward, optimizer.step และติดตามค่าความสูญเสียกับความแม่นยำตลอดแต่ละยุค
วงรอบการฝึก: ค่าความสูญเสีย ตัวปรับปรุง และยุคการฝึก เป็นบทเรียน Machine Learning Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Machine Learning Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Machine Learning Academy มีบทเรียนทั้งหมด 4 บทเรียน
สี่ขั้นตอนของลูปการฝึกทุกแบบ
ลูปการฝึกของ PyTorch มีสี่ขั้นตอนที่ต้องทำซ้ำสำหรับทุกชุดข้อมูล ได้แก่ (1) ล้างแกรเดียนต์ (2) การส่งข้อมูลไปข้างหน้า (3) การส่งข้อมูลย้อนกลับ และ (4) ขั้นตอนของตัวเพิ่มประสิทธิภาพ การข้ามหรือสลับลำดับขั้นตอนเหล่านี้จะทำให้ได้ผลลัพธ์ผิดโดยอาจไม่แสดงข้อผิดพลาดอย่างชัดเจน เช่น แกรเดียนต์สะสม พารามิเตอร์ถูกอัปเดตไม่ถูกต้อง หรือเกิดหน่วยความจำรั่ว การทำความเข้าใจรูปแบบนี้จนคุ้นเคยเป็นนิสัยที่สำคัญที่สุดสำหรับการฝึกเครือข่ายประสาทเทียมด้วย PyTorch
import torch
import torch.nn as nn
import torch.optim as optim
model = nn.Linear(2, 1)
optimizer = optim.SGD(model.parameters(), lr=0.01)
criterion = nn.MSELoss()
X = torch.randn(20, 2)
y = torch.randn(20, 1)
for step in range(1):
optimizer.zero_grad() # (1) zero grads
y_pred = model(X) # (2) forward
loss = criterion(y_pred, y) # (2) loss
loss.backward() # (3) backward
optimizer.step() # (4) update
print('Loss:', loss.item())ฟังก์ชันการสูญเสีย: การเลือกเกณฑ์ที่เหมาะสม
ฟังก์ชันการสูญเสียใช้วัดว่าการคาดการณ์ของโมเดลคลาดเคลื่อนมากเพียงใด โมดูล nn ของ PyTorch มีฟังก์ชันประเภทนี้อยู่หลายแบบ ได้แก่ nn.MSELoss สำหรับการถดถอย (ค่าคลาดเคลื่อนกำลังสองเฉลี่ย), nn.CrossEntropyLoss สำหรับการจำแนกประเภทหลายกลุ่ม (รวมลอจิกซอฟต์แมกซ์กับ NLL) และ nn.BCEWithLogitsLoss สำหรับการจำแนกประเภทแบบทวิภาค (รวมซิกมอยด์กับครอสเอนโทรปีแบบทวิภาค) การใช้ฟังก์ชันการสูญเสียไม่ตรงกับงานเป็นข้อผิดพลาดที่ผู้เริ่มต้นมักทำ ซึ่งทำให้โมเดลไม่สามารถเรียนรู้ได้
import torch
import torch.nn as nn
# Regression
mse = nn.MSELoss()
y_pred = torch.tensor([2.5, 3.0])
y_true = torch.tensor([2.0, 3.5])
print('MSE:', mse(y_pred, y_true).item())
# Multi-class: logits (raw scores), not softmax
ce = nn.CrossEntropyLoss()
logits = torch.tensor([[2.0, 0.5, 1.0]])
labels = torch.tensor([0])
print('CE:', ce(logits, labels).item())ตัวเพิ่มประสิทธิภาพ: SGD, Adam และ AdamW
ตัวปรับค่าการเรียนรู้ใช้เกรเดียนต์ที่คำนวณได้เพื่ออัปเดตพารามิเตอร์ของโมเดล SGD (การลดลงตามเกรเดียนต์แบบสุ่ม) เป็นตัวปรับค่าการเรียนรู้แบบดั้งเดิม การเพิ่ม momentum จะช่วยเร่งการลู่เข้า Adam จะปรับอัตราการเรียนรู้แยกตามพารามิเตอร์ โดยใช้ค่าประมาณโมเมนต์อันดับที่หนึ่งและสอง จึงมักลู่เข้าได้เร็วกว่าในทางปฏิบัติ AdamW เพิ่มการลดค่าน้ำหนักที่เหมาะสม (การทำให้เป็นระเบียบแบบ L2) และเป็นตัวเลือกเริ่มต้นสำหรับโมเดลทรานส์ฟอร์เมอร์ ตัวปรับค่าการเรียนรู้ทั้งหมดอยู่ใน torch.optim
import torch.optim as optim
import torch.nn as nn
model = nn.Linear(4, 2)
# Stochastic Gradient Descent with momentum
sgd = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
# Adam: adaptive learning rate
adam = optim.Adam(model.parameters(), lr=0.001,
betas=(0.9, 0.999))
# AdamW: Adam + proper weight decay
adamw = optim.AdamW(model.parameters(), lr=0.001,
weight_decay=0.01)วนซ้ำตามยุคและชุดข้อมูลย่อย
โดยทั่วไป การฝึกจะทำงานหลายยุค ซึ่งหมายถึงการประมวลผลชุดข้อมูลฝึกครบหนึ่งรอบ ภายในแต่ละยุค คุณจะวนซ้ำผ่านชุดข้อมูลย่อย ซึ่งเป็นส่วนย่อยของข้อมูล การใช้ DataLoader จะจัดการสับเปลี่ยนลำดับและแบ่งชุดข้อมูลโดยอัตโนมัติ การติดตามค่าการสูญเสียเฉลี่ยต่อยุคช่วยให้คุณตรวจสอบได้ว่าโมเดลกำลังลู่เข้าหรือไม่ การพิมพ์ผลทุกยุค (หรือทุก ๆ N ชุดข้อมูลย่อย) ช่วยให้เห็นความคืบหน้าของการฝึก
import torch
from torch.utils.data import TensorDataset, DataLoader
import torch.nn as nn
import torch.optim as optim
X = torch.randn(200, 4)
y = torch.randn(200, 1)
dataset = TensorDataset(X, y)
loader = DataLoader(dataset, batch_size=32, shuffle=True)
model = nn.Linear(4, 1)
optimizer = optim.Adam(model.parameters())
criterion = nn.MSELoss()
for epoch in range(3):
total_loss = 0
for X_batch, y_batch in loader:
optimizer.zero_grad()
pred = model(X_batch)
loss = criterion(pred, y_batch)
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f'Epoch {epoch}: avg_loss={total_loss/len(loader):.4f}')DataLoader: การแบ่งและสับเปลี่ยนข้อมูล
DataLoader ห่อหุ้มชุดข้อมูลและจัดเตรียมตัววนซ้ำที่ส่งคืนชุดข้อมูลย่อย พารามิเตอร์สำคัญ ได้แก่ batch_size ซึ่งกำหนดจำนวนตัวอย่างต่อการอัปเดตเกรเดียนต์ shuffle=True ซึ่งสุ่มลำดับใหม่ในแต่ละยุค (สำคัญอย่างยิ่งต่อการฝึก) และ num_workers ซึ่งเปิดใช้การโหลดข้อมูลแบบขนาน สำหรับชุดข้อมูลที่กำหนดเอง ให้สร้างคลาสย่อยจาก torch.utils.data.Dataset และใช้งาน __len__ กับ __getitem__
import torch
from torch.utils.data import Dataset, DataLoader
class MyDataset(Dataset):
def __init__(self, X, y):
self.X = X
self.y = y
def __len__(self):
return len(self.X)
def __getitem__(self, idx):
return self.X[idx], self.y[idx]
X = torch.randn(100, 5)
y = torch.randint(0, 3, (100,))
dataset = MyDataset(X, y)
loader = DataLoader(dataset, batch_size=16, shuffle=True)
X_batch, y_batch = next(iter(loader))
print(X_batch.shape) # torch.Size([16, 5])CrossEntropyLoss: ลอจิตและดัชนีคลาส
CrossEntropyLoss ต้องการลอจิตดิบ (คะแนนที่ยังไม่ทำให้เป็นมาตรฐาน) ไม่ใช่ความน่าจะเป็นจากซอฟต์แมกซ์ ภายในจะใช้ลอ็กซอฟต์แมกซ์และคำนวณค่าความน่าจะเป็นติดลบแบบลอการิทึม ป้ายกำกับเป้าหมายควรเป็นดัชนีคลาสจำนวนเต็ม (ไม่ใช่เวกเตอร์แบบวันฮอต) นี่คือฟังก์ชันการสูญเสียที่เหมาะสมสำหรับการจำแนกหลายคลาส และมีเสถียรภาพเชิงตัวเลขมากกว่าการใช้ซอฟต์แมกซ์แล้วตามด้วย NLLLoss ด้วยตนเอง ชั้นสุดท้ายของโมเดลไม่ควรมีการทำงานของซอฟต์แมกซ์เมื่อใช้ฟังก์ชันการสูญเสียนี้
import torch
import torch.nn as nn
criterion = nn.CrossEntropyLoss()
# Batch of 4 samples, 3 classes
logits = torch.tensor([
[2.1, 0.5, 0.3],
[0.1, 3.0, 0.2],
[0.8, 0.9, 2.0],
[1.5, 0.1, 0.4]
])
# True labels as class indices (not one-hot)
labels = torch.tensor([0, 1, 2, 0])
loss = criterion(logits, labels)
print('Loss:', loss.item())ติดตามความแม่นยำระหว่างการฝึก
การที่ค่าการสูญเสียลดลงยืนยันว่าโมเดลกำลังเรียนรู้ แต่ความแม่นยำจะบอกว่าการทำนายนั้นถูกต้องจริงหรือไม่ สำหรับการจำแนกหลายคลาส ให้แปลงลอจิตเป็นคลาสที่ทำนายด้วย torch.argmax ตามมิติของคลาส แล้วเปรียบเทียบกับป้ายกำกับจริง การติดตามทั้งค่าการสูญเสียและความแม่นยำระหว่างการฝึก รวมถึงความแม่นยำในการตรวจสอบความถูกต้องหากต้องการ จะให้ภาพรวมที่ครบถ้วนของพลวัตการเรียนรู้
import torch
def compute_accuracy(logits, labels):
preds = torch.argmax(logits, dim=1)
correct = (preds == labels).sum().item()
return correct / len(labels)
logits = torch.tensor([
[2.0, 0.1, 0.3],
[0.1, 0.2, 3.5],
[1.0, 0.5, 0.2]
])
labels = torch.tensor([0, 2, 0])
print('Accuracy:', compute_accuracy(logits, labels))
# 1.0 (all three correct)วงรอบตรวจสอบความถูกต้อง: ประเมินโดยไม่อัปเดต
หลังจากแต่ละยุคของการฝึก ให้เรียกใช้วงรอบตรวจสอบความถูกต้องเพื่อประเมินประสิทธิภาพกับข้อมูลที่ไม่เคยเห็นมาก่อน ห่อการทำงานด้วย torch.no_grad() เพื่อปิดการคำนวณเกรเดียนต์ และเรียกใช้ model.eval() เพื่อปิดความไม่แน่นอนแบบสุ่มของ Dropout และ BatchNorm การเปรียบเทียบค่าการสูญเสียระหว่างการฝึกกับการตรวจสอบความถูกต้องเป็นเครื่องมือหลักในการตรวจจับการเรียนรู้เกินพอดี เมื่อค่าการสูญเสียในการตรวจสอบความถูกต้องเพิ่มขึ้น ขณะที่ค่าการสูญเสียในการฝึกยังลดลง แสดงว่าโมเดลเรียนรู้ชุดฝึกเกินพอดี
import torch
def validate(model, val_loader, criterion):
model.eval()
total_loss = 0
with torch.no_grad():
for X_batch, y_batch in val_loader:
logits = model(X_batch)
loss = criterion(logits, y_batch)
total_loss += loss.item()
model.train() # restore training mode
return total_loss / len(val_loader)
# Usage inside training loop:
# val_loss = validate(model, val_loader, criterion)
# print(f'Val loss: {val_loss:.4f}')การจัดตารางอัตราการเรียนรู้
อัตราการเรียนรู้คงที่มักทำให้การลู่เข้าช้าหรือเกิดการแกว่งใกล้ค่าต่ำสุด ตัวจัดตารางอัตราการเรียนรู้จะปรับ LR โดยอัตโนมัติระหว่างการฝึก StepLR ลด LR ด้วยตัวคูณทุก ๆ N ยุค CosineAnnealingLR ลดค่าลงอย่างราบรื่นจนเกือบเป็นศูนย์ตามเส้นโคไซน์ และ ReduceLROnPlateau ลด LR เมื่อค่าการสูญเสียในการตรวจสอบความถูกต้องหยุดปรับปรุง โดยทั่วไปจะเรียกใช้ตัวจัดตารางหลังตัวปรับค่าการเรียนรู้ โดยมักเรียกหนึ่งครั้งต่อยุค
import torch.optim as optim
import torch.nn as nn
model = nn.Linear(4, 2)
optimizer = optim.Adam(model.parameters(), lr=0.01)
# Decay LR by 0.5 every 2 epochs
scheduler = optim.lr_scheduler.StepLR(
optimizer, step_size=2, gamma=0.5
)
for epoch in range(6):
# ... training code ...
scheduler.step()
print(f'Epoch {epoch}: LR={scheduler.get_last_lr()[0]}')
# LR: 0.01, 0.01, 0.005, 0.005, 0.0025, 0.0025บันทึกจุดตรวจสอบระหว่างการฝึก
การฝึกอาจใช้เวลาหลายชั่วโมงหรือหลายวัน การบันทึกจุดตรวจสอบเป็นระยะช่วยป้องกันการสูญเสียความคืบหน้าเมื่อโปรแกรมขัดข้อง และทำให้กลับมาทำต่อจากจุดที่ดีที่สุดได้ จุดตรวจสอบที่ดีจะเก็บพจนานุกรมสถานะของโมเดล พจนานุกรมสถานะของตัวปรับค่าการเรียนรู้ (ซึ่งมีพจน์โมเมนตัม) หมายเลขยุค และเมตริกการตรวจสอบความถูกต้องที่ดีที่สุด การกู้คืนสถานะของตัวปรับค่าการเรียนรู้ทำให้การฝึกดำเนินต่อจากจุดเดิมได้อย่างแม่นยำ รวมถึงบัฟเฟอร์โมเมนตัมที่ส่งผลต่อการอัปเดตครั้งถัดไป
import torch
def save_checkpoint(model, optimizer, epoch, loss, path):
torch.save({
'epoch': epoch,
'model_state_dict': model.state_dict(),
'optimizer_state_dict': optimizer.state_dict(),
'loss': loss
}, path)
def load_checkpoint(model, optimizer, path):
ckpt = torch.load(path)
model.load_state_dict(ckpt['model_state_dict'])
optimizer.load_state_dict(ckpt['optimizer_state_dict'])
return ckpt['epoch'], ckpt['loss']วงรอบการฝึกฉบับสมบูรณ์: นำทุกส่วนมาประกอบกัน
วงรอบการฝึกที่มีคุณภาพระดับใช้งานจริงจะรวมทุกส่วนเข้าด้วยกัน ได้แก่ DataLoader สำหรับแบ่งชุดข้อมูล การอัปเดตสี่ขั้นตอนต่อชุดข้อมูลย่อย การตรวจสอบความถูกต้องในแต่ละยุค การจัดตารางอัตราการเรียนรู้ การติดตามค่าการสูญเสียและความแม่นยำ และการบันทึกจุดตรวจสอบ โค้ดด้านล่างแสดงรูปแบบทั้งหมดด้วยโมเดลจำแนกอย่างง่าย การปรับแม่แบบนี้ให้ใช้กับปัญหาการเรียนรู้แบบมีผู้สอนใด ๆ ต้องเปลี่ยนเพียงโมเดล ชุดข้อมูล และฟังก์ชันการสูญเสีย
import torch, torch.nn as nn, torch.optim as optim
from torch.utils.data import TensorDataset, DataLoader
X_tr = torch.randn(160, 4); y_tr = torch.randint(0, 3, (160,))
X_val = torch.randn(40, 4); y_val = torch.randint(0, 3, (40,))
tr_loader = DataLoader(TensorDataset(X_tr, y_tr), 32, shuffle=True)
val_loader = DataLoader(TensorDataset(X_val, y_val), 32)
model = nn.Sequential(nn.Linear(4, 16), nn.ReLU(), nn.Linear(16, 3))
optimizer = optim.Adam(model.parameters())
criterion = nn.CrossEntropyLoss()
for epoch in range(5):
model.train()
for Xb, yb in tr_loader:
optimizer.zero_grad()
loss = criterion(model(Xb), yb)
loss.backward(); optimizer.step()
model.eval()
with torch.no_grad():
val_loss = sum(criterion(model(Xb), yb).item()
for Xb, yb in val_loader) / len(val_loader)
print(f'Epoch {epoch}: val_loss={val_loss:.3f}')ตรวจสอบความเข้าใจ
ทดสอบความเข้าใจแนวคิดการเรียนรู้ของเครื่องด้วย Python จากบทเรียนนี้
สรุปบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้ว่า วงรอบการฝึกสี่ขั้นตอน (zero_grad, forward, backward, step) เป็นพื้นฐานของการฝึกด้วย PyTorch ทุกแบบ DataLoader จัดการการแบ่งและสับเปลี่ยนข้อมูลโดยอัตโนมัติ และ CrossEntropyLoss ที่ใช้กับลอจิตเป็นตัวเลือกมาตรฐานสำหรับการจำแนก ลำดับถัดไป เราจะสำรวจการจัดตารางอัตราการเรียนรู้และผลกระทบของอัตราการเรียนรู้ต่อพลวัตการฝึก
เรียนรู้ Python ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 30
- บทเรียน
- 120
คำถามที่พบบ่อย
บทเรียน “วงรอบการฝึก: ค่าความสูญเสีย ตัวปรับปรุง และยุคการฝึก” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “วงรอบการฝึก: ค่าความสูญเสีย ตัวปรับปรุง และยุคการฝึก” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Machine Learning Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Machine Learning Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “วงรอบการฝึก: ค่าความสูญเสีย ตัวปรับปรุง และยุคการฝึก”
ผู้เรียนจะเขียนวงรอบการฝึก PyTorch ได้แก่ zero_grad, forward คำนวณ CrossEntropyLoss, backward, optimizer.step และติดตามค่าความสูญเสียกับความแม่นยำตลอดแต่ละยุค คุณปฏิบัติ Machine Learning Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Machine Learning Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Machine Learning Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “วงรอบการฝึก: ค่าความสูญเสีย ตัวปรับปรุง และยุคการฝึก” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Machine Learning Academy นี้ได้ไหม
ได้ บทเรียน Machine Learning Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เทนเซอร์ PyTorch: การสร้าง การดำเนินการ และการถ่ายโอนไปยัง GPU
- Autograd: การหาอนุพันธ์อัตโนมัติสำหรับการแพร่ย้อนกลับ
- การสร้างเครือข่ายแบบป้อนไปข้างหน้าด้วย nn.Module
- วงรอบการฝึก: ค่าความสูญเสีย ตัวปรับปรุง และยุคการฝึก