Principio de pérdida de límites y análisis de código

artículo: Pérdida de límites por segmentación altamente desequilibrada

Introducción

Por lo general, existe un grave problema de desequilibrio de clases en las tareas de segmentación de imágenes médicas. El tamaño del área de primer plano objetivo es a menudo varios órdenes de magnitud más pequeño que el área de fondo. Por ejemplo, en la figura siguiente, el área de primer plano es más de 500 veces más pequeña. que el área de fondo.

La función de pérdida de entropía cruzada comúnmente utilizada para la segmentación tiene una deficiencia bien conocida en problemas altamente desequilibrados: supone que todas las muestras y categorías tienen la misma importancia, lo que a menudo conduce a inestabilidad en el entrenamiento y hace que el límite de decisión esté sesgado hacia una gran número de categorías. Para el problema de desequilibrio de clases, una estrategia común es reducir la muestra de una gran cantidad de clases para reequilibrar la distribución anterior de clases, pero esta estrategia limita el uso de imágenes de entrenamiento. Otra estrategia es la ponderación, es decir, dar mayor peso a las categorías con un número pequeño y menor peso a las categorías con un gran número. Aunque este método es eficaz para algunos problemas de desequilibrio, no es adecuado para tratar con problemas extremadamente desequilibrados. Hay Todavía hay dificultades con los datos. Los gradientes de entropía cruzada calculados en unos pocos píxeles a menudo contienen ruido, y dar pesos mayores a algunas categorías aumenta aún más el ruido y conduce a un entrenamiento inestable.

La pérdida de dados, otra función de pérdida común en la segmentación, generalmente funciona mejor que la pérdida de ce en problemas de segmentación de imágenes médicas desequilibradas. Sin embargo, pueden surgir dificultades cuando se encuentran áreas muy pequeñas: los píxeles mal clasificados pueden provocar una reducción drástica de la pérdida, lo que provoca inestabilidad en la optimización. Además, la pérdida de dados corresponde al promedio armónico de precisión y recuperación. Cuando el verdadero positivo permanece sin cambios, los falsos positivos y falsos negativos tienen la misma importancia, por lo que la pérdida de dados es principalmente adecuada para situaciones en las que el número de errores de estos dos tipos es similar. .

Contribuciones

La pérdida de CE y la pérdida de Dice son funciones de pérdida basadas en distribución y regiones, respectivamente. Este artículo propone una función de pérdida basada en límites que adopta la forma de métrica de distancia en el espacio de contornos en lugar de en el espacio de regiones. La pérdida de límites no calcula la integral sobre la región, sino la integral sobre el límite entre regiones, por lo que puede aliviar los problemas relacionados con la pérdida regional en problemas de segmentación altamente desequilibrados.

Sin embargo, cómo representar los puntos límite correspondientes en función de la salida regional softmax de CNN es un gran desafío. Este artículo se inspira en el uso de métodos de optimización basados ​​​​en gráficos discretos para calcular el flujo de gradiente de evolución de la curva y utiliza el método integral para calcule los cambios en el límite, evitando el contorno Cálculo diferencial local en el punto, la pérdida de límite final es la suma de la función lineal de la probabilidad softmax del área de salida de la red, por lo que se puede usar junto con la pérdida de área existente.

Formulación

 \(I:\Omega \subset \mathbb{R}^{2,3}\rightarrow \mathbb{R}\) representa una imagen en el dominio espacial \(\Omega\), \(g:\Omega \ rightarrow \begin{Bmatrix}
0,1
\end{Bmatrix}\) es el mapa binario de segmentación de verdad fundamental de la imagen, si el píxel \(p\) pertenece al área objetivo \(G\subset \Omega\) (primer plano área),\(g(p)=1\), de lo contrario es 0, es decir\(p\in\Omega\setminus G\) (área de fondo). \(s_{\theta}:\Omega\rightarrow [0,1]\) representa la salida de probabilidad softmax de la red de segmentación, \(S_{\theta}\subset\Omega\) representa la salida del área de primer plano correspondiente por modelo, es decir\( S_{\theta}=\begin{Bmatrix}
p\in\Omega|s_{\theta}(p)\geqslant \delta 
\end{Bmatrix}\), donde \(\delta\) es el umbral fijado de antemano.

