Serie One Point to Share (Comprensión Parte 5) Suplemento imperdible: mejora de la versión SwintransformerV2.0 y comprensión del uso (Parte 1)

Serie de un punto para compartir (comprensión 5) use la comprensión compartida de SwintransformerV2

Hace un tiempo, actualicé el código de swintransformerV2 en mi almacén Github V5. Hay algunos problemas en el entrenamiento (principalmente porque la columna vertebral apilada es difícil de entrenar por un tiempo. Actualice el cálculo de optimización de memoria restante más tarde. Para una columna vertebral nueva, Usualmente uso adm , reducir la tasa de aprendizaje inicial todavía tiene el problema de caer en la optimización local, pero si solo se entrenan unas pocas capas, el resultado sigue siendo normal, por lo que definitivamente regresaré al horno y lo reconstruiré) lo haré aprovecho para tomarme un tiempo para estudiar de nuevo hoy, y por cierto compensar la actualización del blog, así que no es mucha tontería, hay demasiadas explicaciones sobre SwinV1 en Internet, y todas están bien escritas, así que gané No los analices. ¡El enfoque de hoy es pensar y registrar!

Sección de citas: ¡Narrativa de tesis!

论文- Swin Transformer V2: aumento de capacidad y resolución

1. Swin Transformer v2: capacidad y resolución ampliadas (breve introducción, puede omitir esta sección si ha visto la introducción de swin2)

1. Motivación

  • Swin necesita verificarse en un modelo suficientemente grande, lo que causa problemas: la inestabilidad del entrenamiento hace que el modelo no pueda completar el entrenamiento;
  • Expansión de tareas posteriores: la necesidad de una resolución más alta conduce a una degradación del rendimiento, aumenta el consumo de memoria de la GPU;
  • FLOP excesivos

2. Mejoras proporcionadas por el equipo autor:

  • Posnormalización. (Volviendo a los clásicos, ¿realmente se puede solucionar?)
  • Atención de coseno escalado 。
  • Técnica de codificación de posición continua logarítmica, etc.

Problemas de inestabilidad durante el entrenamiento. En modelos grandes, la diferencia en la magnitud de las salidas de la función de activación entre las capas se hace mayor. Los valores de activación se acumulan capa por capa, por lo que la amplitud de las capas profundas es significativamente mayor que la de las capas superficiales. Como se muestra en la Figura 1 a continuación, es el problema de inestabilidad al expandir la capacidad del modelo.
Cuando escalamos el modelo Swin Transformer original de un modelo pequeño a un modelo grande, el
valor de activación profunda aumenta dramáticamente. La diferencia entre la magnitud más alta y la más baja asciende a 104. Cuando escalamos aún más a un tamaño enorme (parámetros 658M), no puede completar el entrenamiento

inserte la descripción de la imagen aquí

Echemos un vistazo a la tabla de comparación general de modificaciones de BLOQUES V1 y V2, la parte roja:
inserte la descripción de la imagen aquí

Muchas tareas de visión descendente requieren imágenes o ventanas de alta resolución, el modelo de entrenamiento previo se realiza a baja resolución y el ajuste fino
se realiza a alta resolución. Para problemas con diferentes resoluciones, el método tradicional es realizar una interpolación bicúbica en el código de posición
, lo cual es subóptimo.
Como se muestra en la Figura 3 a continuación, la comparación de rendimiento de diferentes métodos de codificación de posición, cuando probamos directamente el modelo Imagenet-1k preentrenado (resolución 256 × 256, tamaño de ventana = 8 × 8) con una resolución de imagen y tamaño de ventana más grandes

Figura: Comparación del rendimiento de diferentes métodos de codificación de posición

Así que un cambio 1: se propuso la posnormalización para el problema de inestabilidad

2. Punto de mejora 1: comprensión de los cambios posteriores a la normalización:

