Computer Vision YOLO กับ Post-mortem Analysis — วิธีใช้ YOLO สำหรับ Object Detection และ Post-mortem Analysis | SiamCafe Blog

Computer Vision YOLO กับ Post-mortem Analysis — วิธีใช้ YOLO สำหรับ Object Detection และ Post-mortem Analysis | SiamCafe Blog
Computer Vision YOLO กับ Post-mortem Analysis — วิธีใช้ YOLO สำหรับ Object Detection และ Post-mortem Analysis | SiamCafe Blog

YOLO Object Detection

YOLO เป็น Real-time Object Detection ที่เร็วมาก Single Pass ตรวจจับวัตถุในภาพ YOLOv8 เป็นเวอร์ชันล่าสุด รองรับ Detection Segmentation Classification Pose

Post-mortem Analysis วิเคราะห์หลังเกิด Incident หา Root Cause สำหรับ ML คือวิเคราะห์ว่า Model ทำนายผิดเพราะอะไร ปรับปรุง Data และ Model

YOLOv8 Setup และ Training

# === YOLOv8 Object Detection ===
# pip install ultralytics

from ultralytics import YOLO
import os

# 1. Load Pre-trained Model
model = YOLO("yolov8n.pt") # nano (fastest)
# model = YOLO("yolov8s.pt") # small
# model = YOLO("yolov8m.pt") # medium
# model = YOLO("yolov8l.pt") # large
# model = YOLO("yolov8x.pt") # extra-large (most accurate)

# 2. Inference (Detection)
# results = model("image.jpg")
# results = model("video.mp4")
# results = model(0) # Webcam

# 3. Process Results
# for result in results:
# boxes = result.boxes
# for box in boxes:
# cls = int(box.cls[0])
# conf = float(box.conf[0])
# xyxy = box.xyxy[0].tolist()
# name = model.names[cls]
# print(f" {name}: {conf:.2f} at {xyxy}")

# 4. Custom Training
# data.yaml format:
# path: /datasets/my_project
# train: images/train
# val: images/val
# test: images/test
# nc: 3
# names: ['car', 'person', 'bicycle']

# Train
# model = YOLO("yolov8n.pt")
# results = model.train(
# data="data.yaml",
# epochs=100,
# imgsz=640,
# batch=16,
# lr0=0.01,
# optimizer="AdamW",
# augment=True,
# patience=20,
# save=True,
# project="runs/detect",
# name="my_model",
# )

# 5. Validate
# metrics = model.val(data="data.yaml")
# print(f"mAP50: {metrics.box.map50}")
# print(f"mAP50-95: {metrics.box.map}")

# 6. Export
# model.export(format="onnx") # ONNX
# model.export(format="engine") # TensorRT
# model.export(format="coreml") # CoreML (iOS)
# model.export(format="tflite") # TFLite (Android)

# CLI Alternative
# yolo detect train model=yolov8n.pt data=data.yaml epochs=100 imgsz=640
# yolo detect val model=best.pt data=data.yaml
# yolo detect predict model=best.pt source=image.jpg

print("YOLOv8 Setup:")
print(" Models: nano, small, medium, large, x-large")
print(" Tasks: detect, segment, classify, pose, obb")
print(" Export: ONNX, TensorRT, CoreML, TFLite")

Post-mortem Analysis สำหรับ ML

# postmortem_analysis.py — ML Model Post-mortem Analysis
import numpy as np
from dataclasses import dataclass, field
from typing import List, Dict, Tuple
from datetime import datetime
from collections import Counter

@dataclass
class Prediction:
 image_id: str
 true_class: str
 pred_class: str
 confidence: float
 iou: float # Intersection over Union
 is_correct: bool

@dataclass
class ErrorPattern:
 pattern: str
 count: int
 examples: List[str]
 severity: str # critical, high, medium, low