Nuestro objetivo es construir una función de pérdida de límites \(Dist(\partial G,\partial S_{\theta })\) que tome la forma de una métrica de distancia en el espacio límite de la región \(\Omega\) donde \(\ G parcial) es una representación del límite del área de verdad fundamental \(G\) (como la suma establecida de todos los puntos en el límite), \(\partial S_{\theta }\) es el límite del Área de segmentación definida por la salida de la red. No está claro cómo representar puntos en \(\partial S_{\theta }\) como funciones diferenciables de la región de salida de la red \(s_{\theta }\). Considere la siguiente representación de \(L_{2}\ distancia\) asimétrica en el espacio de formas, que evalúa el cambio en la distancia entre dos límites adyacentes \(\partial S\) y \(\partial G\)

Donde\(p\in\Omega\) es un punto en el límite\(\partial G\), \(y_{\partial S}(p)\) es el punto correspondiente en el límite\(\partial S\ ), Es decir, \(y_{\partial S}(p)\) es el punto de intersección encontrado en el punto \(p\) en \(\partial G\) y \(\partial S\), como se muestra en La Figura 2(a) Indica que \(\left \| \cdot \right \|\) representa la norma \(L_{2}\). Al igual que otras distancias de contorno que llaman directamente puntos en el contorno \(\partial S\), la fórmula (2) no se puede usar directamente como función de pérdida para \(\partial S=\partial S_{\theta}\). Sin embargo, es fácil demostrar que el cambio de límite diferencial en la ecuación (2) se puede aproximar mediante el método integral, que evita el cálculo diferencial que involucra puntos en el contorno y utiliza integrales de área para representar el cambio de límite, de la siguiente manera

donde \(\bigtriangleup S\) representa el área entre los dos contornos, \(D_{G}:\Omega\rightarrow \mathbb{R}^{+}\) es un área relativa al límite \(\partial G \ ) mapa de distancias , es decir, \(D_{G}(q)\) representa cualquier punto \(q\in\Omega\) y el punto más cercano \(z_{\partial G}( La distancia entre q)\ ): \(D_{G}(q)=\left \| q-z_{\partial G}(q) \right \|\), como se muestra en la Figura 2(b).

Para probar esta aproximación, la gráfica normal versus distancia \(2D_{G }(q)\) Al integrar mediante la siguiente conversión, podemos obtener\(\left \| y_{\partial S(p)}-p \right \|^{2}\)

De la fórmula (3), obtenemos además la siguiente fórmula

donde \(s:\Omega\rightarrow \left \{ 0,1 \right \}\) es la función indicadora binaria del área \(S\): \(s(q)=1\ if\ q\in S \) pertenece al objetivo; de lo contrario, 0. \(\phi _{G}:\Omega\rightarrow \mathbb{R}\) es la representación del conjunto de niveles del límite \(\partial G\): \(\phi _{G}(q)=-D_ {G }(q)\ si\ q\in G\) en caso contrario\(\phi _{G}(q)=D_{G}(q)\). Para \(S=S_{\theta}\), es decir, usando la salida softmax de la red \(s_{\theta}(q)\) para reemplazar \(s(q)\) en la ecuación (4) , obtenemos La pérdida de límite es la siguiente

Tenga en cuenta que eliminamos el último término de la ecuación (4) porque no contiene parámetros del modelo. La función de conjunto de niveles \(\phi_{G}\) se calcula directamente de antemano en función del área gt \(G\). La pérdida de límites se puede combinar con funciones de pérdida basadas en regiones de uso común para problemas de segmentación de clases \(N\).

donde \(\alpha \in\mathbb{R}\) es el parámetro de peso que equilibra las dos pérdidas.

En la ecuación (5), la salida softmax de cada punto \(q\) está ponderada por la función de distancia. En la función de pérdida basada en regiones, esta información de la distancia al límite se ignora y cada punto de la región es ignorado Las distancias límite y los tamaños se procesan todos con el mismo peso.