Esto es muy simple: coloque la capa LN en la parte posterior, que antes pertenecía a la norma anterior, y los amigos que están familiarizados con Transformer probablemente tengan la impresión de que LN se ha colocado en la parte posterior, y el diseño en SwinV1.0 está en la forma de pre_layer_norm, así que ¿por qué haces esto?¿Paño de lana? (He trasplantado las mejoras de la versión V2 a mi V5, pero encontré que todavía es difícil de entrenar), la explicación dada es probablemente:
poner la capa de Normalización de Capa detrás de Atención o MLP, y aquí la compartiré con ustedes los resultados de mi investigacion:

El equipo de autores notó que en modelos grandes, la variación en la magnitud de los resultados de la función de activación en las capas se hace mayor. El valor de activación se acumula capa por capa, por lo que la amplitud de la capa profunda es significativamente mayor que la amplitud de la capa superficial: para que la salida de cada bloque residual no cambie demasiado, porque la rama principal y la rama residual son tanto la salida de la capa LN Limitaciones de la normalización LN. Como se muestra en la figura anterior, este enfoque hace que los valores de salida de cada capa sean básicamente iguales. En el entrenamiento del modelo más grande, después de cada 6 bloques de transformadores, se agrega una capa de LN a la rama principal para estabilizar aún más el entrenamiento y la amplitud de salida.

Interludio: Permítanme hablar sobre una interesante explicación de la diferencia entre Pre-norma y Post-norma, de "On Layer Normalization in Transformer Architecture": pre
-LN: En cada entrada,

					output[i+1]=input[i]+Attention(layer_norm(input[i]))

Puede encontrar que Layer_norm controla la varianza de la entrada, es decir, no tiene nada que ver con la cantidad de capas, luego solo la varianza de la entrada en la primera parte se acumulará con la cantidad de capas, luego está lo siguiente analogía:

El modelo es en realidad una profundización pseudo-profunda. Aunque también se amplía, esta idea de identidad puede ser la razón por la cual el modelo es más fácil de entrenar, pero el rendimiento de la red en realidad disminuirá. Cualquiera que deba estar en contacto con PNL sabe que el transformador original Así está diseñado el puesto. (En la primera imagen combinada, podemos encontrar que los valores de salida de las capas profundas y superficiales son significativamente diferentes, especialmente: el gradiente de Pre-LN en la capa inferior suele ser mayor que el de la capa superficial, lo que conduce a la posibilidad de acercarse a la explosión del gradiente. El gradiente inestable provoca una caída del rendimiento posterior a LN en comparación con))

					output[i+1]=input[i]+(i+1)Attention(layer_norm(input[i]))

post-LN: en cada entrada, salida[i+1]=capa_norma(entrada[i]+Atención(entrada[i])), de modo que la norma se ingresa para cada salida, luego la varianza de Entrada se ve afectada por Gran cambia, por lo que esta fórmula no se puede transformar en una versión simplificada de la pre-LN anterior, y el gradiente será difícil de controlar, pero el rendimiento será mejor después del entrenamiento. Si lo entiende desde este ángulo, entonces el "modelo grande" aquí es "ancho" en un cierto sentido de pre-LN, no "profundo", por lo que posnorma en realidad solo alivia el problema de entrenamiento del modelo ancho, porque desde Para entender en cierto sentido, es en la medida de "profundo"?

Comprensión del punto de mejora 1

¡Mas cerca de casa! ¡Resuma brevemente mi aprendizaje y comprensión de la versión V2 para darme una explicación razonable! De lo contrario, realmente no puedo dormir ni comer ~
Aunque la estructura pre-ln es más fácil de entrenar, pero después de la acumulación de BLOCK, el valor de diferencia de la salida de alimentación hacia adelante generada se vuelve más grande, lo que resulta en el problema de "inestable" entrenamiento: principalmente debido a la disminución en el rendimiento del modelo y alta
resolución El siguiente ni siquiera puede converger. Por supuesto, esta es la conclusión experimental. En cuanto a por qué no es tan bueno como post-layer_ln, si la identidad anterior es verdadera, puede ayudar a explicar al mismo tiempo: porque este no es un modelo "profundo" real, porque las capas profundas y superficiales La brecha de gradiente, el entrenamiento no puede continuar convergiendo.