class MLPostMortem:
 """ML Model Post-mortem Analysis"""

 def __init__(self, model_name, version):
 self.model_name = model_name
 self.version = version
 self.predictions: List[Prediction] = []
 self.error_patterns: List[ErrorPattern] = []

 def add_prediction(self, pred: Prediction):
 self.predictions.append(pred)

 def analyze_errors(self):
 """วิเคราะห์ Error Patterns"""
 errors = [p for p in self.predictions if not p.is_correct]
 correct = [p for p in self.predictions if p.is_correct]

 # Confusion pairs
 confusion = Counter()
 for e in errors:
 pair = f"{e.true_class} -> {e.pred_class}"
 confusion[pair] += 1

 # Low confidence correct predictions
 low_conf = [p for p in correct if p.confidence < 0.5]

 # False Positives (predicted but wrong class)
 false_pos = [e for e in errors if e.pred_class != "none"]

 # False Negatives (missed detections)
 false_neg = [e for e in errors if e.pred_class == "none"]

 # Error patterns
 patterns = []
 for pair, count in confusion.most_common(5):
 patterns.append(ErrorPattern(
 f"Misclassification: {pair}",
 count,
 [e.image_id for e in errors
 if f"{e.true_class} -> {e.pred_class}" == pair][:3],
 "critical" if count > 10 else "high",
 ))

 if low_conf:
 patterns.append(ErrorPattern(
 "Low confidence correct predictions",
 len(low_conf),
 [p.image_id for p in low_conf[:3]],
 "medium",
 ))

 self.error_patterns = patterns
 return patterns

 def generate_report(self):
 """สร้าง Post-mortem Report"""
 total = len(self.predictions)
 correct = sum(1 for p in self.predictions if p.is_correct)
 accuracy = correct / total * 100 if total > 0 else 0

 errors = [p for p in self.predictions if not p.is_correct]
 avg_conf_correct = np.mean([p.confidence for p in self.predictions if p.is_correct]) if correct > 0 else 0
 avg_conf_error = np.mean([p.confidence for p in errors]) if errors else 0

 print(f"\n{'='*60}")
 print(f"ML Post-mortem Report: {self.model_name} v{self.version}")
 print(f"{'='*60}")
 print(f" Date: {datetime.now().strftime('%Y-%m-%d')}")
 print(f" Total Predictions: {total}")
 print(f" Accuracy: {accuracy:.1f}%")
 print(f" Errors: {len(errors)}")
 print(f" Avg Confidence (correct): {avg_conf_correct:.3f}")
 print(f" Avg Confidence (error): {avg_conf_error:.3f}")

 # Error Patterns
 if self.error_patterns:
 print(f"\n Error Patterns:")
 for pattern in self.error_patterns:
 print(f" [{pattern.severity:>8}] {pattern.pattern} "
 f"(count: {pattern.count})")

 # Recommendations
 print(f"\n Recommendations:")
 recommendations = [
 "เพิ่ม Training Data สำหรับ Classes ที่ผิดบ่อย",
 "ปรับ Augmentation สำหรับ Edge Cases",
 "เพิ่ม Hard Negative Mining",
 "ลอง Larger Model (yolov8s -> yolov8m)",
 "ตรวจสอบ Label Quality ใน Training Data",
 ]
 for i, rec in enumerate(recommendations, 1):
 print(f" {i}. {rec}")

 def action_items(self):
 """Action Items จาก Post-mortem"""
 items = [
 {"action": "Review misclassified images", "owner": "ML Engineer",
 "priority": "high", "deadline": "1 week"},
 {"action": "Add edge case data to training set", "owner": "Data Team",
 "priority": "high", "deadline": "2 weeks"},
 {"action": "Retrain with augmented data", "owner": "ML Engineer",
 "priority": "medium", "deadline": "3 weeks"},
 {"action": "Update monitoring dashboards", "owner": "MLOps",
 "priority": "medium", "deadline": "1 week"},
 {"action": "Document findings in wiki", "owner": "ML Lead",
 "priority": "low", "deadline": "1 week"},
 ]

 print(f"\n Action Items:")
 for item in items:
 print(f" [{item['priority']:>6}] {item['action']}")
 print(f" Owner: {item['owner']} | Due: {item['deadline']}")

# ตัวอย่าง
pm = MLPostMortem("YOLOv8-custom", "1.2.0")

np.random.seed(42)
classes = ["car", "person", "bicycle", "truck"]
for i in range(200):
 true_cls = np.random.choice(classes)
 is_correct = np.random.random() > 0.15 # 85% accuracy
 pred_cls = true_cls if is_correct else np.random.choice([c for c in classes if c != true_cls])
 conf = np.random.uniform(0.7, 0.99) if is_correct else np.random.uniform(0.3, 0.8)

 pm.add_prediction(Prediction(
 f"img_{i:04d}", true_cls, pred_cls, conf,
 np.random.uniform(0.5, 0.95), is_correct))

pm.analyze_errors()
pm.generate_report()
pm.action_items()

Production Deployment

# === YOLO Production Deployment ===
# pip install ultralytics fastapi uvicorn pillow

from dataclasses import dataclass
from typing import List, Dict
import time

