Replace inline comments with docstrings (#12764)

* Add docstrings

* Add docstrings

* Add docstrings

* Add docstrings

* Add docstrings

* Add docstrings

* Add docstrings

* Add docstrings

* Add docstrings

* Add docstrings

* Auto-format by https://ultralytics.com/actions

* Add docstrings

* Add docstrings

* Add docstrings

* Add docstrings

* Auto-format by https://ultralytics.com/actions

* Update plots.py

Signed-off-by: Glenn Jocher <glenn.jocher@ultralytics.com>

---------

Signed-off-by: Glenn Jocher <glenn.jocher@ultralytics.com>
Co-authored-by: UltralyticsAssistant <web@ultralytics.com>
This commit is contained in:
Glenn JocherandUltralyticsAssistant authored and GitHub committed 2024-02-26 23:16:32 +01:00
1 parent 41603da162
commit 574331f984
14 files changed
+225 -66

No files matched your search

+5 -2
View File
@@ -59,8 +59,10 @@ class MemoryEfficientMish(nn.Module):
class FReLU(nn.Module):
# FReLU activation https://arxiv.org/abs/2007.11824
"""FReLU activation https://arxiv.org/abs/2007.11824."""
def __init__(self, c1, k=3): # ch_in, kernel
"""Initializes FReLU activation with channel `c1` and kernel size `k`."""
super().__init__()
self.conv = nn.Conv2d(c1, c1, k, 1, 1, groups=c1, bias=False)
self.bn = nn.BatchNorm2d(c1)
@@ -103,7 +105,8 @@ class MetaAconC(nn.Module):
See "Activate or Not: Learning Customized Activation" https://arxiv.org/pdf/2009.04759.pdf.
"""
def __init__(self, c1, k=1, s=1, r=16): # ch_in, kernel, stride, r
def __init__(self, c1, k=1, s=1, r=16):
"""Initializes MetaAconC with params: channel_in (c1), kernel size (k=1), stride (s=1), reduction (r=16)."""
super().__init__()
c2 = max(r, c1 // r)
self.p1 = nn.Parameter(torch.randn(1, c1, 1, 1))
+26 -5
View File
@@ -310,8 +310,13 @@ def mixup(im, labels, im2, labels2):
return im, labels
def box_candidates(box1, box2, wh_thr=2, ar_thr=100, area_thr=0.1, eps=1e-16): # box1(4,n), box2(4,n)
# Compute candidate boxes: box1 before augment, box2 after augment, wh_thr (pixels), aspect_ratio_thr, area_ratio
def box_candidates(box1, box2, wh_thr=2, ar_thr=100, area_thr=0.1, eps=1e-16):
"""
Filters bounding box candidates by minimum width-height threshold `wh_thr` (pixels), aspect ratio threshold
`ar_thr`, and area ratio threshold `area_thr`.
box1(4,n) is before augmentation, box2(4,n) is after augmentation.
"""
w1, h1 = box1[2] - box1[0], box1[3] - box1[1]
w2, h2 = box2[2] - box2[0], box2[3] - box2[1]
ar = np.maximum(w2 / (h2 + eps), h2 / (w2 + eps)) # aspect ratio
@@ -380,7 +385,12 @@ class LetterBox:
self.auto = auto # pass max size integer, automatically solve for short side using stride
self.stride = stride # used with auto
def __call__(self, im): # im = np.array HWC
def __call__(self, im):
"""
Resizes and pads input image `im` (HWC format) to specified dimensions, maintaining aspect ratio.
im = np.array HWC
"""
imh, imw = im.shape[:2]
r = min(self.h / imh, self.w / imw) # ratio of new/old
h, w = round(imh * r), round(imw * r) # resized image
@@ -398,7 +408,12 @@ class CenterCrop:
super().__init__()
self.h, self.w = (size, size) if isinstance(size, int) else size
def __call__(self, im): # im = np.array HWC
def __call__(self, im):
"""
Applies center crop to the input image and resizes it to a specified size, maintaining aspect ratio.
im = np.array HWC
"""
imh, imw = im.shape[:2]
m = min(imh, imw) # min dimension
top, left = (imh - m) // 2, (imw - m) // 2
@@ -412,7 +427,13 @@ class ToTensor:
super().__init__()
self.half = half
def __call__(self, im): # im = np.array HWC in BGR order
def __call__(self, im):
"""
Converts BGR np.array image from HWC to RGB CHW format, and normalizes to [0, 1], with support for FP16 if
`half=True`.
im = np.array HWC in BGR order
"""
im = np.ascontiguousarray(im.transpose((2, 0, 1))[::-1]) # HWC to CHW -> BGR to RGB -> contiguous
im = torch.from_numpy(im) # to torch
im = im.half() if self.half else im.float() # uint8 to fp16/32
+8 -3
View File
@@ -1060,8 +1060,13 @@ def flatten_recursive(path=DATASETS_DIR / "coco128"):
shutil.copyfile(file, new_path / Path(file).name)
def extract_boxes(path=DATASETS_DIR / "coco128"): # from utils.dataloaders import *; extract_boxes()
# Convert detection dataset into classification dataset, with one directory per class
def extract_boxes(path=DATASETS_DIR / "coco128"):
"""
Converts a detection dataset to a classification dataset, creating a directory for each class and extracting
bounding boxes.
Example: from utils.dataloaders import *; extract_boxes()
"""
path = Path(path) # images dir
shutil.rmtree(path / "classification") if (path / "classification").is_dir() else None # remove existing
files = list(path.rglob("*.*"))
@@ -1253,7 +1258,7 @@ class HUBDatasetStats:
"""Generates dataset JSON for Ultralytics HUB, optionally saves or prints it; save=bool, verbose=bool."""
def _round(labels):
# Update labels to integer class and 6 decimal place floats
"""Rounds class labels to integers and coordinates to 4 decimal places for improved label accuracy."""
return [[int(c), *(round(x, 4) for x in points)] for c, *points in labels]
for split in "train", "val", "test":
+19 -6
View File
@@ -351,8 +351,12 @@ def check_online():
return run_once() or run_once() # check twice to increase robustness to intermittent connectivity issues
def git_describe(path=ROOT): # path must be a directory
# Return human-readable git description, i.e. v5.0-5-g3e25f1e https://git-scm.com/docs/git-describe
def git_describe(path=ROOT):
"""
Returns a human-readable git description of the repository at `path`, or an empty string on failure.
Example output is 'fv5.0-5-g3e25f1e'. See https://git-scm.com/docs/git-describe.
"""
try:
assert (Path(path) / ".git").is_dir()
return check_output(f"git -C {path} describe --tags --long --always", shell=True).decode()[:-1]
@@ -767,8 +771,12 @@ def labels_to_image_weights(labels, nc=80, class_weights=np.ones(80)):
return (class_weights.reshape(1, nc) * class_counts).sum(1)
def coco80_to_coco91_class(): # converts 80-index (val2014) to 91-index (paper)
# https://tech.amikelive.com/node-718/what-object-categories-labels-are-in-coco-dataset/
def coco80_to_coco91_class():
"""
Converts COCO 80-class index to COCO 91-class index used in the paper.
Reference: https://tech.amikelive.com/node-718/what-object-categories-labels-are-in-coco-dataset/
"""
# a = np.loadtxt('data/coco.names', dtype='str', delimiter='\n')
# b = np.loadtxt('data/coco_paper.names', dtype='str', delimiter='\n')
# x1 = [list(a[i] == b).index(True) + 1 for i in range(80)] # darknet to coco
@@ -1108,8 +1116,13 @@ def non_max_suppression(
return output
def strip_optimizer(f="best.pt", s=""): # from utils.general import *; strip_optimizer()
# Strip optimizer from 'f' to finalize training, optionally save as 's'
def strip_optimizer(f="best.pt", s=""):
"""
Strips optimizer and optionally saves checkpoint to finalize training; arguments are file path 'f' and save path
's'.
Example: from utils.general import *; strip_optimizer()
"""
x = torch.load(f, map_location=torch.device("cpu"))
if x.get("ema"):
x["model"] = x["ema"] # replace model with ema
+3 -2
View File
@@ -8,8 +8,8 @@ from utils.metrics import bbox_iou
from utils.torch_utils import de_parallel
def smooth_BCE(eps=0.1): # https://github.com/ultralytics/yolov3/issues/238#issuecomment-598028441
# return positive, negative label smoothing BCE targets
def smooth_BCE(eps=0.1):
"""Returns label smoothing BCE targets for reducing overfitting; pos: `1.0 - 0.5*eps`, neg: `0.5*eps`. For details see ttps://github.com/ultralytics/yolov3/issues/238#issuecomment-598028441"""
return 1.0 - 0.5 * eps, 0.5 * eps
@@ -132,6 +132,7 @@ class ComputeLoss:
self.device = device
def __call__(self, p, targets): # predictions, targets
"""Performs forward pass, calculating class, box, and object loss for given predictions and targets."""
lcls = torch.zeros(1, device=self.device) # class loss
lbox = torch.zeros(1, device=self.device) # box loss
lobj = torch.zeros(1, device=self.device) # object loss
+28 -9
View File
@@ -67,7 +67,8 @@ class Colors:
return (c[2], c[1], c[0]) if bgr else c
@staticmethod
def hex2rgb(h): # rgb order (PIL)
def hex2rgb(h):
"""Converts hexadecimal color `h` to an RGB tuple (PIL-compatible) with order (R, G, B)."""
return tuple(int(h[1 + i : 1 + i + 2], 16) for i in (0, 2, 4))
@@ -225,8 +226,13 @@ def plot_lr_scheduler(optimizer, scheduler, epochs=300, save_dir=""):
plt.close()
def plot_val_txt(): # from utils.plots import *; plot_val()
# Plot val.txt histograms
def plot_val_txt():
"""
Plots 2D and 1D histograms of bounding box centers from 'val.txt' using matplotlib, saving as 'hist2d.png' and
'hist1d.png'.
Example: from utils.plots import *; plot_val()
"""
x = np.loadtxt("val.txt", dtype=np.float32)
box = xyxy2xywh(x[:, :4])
cx, cy = box[:, 0], box[:, 1]
@@ -242,8 +248,12 @@ def plot_val_txt(): # from utils.plots import *; plot_val()
plt.savefig("hist1d.png", dpi=200)
def plot_targets_txt(): # from utils.plots import *; plot_targets_txt()
# Plot targets.txt histograms
def plot_targets_txt():
"""
Plots histograms of object detection targets from 'targets.txt', saving the figure as 'targets.jpg'.
Example: from utils.plots import *; plot_targets_txt()
"""
x = np.loadtxt("targets.txt", dtype=np.float32).T
s = ["x targets", "y targets", "width targets", "height targets"]
fig, ax = plt.subplots(2, 2, figsize=(8, 8), tight_layout=True)
@@ -255,8 +265,13 @@ def plot_targets_txt(): # from utils.plots import *; plot_targets_txt()
plt.savefig("targets.jpg", dpi=200)
def plot_val_study(file="", dir="", x=None): # from utils.plots import *; plot_val_study()
# Plot file=study.txt generated by val.py (or plot all study*.txt in dir)
def plot_val_study(file="", dir="", x=None):
"""
Plots validation study results from 'study*.txt' files in a directory or a specific file, comparing model
performance and speed.
Example: from utils.plots import *; plot_val_study()
"""
save_dir = Path(file).parent if file else Path(dir)
plot2 = False # plot additional results
if plot2:
@@ -381,8 +396,12 @@ def imshow_cls(im, labels=None, pred=None, names=None, nmax=25, verbose=False, f
return f
def plot_evolve(evolve_csv="path/to/evolve.csv"): # from utils.plots import *; plot_evolve()
# Plot evolve.csv hyp evolution results
def plot_evolve(evolve_csv="path/to/evolve.csv"):
"""
Plots hyperparameter evolution results from a given CSV, saving the plot and displaying best results.
Example: from utils.plots import *; plot_evolve()
"""
evolve_csv = Path(evolve_csv)
data = pd.read_csv(evolve_csv)
keys = [x.strip() for x in data.columns]
+1
View File
@@ -44,6 +44,7 @@ class ComputeLoss:
self.device = device
def __call__(self, preds, targets, masks): # predictions, targets, model
"""Evaluates YOLOv5 model's loss for given predictions, targets, and masks; returns total loss components."""
p, proto = preds
bs, nm, mask_h, mask_w = proto.shape # batch size, number of masks, mask height, mask width
lcls = torch.zeros(1, device=self.device)
+3 -1
View File
@@ -325,7 +325,9 @@ def model_info(model, verbose=False, imgsz=640):
def scale_img(img, ratio=1.0, same_shape=False, gs=32): # img(16,3,256,416)
# Scales img(bs,3,y,x) by ratio constrained to gs-multiple
"""Scales an image tensor `img` of shape (bs,3,y,x) by `ratio`, optionally maintaining the original shape, padded to
multiples of `gs`.
"""
if ratio == 1.0:
return img
h, w = img.shape[2:]