νμ΄νΌνλΌλ―Έν° μ§ν
μ΄ κ°μ΄λμμλ YOLOv5 πμ λν νμ΄νΌνλΌλ―Έν° μ§νμ λν΄ μ€λͺ ν©λλ€. νμ΄νΌνλΌλ―Έν° μ§νλ μ΅μ νλ₯Ό μν΄ μ μ μκ³ λ¦¬μ¦ (GA)μ μ¬μ©νλ νμ΄νΌνλΌλ―Έν° μ΅μ ν λ°©λ²μ λλ€.
MLμ νμ΄νΌνλΌλ―Έν°λ νμ΅μ λ€μν μΈ‘λ©΄μ μ μ΄νλ©°, μ΄μ λν μ΅μ μ κ°μ μ°Ύλ κ²μ μ΄λ €μ΄ μΌμ΄ λ μ μμ΅λλ€. 그리λ κ²μκ³Ό κ°μ κΈ°μ‘΄ λ°©λ²μ 1) μ°¨μμ΄ λμ κ²μ κ³΅κ° 2) μ°¨μ κ°μ μλ €μ§μ§ μμ μκ΄κ΄κ³ 3) κ° μ§μ μμ μ ν©μ±μ νκ°νλ λ° λ§μ λΉμ©μ΄ λ€κΈ° λλ¬Έμ νμ΄νΌνλΌλ―Έν° κ²μμ μ ν©ν νλ³΄λ‘ GAκ° μ ν©ν μ μμ΅λλ€.
μμνκΈ° μ μ
리ν¬μ§ν 리λ₯Ό 볡μ νκ³ μꡬμ¬ν.txtλ₯Ό μ€μΉν©λλ€. Python>=3.8.0 νκ²½μ ν¬ν¨νμ¬ PyTorch>=1.8. λͺ¨λΈ λ° λ°μ΄ν° μΈνΈλ μ΅μ YOLOv5 릴리μ€μμ μλμΌλ‘ λ€μ΄λ‘λλ©λλ€.
git clone https://github.com/ultralytics/yolov5 # clone
cd yolov5
pip install -r requirements.txt # install
1. νμ΄νΌνλΌλ―Έν° μ΄κΈ°ν
YOLOv5 μλ λ€μν νΈλ μ΄λ μ€μ μ μ¬μ©λλ μ½ 30κ°μ νμ΄νΌνλΌλ―Έν°κ° μμ΅λλ€. μ΄λ¬ν νμ΄νΌνλΌλ―Έν°λ λ€μμμ μ μλ©λλ€. *.yaml
νμΌμ μλ /data/hyps
λλ ν 리μ μ μ₯ν©λλ€. μ΄κΈ° μΆμΈ‘μ΄ μ νν μλ‘ μ΅μ’
κ²°κ³Όκ° λ μ’μΌλ―λ‘ μ§ννκΈ° μ μ μ΄λ¬ν κ°μ μ μ νκ² μ΄κΈ°ννλ κ²μ΄ μ€μν©λλ€. νμ€νμ§ μμ κ²½μ° YOLOv5 COCO κ΅μ‘μ μ΅μ νλ κΈ°λ³Έκ°μ μ²μλΆν° μ¬μ©νλ©΄ λ©λλ€.
# YOLOv5 π by Ultralytics, AGPL-3.0 license
# Hyperparameters for low-augmentation COCO training from scratch
# python train.py --batch 64 --cfg yolov5n6.yaml --weights '' --data coco.yaml --img 640 --epochs 300 --linear
# See tutorials for hyperparameter evolution https://github.com/ultralytics/yolov5#tutorials
lr0: 0.01 # initial learning rate (SGD=1E-2, Adam=1E-3)
lrf: 0.01 # final OneCycleLR learning rate (lr0 * lrf)
momentum: 0.937 # SGD momentum/Adam beta1
weight_decay: 0.0005 # optimizer weight decay 5e-4
warmup_epochs: 3.0 # warmup epochs (fractions ok)
warmup_momentum: 0.8 # warmup initial momentum
warmup_bias_lr: 0.1 # warmup initial bias lr
box: 0.05 # box loss gain
cls: 0.5 # cls loss gain
cls_pw: 1.0 # cls BCELoss positive_weight
obj: 1.0 # obj loss gain (scale with pixels)
obj_pw: 1.0 # obj BCELoss positive_weight
iou_t: 0.20 # IoU training threshold
anchor_t: 4.0 # anchor-multiple threshold
# anchors: 3 # anchors per output layer (0 to ignore)
fl_gamma: 0.0 # focal loss gamma (efficientDet default gamma=1.5)
hsv_h: 0.015 # image HSV-Hue augmentation (fraction)
hsv_s: 0.7 # image HSV-Saturation augmentation (fraction)
hsv_v: 0.4 # image HSV-Value augmentation (fraction)
degrees: 0.0 # image rotation (+/- deg)
translate: 0.1 # image translation (+/- fraction)
scale: 0.5 # image scale (+/- gain)
shear: 0.0 # image shear (+/- deg)
perspective: 0.0 # image perspective (+/- fraction), range 0-0.001
flipud: 0.0 # image flip up-down (probability)
fliplr: 0.5 # image flip left-right (probability)
mosaic: 1.0 # image mosaic (probability)
mixup: 0.0 # image mixup (probability)
copy_paste: 0.0 # segment copy-paste (probability)
2. νΌνΈλμ€ μ μ
νΌνΈλμ€λ μ°λ¦¬κ° κ·Ήλννκ³ μ νλ κ°μΉμ
λλ€. YOLOv5 μμλ κΈ°λ³Έ νΌνΈλμ€ ν¨μλ₯Ό λ©νΈλ¦μ κ°μ€μΉ μ‘°ν©μΌλ‘ μ μν©λλ€: mAP@0.5
λ 무κ²μ 10%λ₯Ό μ°¨μ§νκ³ mAP@0.5:0.95
κ° λλ¨Έμ§ 90%λ₯Ό μ°¨μ§νλ©° μ λ°λ P
κ·Έλ¦¬κ³ λ¦¬μ½ R
λΆμ¬. μ μ νλ€κ³ νλ¨λλ κ²½μ° μ΄λ₯Ό μ‘°μ νκ±°λ utils/metrics.pyμ κΈ°λ³Έ μ ν©μ± μ μλ₯Ό μ¬μ©ν μ μμ΅λλ€(κΆμ₯).
def fitness(x):
"""Return model fitness as the sum of weighted metrics [P, R, mAP@0.5, mAP@0.5:0.95]."""
w = [0.0, 0.0, 0.1, 0.9] # weights for [P, R, mAP@0.5, mAP@0.5:0.95]
return (x[:, :4] * w).sum(1)
3. μ§ν
μ§νλ κ°μ νκ³ μ νλ κΈ°λ³Έ μλ리μ€μ λν΄ μνλ©λλ€. μ΄ μμ μ κΈ°λ³Έ μλ리μ€λ μ¬μ νμ΅λ YOLOv5λ₯Ό μ¬μ©νμ¬ 10νμ κ±Έμ³ COCO128μ λ―ΈμΈ μ‘°μ νλ κ²μ λλ€. κΈ°λ³Έ μλλ¦¬μ€ νλ ¨ λͺ λ Ήμ λ€μκ³Ό κ°μ΅λλ€:
νμ΄νΌνλΌλ―Έν°λ₯Ό λ°μ μν€λ €λ©΄ μ΄ μλ리μ€μ νΉμ νμ μ μλ μ΄κΈ° κ°μμ μμνμ¬ μΉμ
1.μ μ μλ 체λ ₯μ κ·Ήλννκ³ μΉμ
2.μΆκ° --evolve
:
# Single-GPU
python train.py --epochs 10 --data coco128.yaml --weights yolov5s.pt --cache --evolve
# Multi-GPU
for i in 0 1 2 3 4 5 6 7; do
sleep $(expr 30 \* $i) && # 30-second delay (optional)
echo 'Starting GPU '$i'...' &&
nohup python train.py --epochs 10 --data coco128.yaml --weights yolov5s.pt --cache --device $i --evolve > evolve_gpu_$i.log &
done
# Multi-GPU bash-while (not recommended)
for i in 0 1 2 3 4 5 6 7; do
sleep $(expr 30 \* $i) && # 30-second delay (optional)
echo 'Starting GPU '$i'...' &&
"$(while true; do nohup python train.py... --device $i --evolve 1 > evolve_gpu_$i.log; done)" &
done
κΈ°λ³Έ μ§ν μ€μ μ κΈ°λ³Έ μλ리μ€λ₯Ό 300ν, μ¦ 300μΈλ λμ μ€νν©λλ€. μΈλλ₯Ό μμ νλ €λ©΄ --evolve
μΈμ, μ¦ python train.py --evolve 1000
.
μ£Όμ μ μ μ μ°μ°μλ λ€μκ³Ό κ°μ΅λλ€. ν¬λ‘μ€μ€λ² κ·Έλ¦¬κ³ λμ°λ³μ΄. μ΄ μμ
μμλ 80%μ νλ₯ κ³Ό 0.04μ λΆμ°μΌλ‘ λμ°λ³μ΄κ° μ¬μ©λμ΄ μ΄μ μΈλμ λͺ¨λ λΆλͺ¨ μ€ κ°μ₯ μ°μν λΆλͺ¨μ μ‘°ν©μ κΈ°λ°μΌλ‘ μλ‘μ΄ μμμ μμ±ν©λλ€. κ²°κ³Όλ λ€μ μμΉμ κΈ°λ‘λ©λλ€. runs/evolve/exp/evolve.csv
κ·Έλ¦¬κ³ κ°μ₯ 체λ ₯μ΄ μ’μ μμμ 맀 μΈλλ§λ€ λ€μκ³Ό κ°μ΄ μ μ₯λ©λλ€. runs/evolve/hyp_evolved.yaml
:
# YOLOv5 Hyperparameter Evolution Results
# Best generation: 287
# Last generation: 300
# metrics/precision, metrics/recall, metrics/mAP_0.5, metrics/mAP_0.5:0.95, val/box_loss, val/obj_loss, val/cls_loss
# 0.54634, 0.55625, 0.58201, 0.33665, 0.056451, 0.042892, 0.013441
lr0: 0.01 # initial learning rate (SGD=1E-2, Adam=1E-3)
lrf: 0.2 # final OneCycleLR learning rate (lr0 * lrf)
momentum: 0.937 # SGD momentum/Adam beta1
weight_decay: 0.0005 # optimizer weight decay 5e-4
warmup_epochs: 3.0 # warmup epochs (fractions ok)
warmup_momentum: 0.8 # warmup initial momentum
warmup_bias_lr: 0.1 # warmup initial bias lr
box: 0.05 # box loss gain
cls: 0.5 # cls loss gain
cls_pw: 1.0 # cls BCELoss positive_weight
obj: 1.0 # obj loss gain (scale with pixels)
obj_pw: 1.0 # obj BCELoss positive_weight
iou_t: 0.20 # IoU training threshold
anchor_t: 4.0 # anchor-multiple threshold
# anchors: 3 # anchors per output layer (0 to ignore)
fl_gamma: 0.0 # focal loss gamma (efficientDet default gamma=1.5)
hsv_h: 0.015 # image HSV-Hue augmentation (fraction)
hsv_s: 0.7 # image HSV-Saturation augmentation (fraction)
hsv_v: 0.4 # image HSV-Value augmentation (fraction)
degrees: 0.0 # image rotation (+/- deg)
translate: 0.1 # image translation (+/- fraction)
scale: 0.5 # image scale (+/- gain)
shear: 0.0 # image shear (+/- deg)
perspective: 0.0 # image perspective (+/- fraction), range 0-0.001
flipud: 0.0 # image flip up-down (probability)
fliplr: 0.5 # image flip left-right (probability)
mosaic: 1.0 # image mosaic (probability)
mixup: 0.0 # image mixup (probability)
copy_paste: 0.0 # segment copy-paste (probability)
μ΅μμ κ²°κ³Όλ₯Ό μ»μΌλ €λ©΄ μ΅μ 300μΈλ μ΄μμ μ§νλ₯Ό κΆμ₯ν©λλ€. κΈ°λ³Έ μλ리μ€λ μλ°± λ² νμ΅λλ―λ‘ μΌλ°μ μΌλ‘ μλ°± λλ μμ² μκ°( GPU )μ΄ μμλ μ μμΌλ―λ‘ μ§νμλ λ§μ λΉμ©κ³Ό μκ°μ΄ μμλ©λλ€.
4. μκ°ν
evolve.csv
λ λ€μκ³Ό κ°μ΄ νλ‘―λ©λλ€. evolve.png
by utils.plots.plot_evolve()
μ§νκ° μλ£λ ν νμ΄νΌνλΌλ―Έν°λΉ νλμ νμ νλ‘―μΌλ‘ μ ν©λ(yμΆ) λ νμ΄νΌνλΌλ―Έν° κ°(xμΆ)μ νμν©λλ€. λ
Έλμμ λ λμ λλλ₯Ό λνλ
λλ€. μμ§ λΆν¬λ 맀κ°λ³μκ° λΉνμ±νλμ΄ λ³μ΄λμ§ μμμμ λνλ
λλ€. μ΄λ μ¬μ©μκ° meta
λμ
λ리λ₯Ό μΆκ°ν μ μμΌλ©°, 맀κ°λ³μλ₯Ό μμ νκ³ μ§ννλ κ²μ λ°©μ§νλ λ° μ μ©ν©λλ€.
μ§μ νκ²½
Ultralytics λ λ°λ‘ μ¬μ©ν μ μλ λ€μν νκ²½μ μ 곡νλ©°, κ° νκ²½μλ λ€μκ³Ό κ°μ νμ μ’ μμ±μ΄ μ¬μ μ€μΉλμ΄ μμ΅λλ€. CUDA, CUDNN, Python, λ° PyTorchμ κ°μ νμ μ’ μ μμλ₯Ό μ€μΉνμ¬ νλ‘μ νΈλ₯Ό μμν μ μμ΅λλ€.
- λ¬΄λ£ GPU λ ΈνΈλΆ:
- Google Cloud: GCP λΉ λ₯Έ μμ κ°μ΄λ
- Amazon: AWS λΉ λ₯Έ μμ κ°μ΄λ
- Azure: AzureML λΉ λ₯Έ μμ κ°μ΄λ
- Docker: Docker λΉ λ₯Έ μμ κ°μ΄λ
νλ‘μ νΈ μν
μ΄ λ°°μ§λ λͺ¨λ YOLOv5 GitHub Actions μ§μμ ν΅ν©(CI) ν μ€νΈκ° μ±κ³΅μ μΌλ‘ ν΅κ³Όλμμμ λνλ λλ€. μ΄λ¬ν CI ν μ€νΈλ κ΅μ‘, κ²μ¦, μΆλ‘ , λ΄λ³΄λ΄κΈ° λ° λ²€μΉλ§ν¬ λ± λ€μν μ£Όμ μΈ‘λ©΄μμ YOLOv5 μ κΈ°λ₯κ³Ό μ±λ₯μ μ격νκ² νμΈν©λλ€. 24μκ°λ§λ€ κ·Έλ¦¬κ³ μλ‘μ΄ μ»€λ°μ΄ μμ λλ§λ€ ν μ€νΈλ₯Ό μννμ¬ macOS, Windows λ° Ubuntuμμ μΌκ΄λκ³ μμ μ μΈ μλμ 보μ₯ν©λλ€.