Explicación detallada de py-MDNet con código (1): tren

Explicación detallada de py-MDNet con código (1): tren


Todo es 0202, ¿por qué todavía necesita mirar un algoritmo tan temprano de MDNet (CVPR2016)? Las razones son las siguientes:

  • Hay implementaciones de actualización en línea más clásicas en este documento, que se pueden usar como referencia para comprender tales técnicas en el futuro.
  • Como rastreador que está esencialmente clasificado, obtuvo el ganador de VOT2015, y luego el ganador de VOT2018-LT- MBMD también tomó prestado de MDNet.

Enlace de papel: Aprendizaje de redes neuronales convolucionales multidominio para el seguimiento visual [ Espejo doméstico ]
Código: https://github.com/hyeonseobnam/py-MDNet
Este artículo primero presenta la parte más fácil de todo el artículo: entrenar

Arquitectura

Arquitectura general de MDNet
La figura del documento muestra claramente la arquitectura general de MDNet:

  • La red se divide en dos partes: capas compartidas y capas específicas de dominio. La primera usa el modelo VGG-M y los parámetros de preentrenamiento, y la última tiene K ramas, correspondientes a K secuencias de entrenamiento, también llamadas K dominios (aquí solo la parte conv se carga el modelo preentrenado, y luego conv y fc se entrenan en la fase de aprendizaje fuera de línea)
  • Durante el proceso de entrenamiento, cada iteración extrae 32 muestras positivas y 96 muestras negativas de una secuencia para formar un mini-lote y entrena el correspondiente fc 6 k fc6 ^ {k}f c 6k rama (es decir, cada época, cada rama fc6 se entrena una vez por turno)
  • Cada rama de fc6 genera características bidimensionales, que representan el pos_score y neg_score del objetivo y el fondo respectivamente. La etiqueta para las muestras positivas es [0, 1], la etiqueta para las muestras negativas es [1, 0] y la pérdida usa entropía cruzada binaria: pérdida de entropía cruzada softmax binaria

Ahora veamos cómo se implementan estas partes clave desde el punto de vista del código. Lo más importante es cómo generar muestras positivas y negativas:

Regiones

Debido a que MDNet usa la clasificación para juzgar el objetivo, es necesario construir muestras positivas y negativas para entrenar al clasificador, principalmente a través de las siguientes dos oraciones:

dataset[k] = RegionDataset(seq['images'], seq['gt'], opts)
# take vot2013/cup sequence for example
# seq['images'] -> 'datasets/VOT/vot2013/cup/00000001.jpg',...
# seq['gt'] -> (303, 4) np.ndarray
# training
pos_regions, neg_regions = dataset[k].next()

Y hay un método mágico bajo la clase RegionDataset para __next__()generar 32 pos_regions y 96 neg_regions. Aquí, se seleccionan 8 cuadros en una secuencia, y se generan 4 pos_regions y 12 neg_regions en cada cuadro. Entre ellos, pos_regions está entre el IoU de GT bbox [Las muestras entre 0.7, 1]; neg_regions son las muestras con el IoU de GT bbox entre [0, 0.5], como se indica en el documento For offline multi-domain learning, we collect 50 positive and 200 negative samples from every frame, where positive and negative examples have ≥ 0.7 and ≤ 0.5 IoU overlap ratios with ground-truth bounding boxes, respectively.:

def __next__(self):
    next_pointer = min(self.pointer + self.batch_frames, len(self.img_list)) # 8
    idx = self.index[self.pointer:next_pointer]
    if len(idx) < self.batch_frames:
        self.index = np.random.permutation(len(self.img_list))
        next_pointer = self.batch_frames - len(idx)
        idx = np.concatenate((idx, self.index[:next_pointer]))
    self.pointer = next_pointer

    pos_regions = np.empty((0, 3, self.crop_size, self.crop_size), dtype='float32')
    neg_regions = np.empty((0, 3, self.crop_size, self.crop_size), dtype='float32')
    for i, (img_path, bbox) in enumerate(zip(self.img_list[idx], self.gt[idx])):
        image = Image.open(img_path).convert('RGB')
        image = np.asarray(image)

        n_pos = (self.batch_pos - len(pos_regions)) // (self.batch_frames - i)  # 4 * 8
        n_neg = (self.batch_neg - len(neg_regions)) // (self.batch_frames - i)  # 12 * 8
        pos_examples = self.pos_generator(bbox, n_pos, overlap_range=self.overlap_pos) # [0.7, 1]
        neg_examples = self.neg_generator(bbox, n_neg, overlap_range=self.overlap_neg) # [0, 0.5]

        pos_regions = np.concatenate((pos_regions, self.extract_regions(image, pos_examples)), axis=0)
        neg_regions = np.concatenate((neg_regions, self.extract_regions(image, neg_examples)), axis=0)

    pos_regions = torch.from_numpy(pos_regions)
    neg_regions = torch.from_numpy(neg_regions)
    return pos_regions, neg_regions