Post-ln en realidad trata de resolver el "problema de inestabilidad" en el entrenamiento. Específicamente, solo resuelve el problema de entrenamiento causado por el aumento de la dimensión del canal generado por la acumulación de bloques, y controla el gradiente, pero no resuelve y descubre el modelo profundo real El problema de entrenamiento, y bajo la premisa de que se establece el análisis mencionado anteriormente de post-LN, post-LN de hecho traerá un mejor rendimiento, todavía hay fenómenos de explosión o desaparición de gradiente y problemas de entrenamiento más profundos, aquí hay un pit, porque solo mire swinv2 y su comprensión solo está aquí.

Por lo tanto, ambos métodos LN tendrán un entrenamiento inestable.Bajo esta premisa, pre-LN puede ser más fácil de converger en un modelo grande, pero el rendimiento disminuirá y el método Post puede ser más difícil de entrenar (¿por qué? Tiene obviamente suprimió el problema del gradiente del modelo), pero el efecto será mejor. Cuando se expande a un modelo profundo de súper gran escala, estos dos métodos tienen defectos al mismo tiempo. Generalmente, la dificultad de entrenamiento de los modelos profundos proviene de la desaparición del gradiente o explosión de gradiente, pero en el transformador profundo, todavía hay más problemas, entonces, ¿cuál es el mayor problema que ni el método Pre ni el Post pueden resolver? ¿Cuál es exactamente el problema real en swintransformer? Si el pre- es que el gradiente no está bajo control, ¿entonces el gradiente también tiene la culpa del problema de inestabilidad que todavía se presenta en el entrenamiento de Post-LN a cierta profundidad?

Aquí, intentaré proporcionar una explicación razonable para este fenómeno. Por supuesto, no puedo garantizar que sea completamente correcto. Primero mire la imagen a continuación.
inserte la descripción de la imagen aquí

En pocas palabras, el método Post-Norma de SwinV2.0 es solo un medio para el control de gradiente, pero el culpable detrás de escena sigue bloqueando el progreso del paradigma del transformador profundo a gran escala. El equipo es obvio Paradigma, por lo que tienen que demostrar que tienen capacidades a gran escala como CNN Si aterrizas en la luna, tengo que aterrizar en la luna también.

3. Razonamiento: problema del transformador de capa N de entrenamiento

El reciente "DeepNet: Scaling Transformers to 1,000 Layers" producido por Microsoft siguió esta idea para normalizar e inicializar el modelo, y finalmente entrenó con éxito un modelo de Transformer de 1,000 capas. El diseño de DeepNeT puede estabilizar el proceso de optimización al aliviar el explosivo problema de actualización del modelo. Para obtener más información, puede leer el documento usted mismo.
Actualización del modelo a gran escala al comienzo del entrenamiento: cuanto más profundo es el modelo, mayor es la cantidad de actualización, lo que significa que es más probable que el modelo ingrese en un óptimo local incorrecto en la etapa inicial, y luego el entrenamiento no puede continuar convergiendo. ¿Esto es lo que se muestra en la figura ? ? ? ? —————— Problema de “Explosión Incremental”.
La solución generalmente es usar una tasa de aprendizaje más pequeña en la etapa inicial y luego aumentar lentamente la tasa de aprendizaje: calentamiento; de lo contrario, es necesario ajustar manualmente los parámetros según la experiencia para tratar de compensar la brecha incremental inicial;

Método 1: ajustar la inicialización

