Computer Vision ด้วย PyTorch ในปี 2026: CNN, Transfer Learning และคำถามสัมภาษณ์
Computer vision ด้วย PyTorch: สร้าง CNN ตั้งแต่เริ่มต้น, ประยุกต์ใช้ transfer learning กับโมเดล pretrained และเตรียมตัวสำหรับการสัมภาษณ์เทคนิค

Computer vision ด้วย PyTorch ได้กลายเป็นแนวทางหลักสำหรับการจำแนกภาพ การตรวจจับวัตถุ และงานจดจำภาพในปี 2026 บทความนี้ครอบคลุมการสร้าง CNN ตั้งแต่เริ่มต้น การประยุกต์ใช้ transfer learning กับโมเดล pretrained และการเตรียมตัวสำหรับคำถามสัมภาษณ์ด้านเทคนิค
PyTorch 2.4 แนะนำ torch.compile() เป็นค่าเริ่มต้นสำหรับการดำเนินการ CNN ให้ความเร็วเพิ่มขึ้น 30-50% บน GPU สมัยใหม่โดยไม่ต้องเปลี่ยนแปลงโค้ด ตัวอย่างทั้งหมดในบทความนี้เข้ากันได้กับ PyTorch 2.4+
ทำความเข้าใจ Convolutional Neural Networks สำหรับการจำแนกภาพ
Convolutional Neural Networks สกัดคุณลักษณะแบบลำดับชั้นจากภาพผ่านตัวกรองที่เรียนรู้ได้ ต่างจากเครือข่าย fully connected ตรงที่ CNN รักษาความสัมพันธ์เชิงพื้นที่ระหว่างพิกเซล ทำให้เหมาะสำหรับงานด้านการมองเห็น สถาปัตยกรรมประกอบด้วยเลเยอร์ convolution ที่ตรวจจับขอบและรูปแบบ เลเยอร์ pooling ที่ลดมิติ และเลเยอร์ fully connected ที่ทำการจำแนก
การดำเนินการ convolution เลื่อนตัวกรองขนาดเล็ก (โดยทั่วไป 3x3 หรือ 5x5) ข้ามภาพอินพุต คำนวณ dot product ที่แต่ละตำแหน่ง กระบวนการนี้สร้าง feature map ที่เน้นรูปแบบเฉพาะ เช่น ขอบ พื้นผิว หรือรูปทรง เลเยอร์ที่ลึกกว่าจะรวมคุณลักษณะระดับต่ำเหล่านี้เข้าเป็นการแสดงที่ซับซ้อน—ใบหน้า วัตถุ หรือฉาก
# cnn_architecture.py
import torch
import torch.nn as nn
class SimpleCNN(nn.Module):
"""Basic CNN for CIFAR-10 classification (32x32 RGB images, 10 classes)"""
def __init__(self, num_classes: int = 10):
super().__init__()
# First conv block: 3 input channels (RGB) -> 32 feature maps
self.conv1 = nn.Sequential(
nn.Conv2d(3, 32, kernel_size=3, padding=1), # Output: 32x32x32
nn.BatchNorm2d(32), # Normalize activations for stable training
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2) # Output: 16x16x32
)
# Second conv block: increase depth for richer features
self.conv2 = nn.Sequential(
nn.Conv2d(32, 64, kernel_size=3, padding=1), # Output: 16x16x64
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2) # Output: 8x8x64
)
# Third conv block: capture high-level patterns
self.conv3 = nn.Sequential(
nn.Conv2d(64, 128, kernel_size=3, padding=1), # Output: 8x8x128
nn.BatchNorm2d(128),
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2) # Output: 4x4x128
)
# Classifier head
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(128 * 4 * 4, 256),
nn.ReLU(inplace=True),
nn.Dropout(0.5), # Prevent overfitting
nn.Linear(256, num_classes)
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
x = self.conv1(x)
x = self.conv2(x)
x = self.conv3(x)
return self.classifier(x)สถาปัตยกรรมนี้เพิ่มจำนวนตัวกรองอย่างต่อเนื่อง (32 → 64 → 128) ในขณะที่ลดมิติเชิงพื้นที่ผ่าน pooling BatchNorm ทำให้การฝึกมีเสถียรภาพด้วยการ normalize เอาต์พุตของเลเยอร์ ในขณะที่ Dropout ป้องกันไม่ให้ classifier จดจำตัวอย่างการฝึก
การฝึก CNN ด้วย PyTorch DataLoaders
การโหลดข้อมูลอย่างมีประสิทธิภาพเป็นสิ่งสำคัญสำหรับการใช้งาน GPU ในระหว่างการฝึก DataLoader ของ PyTorch จัดการ batching, shuffling และการโหลดข้อมูลแบบขนานโดยอัตโนมัติ การเพิ่มข้อมูลที่เหมาะสม—random crop, flip และ color jitter—ปรับปรุงการ generalize บนภาพที่ไม่เคยเห็นอย่างมีนัยสำคัญ
# train_cnn.py
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
# Data augmentation for training (reduces overfitting)
train_transform = transforms.Compose([
transforms.RandomHorizontalFlip(p=0.5),
transforms.RandomCrop(32, padding=4), # Random crop with padding
transforms.ColorJitter(brightness=0.2, contrast=0.2),
transforms.ToTensor(),
transforms.Normalize((0.4914, 0.4822, 0.4465), # CIFAR-10 mean
(0.2470, 0.2435, 0.2616)) # CIFAR-10 std
])
# No augmentation for validation (deterministic evaluation)
val_transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.4914, 0.4822, 0.4465),
(0.2470, 0.2435, 0.2616))
])
def train_model(model: nn.Module, epochs: int = 20) -> dict:
"""Train CNN with standard best practices"""
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
# Load CIFAR-10 dataset
train_data = datasets.CIFAR10(root="./data", train=True,
download=True, transform=train_transform)
val_data = datasets.CIFAR10(root="./data", train=False,
transform=val_transform)
# DataLoaders with num_workers for parallel loading
train_loader = DataLoader(train_data, batch_size=128, shuffle=True,
num_workers=4, pin_memory=True)
val_loader = DataLoader(val_data, batch_size=256, shuffle=False,
num_workers=4, pin_memory=True)
criterion = nn.CrossEntropyLoss()
optimizer = optim.AdamW(model.parameters(), lr=1e-3, weight_decay=1e-4)
scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=epochs)
best_acc = 0.0
for epoch in range(epochs):
model.train()
for images, labels in train_loader:
images, labels = images.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
scheduler.step()
# Validation
model.eval()
correct, total = 0, 0
with torch.no_grad():
for images, labels in val_loader:
images, labels = images.to(device), labels.to(device)
outputs = model(images)
_, predicted = outputs.max(1)
total += labels.size(0)
correct += predicted.eq(labels).sum().item()
acc = 100. * correct / total
best_acc = max(best_acc, acc)
print(f"Epoch {epoch+1}/{epochs} - Val Acc: {acc:.2f}%")
return {"best_accuracy": best_acc}การเพิ่มประสิทธิภาพการฝึกที่สำคัญ ได้แก่: pin_memory=True สำหรับการถ่ายโอน CPU-ไป-GPU ที่เร็วขึ้น, num_workers สำหรับการโหลดข้อมูลแบบขนาน, optimizer AdamW พร้อม weight decay สำหรับ regularization และตารางเวลา learning rate cosine annealing สำหรับการลู่เข้าที่ราบรื่น
Transfer Learning ด้วย Pretrained ResNet และ EfficientNet
Transfer learning ใช้ประโยชน์จากโมเดลที่ฝึกมาแล้วบน ImageNet (1.2 ล้านภาพ, 1000 คลาส) และปรับให้เข้ากับชุดข้อมูลที่กำหนดเอง แนวทางนี้ให้ความแม่นยำสูงกว่าด้วยข้อมูลการฝึกและเวลาการคำนวณที่น้อยกว่า torchvision.models ของ PyTorch มีสถาปัตยกรรมที่ทันสมัยที่สุดพร้อม weights pretrained
แนวทางมาตรฐานคือการแช่แข็งเลเยอร์ convolution แรกๆ (ที่ตรวจจับคุณลักษณะสากล เช่น ขอบ) และ fine-tune เลเยอร์หลังๆ รวมถึงหัว classification ใหม่สำหรับงานเป้าหมาย
# transfer_learning.py
import torch
import torch.nn as nn
from torchvision import models
from torchvision.models import ResNet50_Weights, EfficientNet_B0_Weights
def create_transfer_model(
model_name: str = "resnet50",
num_classes: int = 10,
freeze_backbone: bool = True
) -> nn.Module:
"""Create a pretrained model with custom classification head"""
if model_name == "resnet50":
# Load ResNet50 with ImageNet weights
model = models.resnet50(weights=ResNet50_Weights.IMAGENET1K_V2)
# Replace final fully connected layer
in_features = model.fc.in_features # 2048 for ResNet50
model.fc = nn.Sequential(
nn.Dropout(0.3),
nn.Linear(in_features, num_classes)
)
elif model_name == "efficientnet_b0":
# EfficientNet: better accuracy/compute tradeoff
model = models.efficientnet_b0(weights=EfficientNet_B0_Weights.IMAGENET1K_V1)
in_features = model.classifier[1].in_features # 1280 for B0
model.classifier = nn.Sequential(
nn.Dropout(0.2),
nn.Linear(in_features, num_classes)
)
if freeze_backbone:
# Freeze all layers except classifier
for name, param in model.named_parameters():
if "fc" not in name and "classifier" not in name:
param.requires_grad = False
return model
def count_trainable_params(model: nn.Module) -> int:
"""Count parameters that will be updated during training"""
return sum(p.numel() for p in model.parameters() if p.requires_grad)
# Example usage
model = create_transfer_model("resnet50", num_classes=5, freeze_backbone=True)
print(f"Trainable parameters: {count_trainable_params(model):,}")
# Output: ~10,245 (only classifier) vs ~25 million (full ResNet50)การแช่แข็ง backbone ลดพารามิเตอร์ที่ฝึกได้จาก 25 ล้านเหลือประมาณ 10,000 ทำให้สามารถฝึกบนชุดข้อมูลขนาดเล็กโดยไม่เกิด overfitting สำหรับชุดข้อมูลขนาดใหญ่ (10,000+ ภาพ) ค่อยๆ ปลดล็อคเลเยอร์หลังๆ โดยใช้ differential learning rates—อัตราต่ำกว่าสำหรับเลเยอร์ pretrained, อัตราสูงกว่าสำหรับ classifier ใหม่
พร้อมที่จะพิชิตการสัมภาษณ์ Data Science & ML แล้วหรือยังครับ?
ฝึกฝนด้วยตัวจำลองแบบโต้ตอบ, flashcards และแบบทดสอบเทคนิคครับ
กลยุทธ์การเพิ่มข้อมูลสำหรับ Computer Vision
การเพิ่มข้อมูลขยายชุดการฝึกโดยเทียมด้วยการใช้การแปลงที่รักษาเนื้อหาเชิงความหมาย การเพิ่มข้อมูลสมัยใหม่ไปไกลกว่าการพลิกและหมุนพื้นฐาน—เทคนิคอย่าง MixUp และ CutOut สร้างตัวอย่างการฝึกสังเคราะห์ที่ปรับปรุงความทนทานของโมเดล
# augmentation_strategies.py
import torch
import torchvision.transforms.v2 as T
from torchvision.transforms.v2 import functional as F
# Modern augmentation pipeline using torchvision v2 transforms
advanced_augmentation = T.Compose([
T.RandomResizedCrop(224, scale=(0.8, 1.0)), # Random crop and resize
T.RandomHorizontalFlip(p=0.5),
T.RandomVerticalFlip(p=0.1), # Less common but useful for some domains
T.RandomRotation(degrees=15),
T.ColorJitter(brightness=0.3, contrast=0.3, saturation=0.3, hue=0.1),
T.RandomAffine(degrees=0, translate=(0.1, 0.1)), # Small translations
T.GaussianBlur(kernel_size=3, sigma=(0.1, 2.0)),
T.ToImage(),
T.ToDtype(torch.float32, scale=True),
T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
class CutOut:
"""Randomly mask out square regions of the image"""
def __init__(self, n_holes: int = 1, length: int = 16):
self.n_holes = n_holes
self.length = length
def __call__(self, img: torch.Tensor) -> torch.Tensor:
h, w = img.shape[1], img.shape[2]
mask = torch.ones_like(img)
for _ in range(self.n_holes):
y = torch.randint(0, h, (1,)).item()
x = torch.randint(0, w, (1,)).item()
y1 = max(0, y - self.length // 2)
y2 = min(h, y + self.length // 2)
x1 = max(0, x - self.length // 2)
x2 = min(w, x + self.length // 2)
mask[:, y1:y2, x1:x2] = 0
return img * mask
def mixup_data(
x: torch.Tensor,
y: torch.Tensor,
alpha: float = 0.4
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, float]:
"""MixUp: blend two images and their labels"""
lam = torch.distributions.Beta(alpha, alpha).sample().item()
batch_size = x.size(0)
index = torch.randperm(batch_size)
mixed_x = lam * x + (1 - lam) * x[index]
y_a, y_b = y, y[index]
return mixed_x, y_a, y_b, lamCutOut บังคับให้โมเดลพึ่งพาเบาะแสภาพหลายอย่างแทนที่จะเป็นพื้นที่แยกแยะเดียว MixUp สร้างการรวมแบบ convex ของคู่การฝึก ส่งผลให้ขอบเขตการตัดสินใจราบรื่นขึ้น เทคนิคเหล่านี้ปรับปรุงความแม่นยำอย่างสม่ำเสมอ 1-3% บน benchmark มาตรฐาน
คำถามสัมภาษณ์เกี่ยวกับ CNN และ Computer Vision
การสัมภาษณ์เทคนิคสำหรับตำแหน่ง computer vision ทดสอบทั้งความเข้าใจทางทฤษฎีและทักษะการนำไปใช้จริง เตรียมตัวสำหรับคำถามเกี่ยวกับการออกแบบสถาปัตยกรรม ความท้าทายในการเพิ่มประสิทธิภาพ และข้อพิจารณาการ deploy ในโลกจริง
ผู้สัมภาษณ์มักถามเกี่ยวกับการคำนวณ receptive field, วัตถุประสงค์ของ batch normalization, เหตุใด convolution จึงทำงานได้ดีกับภาพ และวิธีวินิจฉัย overfitting ในโมเดล vision
ถาม: Receptive field คืออะไรและทำไมถึงสำคัญ?
Receptive field คือพื้นที่ของภาพอินพุตที่มีอิทธิพลต่อตำแหน่ง feature map เฉพาะ เลเยอร์ที่ลึกกว่ามี receptive field ที่ใหญ่กว่า ทำให้สามารถจับบริบทที่กว้างขึ้น สำหรับเครือข่ายที่มี n เลเยอร์ convolution โดยใช้ kernel 3x3 receptive field จะเติบโตเป็น (2n + 1) x (2n + 1) การออกแบบสถาปัตยกรรมต้องสมดุลระหว่างขนาด receptive field และต้นทุนการคำนวณ—dilated convolution ขยาย receptive field โดยไม่เพิ่มพารามิเตอร์
ถาม: ทำไมต้องใช้ batch normalization ใน CNN?
Batch normalization ทำการ normalize อินพุตของเลเยอร์ให้มี mean เป็นศูนย์และ variance เป็นหนึ่ง แก้ปัญหา internal covariate shift ประโยชน์ ได้แก่: การลู่เข้าเร็วขึ้น (learning rate ที่สูงขึ้นมีเสถียรภาพ), ผลของ regularization (ลดความต้องการ dropout) และการปรับปรุงการไหลของ gradient (ป้องกัน vanishing gradient ในเครือข่ายลึก) ในระหว่างการ inference, running statistics แทนที่ batch statistics สำหรับเอาต์พุตที่แน่นอน
ถาม: อธิบายความแตกต่างระหว่าง same และ valid padding
Same padding เพิ่มศูนย์รอบอินพุตเพื่อรักษามิติเชิงพื้นที่หลัง convolution—อินพุต 32x32 กับ kernel 3x3 สร้างเอาต์พุต 32x32 Valid padding ไม่ใช้ padding ลดมิติ—การดำเนินการเดียวกันสร้างเอาต์พุต 30x30 Same padding เป็นที่นิยมในเครือข่ายลึกเพื่อหลีกเลี่ยงการลดมิติเชิงพื้นที่อย่างรวดเร็ว
ถาม: จัดการกับความไม่สมดุลของคลาสในการจำแนกภาพอย่างไร?
กลยุทธ์ ได้แก่: weighted cross-entropy loss (น้ำหนักสูงกว่าสำหรับคลาสส่วนน้อย), oversampling คลาสส่วนน้อยในระหว่างการฝึก, การเพิ่มข้อมูลที่เน้นคลาสที่มีตัวแทนน้อย และ focal loss ที่ลดน้ำหนักตัวอย่างที่ง่าย สำหรับความไม่สมดุลรุนแรง (>100:1) รวมหลายเทคนิคและพิจารณา metrics นอกเหนือจากความแม่นยำ—F1 score, precision-recall AUC หรือการวิเคราะห์ confusion matrix
สำหรับการเตรียมสัมภาษณ์ deep learning เพิ่มเติม สำรวจโมดูลคำถาม CNN & Image Classification และ Deep Learning Fundamentals
Deploy โมเดล Vision PyTorch ด้วย TorchScript
การ deploy ใน production ต้องการการแปลงโมเดล PyTorch เป็นรูปแบบที่เพิ่มประสิทธิภาพ TorchScript คอมไพล์โมเดลเป็นการแสดงแบบพกพาที่ทำงานโดยไม่ต้องใช้ Python ทำให้สามารถ deploy ในแอปพลิเคชัน C++, อุปกรณ์มือถือ หรือสภาพแวดล้อม serverless
# deployment_export.py
import torch
from torchvision import models
from torchvision.models import ResNet18_Weights
def export_for_production(model: torch.nn.Module, save_path: str) -> None:
"""Export model to TorchScript for production deployment"""
model.eval() # Set to evaluation mode (disables dropout, uses running stats)
# Create example input matching expected dimensions
example_input = torch.randn(1, 3, 224, 224)
# Method 1: Tracing (for models without control flow)
traced_model = torch.jit.trace(model, example_input)
traced_model.save(save_path.replace(".pt", "_traced.pt"))
# Method 2: Scripting (handles if/else, loops)
scripted_model = torch.jit.script(model)
scripted_model.save(save_path.replace(".pt", "_scripted.pt"))
# Verify outputs match
with torch.no_grad():
original_out = model(example_input)
traced_out = traced_model(example_input)
scripted_out = scripted_model(example_input)
assert torch.allclose(original_out, traced_out, atol=1e-5)
assert torch.allclose(original_out, scripted_out, atol=1e-5)
print(f"Model exported successfully to {save_path}")
def optimize_for_inference(model_path: str) -> torch.jit.ScriptModule:
"""Load and optimize TorchScript model for inference"""
model = torch.jit.load(model_path)
# Optimize for inference (fuses operations, removes dropout)
optimized = torch.jit.optimize_for_inference(model)
return optimized
# Export ResNet18
model = models.resnet18(weights=ResNet18_Weights.IMAGENET1K_V1)
export_for_production(model, "resnet18_production.pt")สำหรับความเร็ว inference สูงสุด พิจารณาการ export ONNX สำหรับความเข้ากันได้ข้าม framework หรือ TensorRT สำหรับการ deploy บน GPU NVIDIA การเปรียบเทียบ PyTorch vs TensorFlow ครอบคลุมข้อแลกเปลี่ยนการ deploy ระหว่าง framework
สรุป
Computer vision ด้วย PyTorch รวมการ abstract ที่ทรงพลังกับเครื่องมือที่พร้อมใช้งานใน production:
- สถาปัตยกรรม CNN สกัดคุณลักษณะแบบลำดับชั้นผ่านเลเยอร์ convolution, pooling และ normalization
- Transfer learning กับโมเดล pretrained (ResNet, EfficientNet) ให้ความแม่นยำสูงบนข้อมูลจำกัด
- การเพิ่มข้อมูล (MixUp, CutOut, การแปลงทางเรขาคณิต) ปรับปรุง generalization และป้องกัน overfitting
- การสัมภาษณ์เทคนิคทดสอบ receptive field, batch normalization, กลยุทธ์ padding และการจัดการความไม่สมดุลของคลาส
- TorchScript ทำให้สามารถ deploy ใน production โดยไม่ต้องพึ่งพา Python
เริ่มฝึกซ้อมเลย!
ทดสอบความรู้ของคุณด้วยตัวจำลองสัมภาษณ์และแบบทดสอบเทคนิคครับ

เขียนโดย
Anthony Fillion-Mailletนักพัฒนาฟูลสแตก ผู้ก่อตั้ง SharpSkill
เป็นนักพัฒนาฟูลสแตกมากว่า 10 ปี ดูแล SharpSkill และรับผิดชอบทุกสิ่งที่เผยแพร่ที่นี่
อัปเดตเมื่อ 14 สิงหาคม 2569
แชร์
บทความที่เกี่ยวข้อง

LangChain สำหรับ Data Scientist ปี 2026: LLM, Agent และคำถามสัมภาษณ์
เชี่ยวชาญ LangChain 0.3 สำหรับ data science: LCEL chain, รูปแบบ RAG, ReAct agent, ระบบ memory และคำถามสัมภาษณ์สำหรับตำแหน่ง ML engineering

MLOps ในปี 2026: MLflow, Model Registry และคำถามสัมภาษณ์เชิงเทคนิค
คำถามสัมภาษณ์ MLOps ครอบคลุมวงจรชีวิต ML การติดตามการทดลองด้วย MLflow การเลื่อนระดับใน model registry รูปแบบการนำไปใช้งาน การเฝ้าติดตาม drift และ system design สำหรับปี 2026 พร้อมโค้ด Python และคำตอบ

RAG และ LLM ในปี 2026: Retrieval-Augmented Generation สำหรับสัมภาษณ์ Data Science
อธิบาย Retrieval-Augmented Generation (RAG) สำหรับการสัมภาษณ์ data science ในปี 2026 ครอบคลุมฐานข้อมูลเวกเตอร์ กลยุทธ์ chunking โมเดล embedding agentic RAG Graph RAG และสถาปัตยกรรมไปป์ไลน์ที่พร้อมใช้งานจริง