【YOLO】stratégie d'entraînement 3 de yolov5 - poids des images

1. Qu'est-ce que la pondération des images d'entraînement ?

Résolvez le problème en utilisant différentes méthodes de fréquence d'appel d'image en fonction de la distribution des types d'échantillons.
1. Lisez le GT dans l'échantillon de formation et enregistrez-le sous forme de liste ;
2. Calculez le nombre de catégories différentes dans la liste d'échantillons de formation, puis attribuez une valeur à chaque catégorie en fonction de l'inverse du nombre correspondant de cadres cibles. Plus le nombre est grand, plus le poids de la catégorie est petit. Formez un histogramme de distribution par catégorie ;
3. Pour la liste des données d'entraînement, les images de chaque catégorie sont filtrées en fonction du poids de la catégorie pendant l'entraînement en tant que données d'entraînement. Utilisez random.choice(population,weights=None, *, cum_weights=None, k=1) pour modifier l'index de l'image d'entraînement afin d'obtenir un équilibrage des échantillons.

2. Coder

Calculer le poids d'une catégorie :

def labels_to_class_weights(labels, nc=80):
    """
    计算类别权重
    Get class weights (inverse frequency) from training labels
    输出入: 
        labels -- 真实的标签列表 [class xywh]
        nc -- 类别数
    """
    if labels[0] is None:  # no labels loaded
        return torch.Tensor()

    labels = np.concatenate(labels, 0)  # labels.shape = (866643, 5) for COCO
    classes = labels[:, 0].astype(int)  # labels = [class xywh]
    # 直方图统计
    weights = np.bincount(classes, minlength=nc)  # occurrences per class

    # Prepend gridpoint count (for uCE training)
    # gpi = ((320 / 32 * np.array([1, 2, 4])) ** 2 * 3).sum()  # gridpoints per image
    # weights = np.hstack([gpi * len(labels)  - weights.sum() * 9, weights * 9]) ** 0.5  # prepend gridpoints to start
    
    # 统计的倒数
    weights[weights == 0] = 1   # replace empty bins with 1
    weights = 1 / weights       # number of targets per class
    # 归一化为0~1,就是权重
    weights /= weights.sum()    # normalize
    return torch.from_numpy(weights).float()

Calculer le poids de l'image

def labels_to_image_weights(labels, nc=80, class_weights=np.ones(80)):
    """
    计算图片的权重
    # Produces image weights based on class_weights and image contents
    # Usage: index = random.choices(range(n), weights=image_weights, k=1)  # weighted image sample
    """
    class_counts = []
    for x in labels:
        class_bin = np.bincount(x[:, 0].astype(int), minlength=nc)
        class_counts.append(class_bin)
    class_counts = np.array(class_counts)
    # 类别权重 * 每张图片中类别数量, 然后在sum
    return (class_weights.reshape(1, nc) * class_counts).sum(1)

Mettez à jour l'index des images dans l'ensemble de données afin que les images avec un poids élevé apparaissent plus probablement :

# epoch ------------------------------------------------------------------
for epoch in range(self.start_epoch, self.epochs):
    # Update image weights 在每次迭代前,更新数据集的indices,使得权重高的图片出现概率大
    if self.opt["image_weights"]:
        cw = class_weights * (1 - maps) ** 2 / self.nc  # class weights
        iw = labels_to_image_weights(dataset.labels, nc=self.nc, class_weights=cw)      # image weights
        dataset.indices = random.choices(range(dataset.n), weights=iw, k=dataset.n)     # rand weighted idx

Aimez, favoris, suivez, commentez

Guess you like

Origin blog.csdn.net/qq_21386397/article/details/131724028