Haz que el entrenamiento de Transformer sea más estable. Por lo tanto, los investigadores analizaron el proceso de formación de Post-LN con y sin inicialización adecuada. A través de una mejor inicialización, después de realizar
la inicialización de Xavier, reduzca la escala de los pesos de la capa L. La relación de disminución es:
[oficial]
Por ejemplo, el peso del FFN de la capa L se inicializa como, d 'es el valor medio de las dimensiones de entrada y salida
inserte la descripción de la imagen aquí
donde d' es el promedio de las dimensiones de entrada y salida. Los investigadores llamaron a este modelo Post-LN-init. Tenga en cuenta que, a diferencia de trabajos anteriores (Zhang et al., 2019a), Post-LN-init es una extensión que estrecha las capas inferiores en lugar de las superiores. Los investigadores creen que este enfoque ayuda a separar los efectos de la expansión del gradiente de las actualizaciones del modelo. Además, Post-LN-init tiene la misma arquitectura que Post-LN, eliminando así la influencia de la arquitectura.
El estudio entrenó 18L-18L Post-LN y 18L-18L Post-LN-init en el conjunto de datos de traducción automática IWSLT-14 De-En. La Figura 3 visualiza sus curvas de gradiente y pérdida de validación. Como se muestra en la Figura 3©, Post-LN-init converge, mientras que Post-LN no lo hace. Post-LN-init tiene normas de gradiente más grandes en las últimas capas, aunque sus pesos se reducen. Además, visualizamos la norma de gradiente de la última capa del decodificador con profundidades de modelo de 6L-6L a 24L-24L.
La figura 3 a continuación muestra que, independientemente de la profundidad del modelo, la norma de gradiente de la última capa Post-LN-init sigue siendo mucho mayor que la de Post-LN. Concluimos que la explosión de gradientes profundos no debería ser la causa raíz de las inestabilidades posteriores a LN, y que las extensiones de las actualizaciones del modelo a menudo pueden explicar esto.
inserte la descripción de la imagen aquí

Para resumir la conclusión: la causa raíz de la inestabilidad POST-LN no es el problema del gradiente

DeepNet: modelo de transformador muy profundo

El autor de DeepNET diseñó con la idea de "no actualizar los parámetros del modelo demasiado rápido en la etapa inicial", DeepsNorm: la compensación pre-lN y pre
deepnet combinada con post y pre ha sido mejorada a deep-norm :
inserte la descripción de la imagen aquí
donde α es una constante, G_l(x_l, θ_l) es una función de la l-ésima subcapa del Transformador (es decir, red de atención o feed-forward) con parámetro θ_l. DeepNet también extiende el peso θ_l dentro del residual por β. A continuación, los investigadores proporcionan una estimación de la magnitud esperada de la actualización del modelo DeepNet. Visualizaron las actualizaciones del modelo de Post-LN y DeepNet en la fase inicial de capacitación en el conjunto de datos de traducción IWSLT-14 De-En, como se muestra en la Figura 5 a continuación. Se puede ver que en comparación con Post-LN, la actualización del modelo de DeepNet se mantiene casi constante.
inserte la descripción de la imagen aquí
En comparación con el formulario Post-LN, el modelo es más estable.
Luego, los investigadores demostraron que la inestabilidad de Post-LN proviene de una serie de problemas, que incluyen gradientes que se desvanecen y actualizaciones de modelos demasiado grandes. Como se muestra en la Figura 4(a), primero visualizan la norma de la actualización del modelo ||ΔF|| en las primeras etapas del entrenamiento:

inserte la descripción de la imagen aquí

donde x y θ_i representan los parámetros de entrada y del modelo después de la i-ésima actualización, respectivamente. Post-LN tiene actualizaciones explosivas al comienzo del entrenamiento, y luego casi no hay actualizaciones muy rápidamente. Esto indica que el modelo se ha quedado atascado en un óptimo local falso. Tanto el calentamiento como una mejor inicialización pueden ayudar a aliviar este problema, lo que permite que el modelo se actualice sin problemas. Al actualizar la explosión, la entrada a LN se vuelve más grande (ver Fig. 4(b) y Fig. 4©). Según el análisis teórico de Xiong y otros (2020), el tamaño del gradiente a través del LN es inversamente proporcional al tamaño de su entrada:
inserte la descripción de la imagen aquí
en comparación con el caso sin calentamiento o inicialización adecuada, Fig. 4(b) y Fig. .4© muestran que ||x|| es significativamente mayor que inserte la descripción de la imagen aquí
, lo que explica el problema del gradiente de fuga en el entrenamiento Post-LN (consulte la Figura 4(d)).