@dataclass
class DetectionResult:
 class_name: str
 confidence: float
 bbox: List[float] # [x1, y1, x2, y2]

class YOLOProductionServer:
 """YOLO Production Server"""

 def __init__(self, model_path="yolov8n.pt"):
 self.model_path = model_path
 self.request_count = 0
 self.total_latency = 0
 self.errors = 0

 def predict(self, image_path):
 """Run Prediction"""
 start = time.time()
 self.request_count += 1

 # model = YOLO(self.model_path)
 # results = model(image_path, conf=0.25, iou=0.45)

 # Simulated results
 detections = [
 DetectionResult("car", 0.92, [100, 200, 400, 350]),
 DetectionResult("person", 0.87, [450, 150, 550, 400]),
 ]

 latency = (time.time() - start) * 1000
 self.total_latency += latency

 return detections, latency

 def health_check(self):
 """Health Check"""
 avg_latency = self.total_latency / self.request_count if self.request_count > 0 else 0
 error_rate = self.errors / self.request_count * 100 if self.request_count > 0 else 0

 return {
 "status": "healthy",
 "model": self.model_path,
 "requests": self.request_count,
 "avg_latency_ms": f"{avg_latency:.1f}",
 "error_rate": f"{error_rate:.1f}%",
 }

# FastAPI Server
# from fastapi import FastAPI, UploadFile
# app = FastAPI()
# server = YOLOProductionServer("best.pt")
#
# @app.post("/detect")
# async def detect(file: UploadFile):
# contents = await file.read()
# with open("/tmp/upload.jpg", "wb") as f:
# f.write(contents)
# detections, latency = server.predict("/tmp/upload.jpg")
# return {
# "detections": [
# {"class": d.class_name, "confidence": d.confidence, "bbox": d.bbox}
# for d in detections
# ],
# "latency_ms": latency,
# }
#
# @app.get("/health")
# async def health():
# return server.health_check()

# Docker Deployment
# FROM python:3.11-slim
# WORKDIR /app
# COPY requirements.txt .
# RUN pip install -r requirements.txt
# COPY . .
# CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

server = YOLOProductionServer()
detections, latency = server.predict("test.jpg")
print(f"\nDetections: {len(detections)}")
for d in detections:
 print(f" {d.class_name}: {d.confidence:.2f}")
print(f"Latency: {latency:.1f}ms")
print(f"Health: {server.health_check()}")

Best Practices

  • Start Small: เริ่มจาก YOLOv8n (nano) แล้วค่อยขยายถ้าต้องการความแม่นยำมากขึ้น
  • Data Quality: Label ให้ถูกต้อง ใช้ Roboflow หรือ CVAT สำหรับ Labeling
  • Augmentation: ใช้ Mosaic, MixUp, HSV augmentation เพิ่มความหลากหลาย
  • Post-mortem: วิเคราะห์ Errors หลังทุก Training Run หา Pattern แก้ไขข้อมูล
  • Monitoring: ติดตาม mAP, Latency, Error Rate ใน Production
  • Export: Export เป็น ONNX หรือ TensorRT สำหรับ Production ลด Latency

YOLO คืออะไร

Real-time Object Detection Algorithm ตรวจจับวัตถุเร็วมาก Single Pass YOLOv8 Ultralytics ล่าสุด Detection Segmentation Classification Pose Estimation

Post-mortem Analysis คืออะไร

วิเคราะห์หลังเกิด Incident หา Root Cause ML Model วิเคราะห์ทำนายผิดเพราะอะไร False Positives Negatives Edge Cases ปรับปรุง Training Data Model

YOLOv8 ต่างจาก YOLOv5 อย่างไร

Architecture ใหม่แม่นยำเร็วกว่า Tasks มากกว่า Detection Segmentation Classification Pose OBB API ง่าย CLI Python Auto-augmentation Export ONNX TensorRT CoreML

วิธี Train Custom YOLO Model ทำอย่างไร

เตรียม Dataset YOLO Format images labels Label Roboflow LabelImg data.yaml Classes yolo train epochs=100 ประเมิน mAP Precision Recall Confusion Matrix Error Patterns

สรุป

YOLO เป็น Real-time Object Detection ที่เร็วและแม่นยำ YOLOv8 รองรับหลาย Tasks Training Custom Model ด้วย data.yaml Post-mortem Analysis วิเคราะห์ Errors หา Root Cause Production Deploy ด้วย FastAPI Export ONNX TensorRT Monitor mAP Latency