En la pérdida de límites propuesta por el autor, cuando se retienen todos los valores negativos en la función de distancia (la predicción softmax del modelo para todos los píxeles en el área gt es 1) y se descartan todos los valores positivos (es decir es decir, la predicción softmax del modelo para el fondo Cuando ambos son 0), la pérdida de límites alcanza el mínimo global, es decir, la pérdida de límites es mínima cuando la predicción softmax del modelo genera exactamente la verdad fundamental, que también verifica la efectividad de la pérdida de límites. .

Como se puede ver en experimentos posteriores, generalmente es necesario combinar la pérdida de límites y la pérdida de área para lograr buenos resultados. No entiendo muy bien las razones explicadas por el autor en el artículo, así que publicaré el texto original.

 "Como se discutió anteriormente, el óptimo global de nuestra pérdida de límites corresponde a un valor estrictamente negativo, con las probabilidades softmax produciendo una región de primer plano no vacía. Sin embargo, un primer plano vacío, con valores aproximadamente nulos de las probabilidades softmax en casi todas partes, corresponde a gradientes muy bajos . Por lo tanto, esta solución trivial está cerca de un mínimo local o un punto de silla. Es por eso que integramos nuestra pérdida de límites con una pérdida regional "

experimentos

Comparación de pérdidas regionales

En experimentos comparativos con otras funciones de pérdida, \alpha utiliza una estrategia de reequilibrio, es decir, el valor inicial es 0,01 y aumenta en 0,01 después de cada época.

Se puede ver en la tabla que, ya sea pérdida de entropía cruzada, pérdida general de dados o pérdida focal, se logra una cierta mejora en la precisión después de la combinación de pérdida de límites, lo que indica la efectividad de la pérdida de límites. 

Selección de \(\alpha\)

El autor comparó tres métodos diferentes, uno es constante \(\alpha\), es decir, el valor de \(\alpha\) permanece sin cambios durante todo el proceso de entrenamiento; el segundo es aumentar \(\alpha\), que es la configuración inicial es un valor mayor que 0 pero relativamente pequeño. Después de cada época, el valor \(\alpha\) aumenta gradualmente, pero el peso de la pérdida regional permanece sin cambios hasta el final del entrenamiento. Los pesos de los dos las pérdidas son las mismas; el tercero es reequilibrar \(\alpha\), es decir, combinar las dos pérdidas en la forma de \((1-\alpha)L_{R}+\alpha L_{B}\), aumentando el valor de \(\alpha\) después de cada época, a medida que avanza el entrenamiento, el peso de la pérdida de límites se vuelve cada vez mayor, mientras que el peso de la pérdida regional se vuelve cada vez más pequeño. Los resultados experimentales son los siguientes.

Se puede ver que la estrategia Rebalance logró resultados óptimos, por lo que esta estrategia también se utilizó en todos los experimentos comparativos sobre resultados de pérdidas en otras áreas.

Implementación

Entre ellos, los datos son la verdad fundamental, aquí solo consideramos el caso de dos categorías, es decir, primer plano y fondo. Logits es la salida después de softmax. Por conveniencia, es equivalente a dividir cada píxel en la salida del modelo en la categoría correspondiente a través de argmax o umbral. De hecho, el valor aquí debe ser la salida de softmax, entre [0, 1] entre . El mapa de distancia se calcula mediante la función distancia_transform_edt en la biblioteca scipy. Para obtener una introducción a esta función, consulte el  uso de scipy.ndimage.distance_transform_edt y cv2.distanceTransform.

import torch
import numpy as np
from torch import einsum
from torch import Tensor
from scipy.ndimage import distance_transform_edt as distance
from typing import Any, Callable, Iterable, List, Set, Tuple, TypeVar, Union


# switch between representations
def probs2class(probs: Tensor) -> Tensor:
    b, _, w, h = probs.shape  # type: Tuple[int, int, int, int]
    assert simplex(probs)

    res = probs.argmax(dim=1)
    assert res.shape == (b, w, h)

    return res


def probs2one_hot(probs: Tensor) -> Tensor:
    _, C, _, _ = probs.shape
    assert simplex(probs)

    res = class2one_hot(probs2class(probs), C)
    assert res.shape == probs.shape
    assert one_hot(res)

    return res