La inestabilidad comienza con grandes actualizaciones del modelo al comienzo del entrenamiento. Atrapa al modelo en malos óptimos locales (el tamaño del gradiente a través del LN es inversamente proporcional al tamaño de su entrada), lo que significa volver a aumentar la cantidad de entrada para cada LN. A medida que continúa el entrenamiento, el gradiente a través del LN se vuelve cada vez más pequeño, lo que provoca una desaparición severa del gradiente, lo que dificulta escapar de los óptimos locales y desestabiliza aún más la optimización. Por el contrario, la actualización de Post-LN-init es relativamente pequeña y la entrada a LN es estable. Esto alivia el problema de los gradientes que desaparecen y hace que la optimización sea más estable.

Hasta ahora, DeepNorm me ha dicho cuál es la causa raíz de nuestro problema de inestabilidad de gradiente posterior a LN, ¡así que pongámonos manos a la obra!

4. Punto de mejora 2 - Tecnología de atención de coseno escalado: resuelve el problema de inestabilidad en el entrenamiento.

En el cálculo original de autoatención, la similitud entre la consulta y la clave se mide por el producto escalar. El autor descubrió que el mapa de atención aprendido de esta manera a menudo está dominado por una pequeña cantidad de pares de píxeles. Así que cambie el punto a una función de coseno y utilícelo para medir la similitud entre la consulta y la clave.

inserte la descripción de la imagen aquí

En la fórmula, Bij es el código de posición relativa que se menciona a continuación y T es un parámetro que se puede aprender. La función coseno se normaliza naturalmente, por lo que puede tener un valor de atención más suave.

Al usar el mecanismo de atención del coseno, entiendo que se mejora la distribución numérica de toda la salida, lo que desempeña un papel de normalización, de modo que el mapa de atención no suele estar dominado por valores más altos.

Aunque el código no es de código abierto, estos cambios son relativamente simples:

		#dot 改成cosine ,并初始化一个参数给NET
 	 self.register_parameter("tau", nn.Parameter(torch.zeros(1, num_heads, 1, 1)))

	 attn= (q @ k.transpose(-2, -1)) 
	 attn=attn /torch.maximum(torch.norm(q, dim=-1, keepdim=True)   * torch.norm(k, dim=-1, keepdim=True).transpose(-2, -1),torch.tensor(1e-06, device=q.device, dtype=q.dtype))
	 attn/=self.tau.clamp(min=0.01)

¡Entonces necesita generar un tensor codificado de posición relativa antes de continuar con el cálculo! Excepto por el cálculo de B posterior, básicamente no hay diferencia con 1.0.

5. Punto de mejora 3: tecnología de codificación de posición continua logarítmica: ¡resuelva el problema de la inconsistencia en las dimensiones de codificación de posición causadas por cambios de resolución y suavice las tareas posteriores!

Este método puede transferir de manera más fluida los pesos de los modelos entrenados previamente en baja resolución para manejar los pesos de los modelos en alta resolución. Primero revisamos
la tecnología de codificación de posición relativa de Swin Transformer.

[oficial]

En la fórmula, B es el sesgo de posición relativa de cada cabeza (sesgo de posición relativa), Q, K, V son la consulta, la clave y el valor de la atención basada en la ventana. M es el tamaño de la ventana.

Cuando se cambia la resolución de entrada en la tarea posterior, el tamaño de la ventana también puede cambiar, lo que hace que sea imposible transferir directamente. El enfoque de Swin es el mismo que el de ViT, usando interpolación bicúbica. Este método no es óptimo, por lo tanto, introduzca sesgo de posición continua en el espacio logarítmico: Registre la tabla_sesgo_de_posición_relativa anterior como "sesgos parametrizados". El nuevo método del autor no optimiza directamente los sesgos parametrizados, sino que utiliza una metared pequeña (MLP de 2 capas con función de activación de ReLU) para generar sesgos parametrizados:

[oficial]

Cuando la resolución de entrada cambia, el tamaño de la ventana también cambiará. El autor usa las coordenadas de posición relativas en el espacio logarítmico:

[oficial]