Una vez que los datos de entrenamiento están disponibles, el criterio de la función de pérdida y el evaluador se construyen para evaluar si el entrenamiento ha convergido, y el optimizador optimizador:

Función de pérdida

La función de pérdida aquí es muy simple, es directamente la entropía cruzada de dos categorías:

class BCELoss(nn.Module):
    def forward(self, pos_score, neg_score, average=True):
        # pos_score:(32, 2) | neg_score:(96, 2)
        pos_loss = -F.log_softmax(pos_score, dim=1)[:, 1]
        neg_loss = -F.log_softmax(neg_score, dim=1)[:, 0]

        loss = pos_loss.sum() + neg_loss.sum()
        if average:
            loss /= (pos_loss.size(0) + neg_loss.size(0))
        return loss

Se F.log_softmaxtuvo que F.nll_lossser utilizado en conjunción , por lo que la multiplicación por 1 se omite aquí. Puede verse a partir de esto que la etiqueta de las muestras positivas es [0, 1] y la etiqueta de las muestras negativas es [1, 0].

evaluador

El indicador para ver si el entrenamiento se realiza de manera efectiva es Precisión, que se define de la siguiente manera:

class Precision():
    def __call__(self, pos_score, neg_score):
        scores = torch.cat((pos_score[:, 1], neg_score[:, 1]), 0)
        topk = torch.topk(scores, pos_score.size(0))[1]
        # torch.topk -> (values, indexes)
        prec = (topk < pos_score.size(0)).float().sum() / (pos_score.size(0) + 1e-8)
        return prec.item()

Aquí es que la puntuación objetivo más pequeña en pos_regions es mayor que la puntuación objetivo más grande en neg_regions, luego Precision = 1; hay una tendencia: cuantas más pos_regions tengan puntuaciones objetivo más altas que neg_regions, mayor será la precisión.

Hiperparámetros

A continuación, se muestran algunos hiperparámetros utilizados en el documento y en el código:

mejor papel código
iteraciones de aprendizaje fuera de línea 100 mil 50K
lr para conv 0,0001 0,0001
lr para fc 0,001 0,001
Rango de IoU para muestras pos [0,7, 1] [0,7, 1]
Rango de IoU para muestras negativas [0, 0,5] [0, 0,5]

Cifras

La siguiente imagen visualiza las muestras positivas y negativas en la fase de entrenamiento (acabo de seleccionar 16 muestras aquí). El rojo es pos_examples, el azul es neg_examples y el verde es GT bbox.
Visualización de muestras positivas y negativas en la imagen original.

A continuación se muestra la visualización de pos_regions y neg_regions después de recortar con 2 muestras positivas y negativas de las anteriores, que es la entrada de la red. Aquí puede realizar algunas mejoras en los datos del parche.
Regiones positivas y negativas enviadas al aprendizaje en red
A continuación se muestra una captura de pantalla del proceso de entrenamiento, pero la configuración en el código no son La máxima precisión guarda el modelo, pero cada ciclo se sobrescribe y guarda.
Captura de pantalla del proceso de formación

Discutir

La clave de MDNet no está en la fase de capacitación, sino más trucos en la fase de seguimiento en línea, pero hay varios puntos para discutir de la parte de capacitación:

  • El entrenamiento es muy similar a R-CNN, porque el recorte de la imagen original se envía a capas compartidas juntas, lo cual es redundante e ineficiente.
  • Este método de clasificación utiliza una secuencia para entrenar un dominio. Si no hay una parte de actualización en línea, personalmente creo que es más preciso rastrear los objetos que he visto. Por supuesto, la parte de actualización en línea será mucho mejor y la Sin duda, la velocidad será más lenta. Consulte la siguiente parte para obtener más detalles.

Supongo que te gusta

Origin blog.csdn.net/laizi_laizi/article/details/107475865
Recomendado
Clasificación