def class2one_hot(seg: Tensor, C: int) -> Tensor:
    if len(seg.shape) == 2:  # Only w, h, used by the dataloader
        seg = seg.unsqueeze(dim=0)
    assert sset(seg, list(range(C)))

    b, w, h = seg.shape  # type: Tuple[int, int, int]

    res = torch.stack([seg == c for c in range(C)], dim=1).type(torch.int32)
    assert res.shape == (b, C, w, h)
    assert one_hot(res)

    return res


def one_hot2dist(seg: np.ndarray) -> np.ndarray:
    assert one_hot(torch.Tensor(seg), axis=0)
    C: int = len(seg)

    res = np.zeros_like(seg)
    # res = res.astype(np.float64)
    for c in range(C):
        posmask = seg[c].astype(np.bool)

        if posmask.any():
            negmask = ~posmask
            res[c] = distance(negmask) * negmask - (distance(posmask) - 1) * posmask
    return res


def simplex(t: Tensor, axis=1) -> bool:
    _sum = t.sum(axis).type(torch.float32)
    _ones = torch.ones_like(_sum, dtype=torch.float32)
    return torch.allclose(_sum, _ones)


def one_hot(t: Tensor, axis=1) -> bool:
    return simplex(t, axis) and sset(t, [0, 1])

    # Assert utils


def uniq(a: Tensor) -> Set:
    return set(torch.unique(a.cpu()).numpy())


def sset(a: Tensor, sub: Iterable) -> bool:
    return uniq(a).issubset(sub)


class SurfaceLoss():
    def __init__(self):
        # Self.idc is used to filter out some classes of the target mask. Use fancy indexing
        self.idc: List[int] = [1]  # 这里忽略背景类  https://github.com/LIVIAETS/surface-loss/issues/3

    # probs: bcwh, dist_maps: bcwh
    def __call__(self, probs: Tensor, dist_maps: Tensor, _: Tensor) -> Tensor:
        assert simplex(probs)
        assert not one_hot(dist_maps)

        pc = probs[:, self.idc, ...].type(torch.float32)
        dc = dist_maps[:, self.idc, ...].type(torch.float32)

        multiplied = einsum("bcwh,bcwh->bcwh", pc, dc)

        loss = multiplied.mean()

        return loss


if __name__ == "__main__":
    data = torch.tensor([[[0, 0, 0, 0, 0, 0, 0],
                          [0, 1, 1, 0, 0, 0, 0],
                          [0, 1, 1, 0, 0, 0, 0],
                          [0, 0, 0, 0, 0, 0, 0]]])  # (b, h, w)->(1,4,7)

    data2 = class2one_hot(data, 2)  # (b, num_class, h, w): (1,2,4,7)
    data2 = data2[0].numpy()  # (2,4,7)
    data3 = one_hot2dist(data2)  # bcwh

    logits = torch.tensor([[[0, 0, 0, 0, 0, 0, 0],
                            [0, 1, 1, 1, 1, 1, 0],
                            [0, 1, 1, 0, 0, 0, 0],
                            [0, 0, 0, 0, 0, 0, 0]]])  # (b, h, w)

    logits = class2one_hot(logits, 2)

    Loss = SurfaceLoss()
    data3 = torch.tensor(data3).unsqueeze(0)

    res = Loss(logits, data3, None)
    print('loss:', res)

Tenga en cuenta que para un determinado tipo de área objetivo, al calcular el mapa de distancias, las distancias fuera del área son todas valores positivos y las distancias dentro del área son todas valores negativos, y cuanto más lejos del límite del área, mayor será el valor absoluto. valor. Cuando hay varias categorías, el mapa de distancia se calcula por separado para cada categoría. El área objetivo de cada categoría se trata como un valor de primer plano de 1 y otras áreas tienen un valor de fondo de 0. Idealmente, el modelo debería predecir todos los píxeles fuera del área como fondo, es decir, todas las predicciones son 0, y predecir todos los píxeles dentro del área como primer plano, es decir, 1. En este momento, la pérdida es negativa y alcanza el mínimo global. . 

Supongo que te gusta

Origin blog.csdn.net/ooooocj/article/details/126560722
Recomendado
Clasificación