El autor afirma que después de pasar la función de registro, la posición relativa de [-7, 7] * [-7, 7] de la ventana original de 8x8 se convertirá en [-2.079, 2.079] * [-2.079, 2.079], si se duplica la posición relativa de la ventana de 16x16 [-15, 15] * [-15, 15] se convertirá en [-2.773, 2.773] * [-2.773, 2.773]. Los cambios de codificación de posición posteriores al registro son pequeños, lo que lo hace estable.

Este es también el cálculo de seguimiento para la codificación B, referencia de código completa:

class WindowAttention(nn.Module):

 	def __init__(self, dim, window_size, num_heads, qkv_bias=True, attn_drop=0., proj_drop=0.,meta_network_hidden_features=256):
 			#创建一个meta netowrk:2liner +rule
			self.meta_network = nn.Sequential(
            nn.Linear(in_features=2, out_features=meta_network_hidden_features, bias=True),
            nn.ReLU(inplace=True),
            nn.Linear(in_features=meta_network_hidden_features, out_features=num_heads, bias=True))
            self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
       		self.attn_drop = nn.Dropout(attn_drop)
       		self.proj = nn.Linear(dim, dim)
      		self.proj_drop = nn.Dropout(proj_drop)
      		#注册可学习参数T
            self.register_parameter("tau", nn.Parameter(torch.zeros(1, num_heads, 1, 1)))
             # Init pair-wise relative positions (log-spaced)
             #根据windowsize给窗口编号,再压平
       	    indexes = torch.arange(self.window_size[0], device=self.tau.device)
            coordinates = torch.stack(torch.meshgrid([indexes, indexes]), dim=0)
            coordinates = torch.flatten(coordinates, start_dim=1)
            #利用广播机制 ,然后进行相减,得到相对位置关系-横纵坐标偏移
            relative_coordinates = coordinates[:, :, None] - coordinates[:, None, :]
            relative_coordinates = relative_coordinates.permute(1, 2, 0).contiguous().reshape(-1, 2).float()
            #对数空间的相对位置坐标计算
            relative_coordinates_log = torch.sign(relative_coordinates) \
                                                 * torch.log(1. + relative_coordinates.abs())
            self.register_buffer("relative_coordinates_log", relative_coordinates_log) 
            self.softmax = nn.Softmax(dim=-1)

  def forward(self, x, mask = None):
        """
        Args:
            x: input features with shape of (num_windows*B, Mh*Mw, C)
            mask: (0/-inf) mask with shape of (num_windows, Wh*Ww, Wh*Ww) or None
        """
        # [batch_size*num_windows, Mh*Mw, total_embed_dim]
        B_, N, C = x.shape
        # qkv(): -> [batch_size*num_windows, Mh*Mw, 3 * total_embed_dim]
        # reshape: -> [batch_size*num_windows, Mh*Mw, 3, num_heads, embed_dim_per_head]
        # permute: -> [3, batch_size*num_windows, num_heads, Mh*Mw, embed_dim_per_head]
        qkv = self.qkv(x).reshape(B_, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
        # [batch_size*num_windows, num_heads, Mh*Mw, embed_dim_per_head]
        q, k, v = qkv.unbind(0)  # make torchscript happy (cannot use tensor as tuple)
        attn = torch.einsum("bhqd, bhkd -> bhqk", q, k) \
                                      / torch.maximum(torch.norm(q, dim=-1, keepdim=True)
                                                      * torch.norm(k, dim=-1, keepdim=True).transpose(-2, -1),
                                                      torch.tensor(1e-06, device=q.device, dtype=q.dtype))
        attn/=self.tau.clamp(min=0.01)
        
        relative_position_bias = self.meta_network(self.relative_coordinates_log)
        relative_position_bias = relative_position_bias.permute(1, 0)
        relative_position_bias = relative_position_bias.reshape(self.num_heads, self.window_size[0] * self.window_size[1],\
                                                                                        self.window_size[0] * self.window_size[1])
         
        attn = attn + relative_position_bias.unsqueeze(0)
        #attn = attn + self.get_relative_positional_encodings()
        if mask is not None:
            # mask: [nW, Mh*Mw, Mh*Mw]
            nW = mask.shape[0]  # num_windows
            # attn.view: [batch_size, num_windows, num_heads, Mh*Mw, Mh*Mw]
            # mask.unsqueeze: [1, nW, 1, Mh*Mw, Mh*Mw]
            attn = attn.view(B_ // nW, nW, self.num_heads, N, N) + mask.unsqueeze(1).unsqueeze(0)
            attn = attn.view(-1, self.num_heads, N, N)
            attn = self.softmax(attn)
        else:
            attn = self.softmax(attn)

        attn = self.attn_drop(attn)
        x = torch.einsum("bhal, bhlv -> bhav", attn, v)
    
        return x

6. Mejora 4: reducción de memoria GPU

Zero-Redundancy Optimizer (ZeRO) from《Zero: Optimizaciones de memoria para entrenar trillones de modelos de parámetros》:

Los métodos tradicionales de entrenamiento en paralelo de datos (como DDP) transmiten el modelo a cada GPU, lo cual es muy poco amigable para los modelos grandes. Por ejemplo, para modelos grandes con parámetros de 3,000M = 3B, si se usa el optimizador Adam, 32 Para el flotante -número de punto, ocupará 48G de memoria GPU. Al usar el optimizador ZeRO, los parámetros del modelo y los estados de optimización correspondientes se dividen y distribuyen a varias GPU, lo que reduce considerablemente el consumo de memoria. Use el marco DeepSpeed, la opción ZeRO etapa 1 durante el entrenamiento.

Activación de puntos de verificación de 《Entrenamiento de redes profundas con costo de memoria sublineal》

El mapa de características en la capa de Transformador también consume mucha memoria GPU, lo que se convertirá en un cuello de botella en el caso de imágenes y ventanas de alta resolución. Esta optimización puede reducir la velocidad de entrenamiento hasta en un 30%.

Cálculo secuencial de autoatención:

Al entrenar un modelo grande con una resolución muy grande, como una resolución de 1535×1536 y un tamaño de ventana de 32×32, después de usar las dos estrategias de optimización anteriores, para una GPU convencional (40 GB de memoria), sigue siendo insoportable. Los autores encontraron que en este caso, el módulo de autoatención constituye el cuello de botella. Para resolver este problema, el autor implementó un cálculo de autoatención secuencial en lugar de utilizar el método de cálculo por lotes anterior. Esta optimización se aplica a cada capa en las dos primeras etapas y tiene una cierta mejora en la velocidad de entrenamiento general.
En este trabajo, los autores también escalan modestamente el conjunto de datos de ImageNet-22k en un factor de 5 a 70 millones de imágenes con etiquetas ruidosas. También se emplea un enfoque de aprendizaje autosupervisado para hacer un mejor uso de estos datos. Al combinar estas dos estrategias, los autores entrenaron un poderoso modelo Swin Transformer con 3 mil millones de parámetros, actualizaron los indicadores de múltiples conjuntos de datos de referencia y pudieron aumentar la resolución de entrada a 1536 × 1536 (GPU Nvidia A100-40G). Además, los autores comparten algunos detalles clave de implementación de SwinV2 que generan ahorros significativos en el consumo de memoria de la GPU, lo que hace posible entrenar modelos de gran visión con GPU convencionales. El objetivo del autor es estimular una mayor investigación en la dirección de la visión previa al entrenamiento de modelos grandes, y así eventualmente cerrar la brecha de capacidad entre los modelos de visión y los modelos de lenguaje.

De hecho, la principal mejora de SWINV2.0 es mejorar las dificultades encontradas en la tarea de expansión del modelo. El contenido central: control de gradiente y reducción de sobrecarga; algunos códigos están adaptados a YOLOV5. En la depuración y verificación interminables, algunos códigos necesitan ser optimizado Cálculo de atención para reducir la variable de memoria GPU y resolución

Supongo que te gusta

Origin blog.csdn.net/weixin_44119362/article/details/123528547
Recomendado
Clasificación