De transformador a ViT: análisis de principios e implementación del algoritmo de codificador multimodal

La arquitectura Transformer es una red neuronal que utiliza un mecanismo de autoatención, propuesto originalmente por Google, y es ampliamente utilizado en tareas de procesamiento de imágenes y procesamiento de lenguaje natural. Es un modelo de aprendizaje profundo basado en la atención adecuado para tareas de aprendizaje de secuencia a secuencia, como traducción automática, reconocimiento de voz, resumen de texto, etc.

El algoritmo codificador de la parte frontal del Transformador multimodal es una de las líneas de investigación que más ha llamado la atención en el campo de la visión artificial en los últimos años. Su aparición ha favorecido mucho la fusión y procesamiento de información multimodal, y es ampliamente utilizado en el procesamiento de diversos tipos de datos como imágenes y textos.

Entre ellos, Vision Transformer (ViT) es un codificador visual basado en Transformer que ha logrado excelentes resultados en varias tareas visuales. Este blog presentará el principio del algoritmo del codificador en la primera parte del Transformador multimodal, centrándose en su implementación en ViT, y viene con una implementación completa del código ViT. Si está interesado en el algoritmo del codificador de la primera parte del Transformador multimodal, o desea tener una comprensión más profunda de la implementación de ViT, este artículo puede ayudarlo.

El siguiente es el diagrama de la arquitectura central del modelo vit, y la siguiente es una introducción detallada a cada parte de la arquitectura del modelo.
inserte la descripción de la imagen aquí

Principios de algoritmos y arquitectura de modelos

Incrustación de token de imagen

El modelo ingresa una imagen de 28x28x3, y el modelo primero corta la imagen en 16 piezas, cada una de las cuales es de 7x7. Todavía 3 canales.

Luego combine los datos de 3 canales de 7x7 en una fila, [1,7x7x3]=[1,147],
hay 16 bloques, es decir, [16,147].

A continuación, convierta la imagen en un vector de características Incrustación:
Imagen 16 ∗ 147 Imagen_{16*147}me imagino _ _16 147* AN 147 ∗ 96 AN_{147*96}W147 96= Incrustación IncrustaciónIncrustación _ _ _ _ _

Ancho 147 ∗ 96 Ancho_{147*96}W147 96Es el parámetro que se va a entrenar, que es la incrustación de parches en la figura a continuación,
inserte la descripción de la imagen aquí

Proceso de autoatención de varios cabezales

De acuerdo con la incrustación de token de imagen convertida a partir de la entrada de imagen por el modelo, asumimos que el conjunto de bloques de imagen es [ x 1 , x 2 , . . . , x 16 ] [{x_1, x_2, ..., x_{ dieciséis}}][ X1,X2,... ,X16] , la dimensión de cada bloque de imagen es96 × 16 96 \times 1696×16 , y luego ingrese esta incrustación en el transformador.
inserte la descripción de la imagen aquí
En el transformador, primero ingrese la Autoatención de cabezales múltiples para realizar los siguientes cuatro pasos: transformación lineal, mecanismo de cabezales múltiples, escala y softmax, y mecanismo de cabezales múltiples. A continuación describimos paso a paso el flujo algorítmico de estos pasos.

transformación lineal

Primero dividimos cada parche de imagen xi x_iXyoAsignado a un vector de 10 dimensiones zi z_izyo

Este mapeo se realiza emparejando xi x_iXyoHaz una transformación lineal para obtener, en concreto, xi x_iXyomultiplicar por 96 × 10 96 \times 1096×matriz de 10 pesos W q W_qWqObtenga un vector de 10 dimensiones zi z_izyo

inserte la descripción de la imagen aquízi = W qai z_i = W_q a_izyo=Wqayo

zi z_i en esozyoEl vector contiene qi , ki , vi q_i,k_i,v_iqyo,kyo,vyo, el entrenamiento del modelo necesita calcular los parámetros. Hay tres matrices de transformación W q , W k , W v W_q, W_k, W_vWqWkWv

MatMul

Calculamos x_i para cada parche de imagen xiXyoPuntuación de atención con todos los demás parches de imagen. Específicamente, calculamos para cada par de parches de imagen ( xi , xj ) (x_i, x_j)( Xyo,Xj) puntuación de atenciónai , j a_{i,j}ayo , jy utilícelo para sumar ponderadamente las representaciones vectoriales de todos los parches de imagen.

Para calcular el puntaje de atención, primero debemos calcular la "similitud" entre cada par de parches de imagen.

Esta similitud se calcula sumando qi q_iqyocon kj k_jkjHaz el producto escalar para obtenerlo.
Entre ellos, qi q_iqyoy kj k_jkjson los bloques de imagen iii y bloque de imagenjjj es el vector obtenido por transformación lineal. El resultado de este producto escalar puede considerarse como la similitud del coseno de dos vectores, que se usa para medir la similitud entre ellos,i ∈ [ 1 , 16 ] , j ∈ [ 1 , 16 ] i \in[1,16] ,j\en [1,16]i[ 1 ,16 ] ,j[ 1 ,16 ]

sj = qi ⋅ kj s_j = q_i \cdot k_jsj=qyokj

inserte la descripción de la imagen aquí

Escala y softmax

Sin embargo, calcular directamente el producto escalar puede causar inestabilidad computacional debido a la gran dimensión del vector, por lo que primero calculamos qi q_iqyoy kj k_jkjdividir por un factor de escala de 10 \sqrt{10}10 , es decir, la dimensión de la característica es 10, para garantizar que el valor del producto punto sea pequeño, y la inestabilidad del cálculo no es fácil de producir, y luego se calcula la función softmax.

La fórmula específica es la siguiente:

pj = softmax ( ∑ i ∑ jqi ⋅ kj 10 ) = qi ⋅ kj 10 ∑ i ∑ jqi ⋅ kj 10 p_j =softmax(\sum_{i}\sum_{j}\frac{q_i \cdot k_j}{\sqrt{ 10}})=\frac{ \frac{q_i \cdot k_j}{\sqrt{10}}}{\sum_{i}\sum_{j} \frac{q_i \cdot k_j}{\sqrt{10}} }pagj=entonces f t máx ( _ij10 qyokj)=yoj10 qyo⋅k _j10 qyo⋅k _j

donde, ⋅ \cdot⋅Indica la operación de producto escalar vectorial. El denominador de la puntuación de atención10 \sqrt{10}10 es un factor de escala que se utiliza para garantizar que el resultado del producto escalar no sea demasiado grande ni demasiado pequeño.

MatMul

Finalmente combine el vector vi v_ivyoCalcular xi x_iXyoEl vector de características de atención zi z_i dezyo

zi = ∑ ii = 16 pi ∗ vi z_i=\sum_{i}^{i=16} p_i*v_izyo=iyo = 16pagyovyo

El proceso específico se puede ver en la siguiente figura.

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

Lo anterior es para la atención propia, y hay otro tipo de atención múltiple.
La realización de la atención múltiple es en realidad la combinación de múltiples estructuras de atención propia, como se muestra en la figura a continuación.
inserte la descripción de la imagen aquí
El xx anteriorx,就是 [ x 1 , x 2 , x 3 , . . . , x 16 ] [x_1,x_2,x_3,...,x_{16}] [ X1,X2,X3,... ,X16] combinados, desde la perspectiva de la primera autoatención,Q 1 , K 1 , V 1 Q_1,K_1,V_1q1,k1,V1De hecho, es [ q 1 , q 2 , q 3 , . . . , q 16 ], [ k 1 , k 2 , k 3 , .v 3 , . . . , v 16 ] [q_1,q_2,q_3 ,...,q_{16}],[k_1,k_2,k_3,...,k_{16}],[v_1,v_2,v_3 ,...,v_{16}][ q1,q2,q3,... ,q16] ,[ k1,k2,k3,... ,k16] ,[ v1,v2,v3,... ,v16]

Los toros solo se preocupan computacionalmente, cada autoatención q no solo debe calcularse con su propia k y v, sino también combinarse con otros cálculos de autoatención k y v.

El ejemplo más simple para entender la atención, tomemos un ejemplo de la vida.

Cuando comparamos el algoritmo de autoatención con el proceso de un estudiante que aprende una materia, podemos comparar qqq se considera como la atencion del alumno,kk como el contorno del sujeto,vvv representa el contenido del libro de texto de esta asignatura. Calculandoqqq ykLa similitud de k puede obtener el peso de la distribución entre el consumo de atención de los estudiantes y los diferentes puntos de conocimiento en el esquema, para determinar en qué puntos de conocimiento los estudiantes deben enfocarse en aprender. Finalmente, al multiplicar estos pesos porvvv , puede obtener el contenido de conocimiento que los estudiantes han aprendido.

El algoritmo de atención de múltiples cabezas se puede comparar con una situación en la que un estudiante está estudiando varias materias. En este caso, diferentes temas pueden tener diferentes niveles de dificultad, contenido y formato. Por lo tanto, la capacidad de atención de los estudiantes puede variar en diferentes materias. A través del algoritmo de atención de múltiples cabezas, podemos dividir la atención del estudiante qqq y los puntos de conocimiento kken diferentes esquemas de materiask y contenido del temavvv se multiplican entre sí para obtener los resultados de aprendizaje de diferentes materias. La ventaja de esto es que las ventajas de diferentes materias se pueden utilizar mejor para mejorar aún más el efecto de aprendizaje de los estudiantes.

módulo de capa delantera

El módulo de capa directa consta de dos capas completamente conectadas y una conexión residual. Las conexiones residuales agregan la entrada directamente a la salida del módulo. La capa completamente conectada incluye una transformación lineal y una función de activación, donde la transformación lineal multiplica la entrada x por una matriz de peso W1, agrega un sesgo b1 y luego ingresa el resultado en la función de activación para la transformación no lineal. La función de activación suele ser ReLU.

La fórmula de cálculo del módulo de la capa delantera es la siguiente:

FFN ( x ) = max ⁡ ( 0 , x W 1 + segundo 1 ) W 2 + segundo 2 + x \mathrm{FFN}(x) = \max(0, xW_1+b_1)W_2+b_2 + xFFN ( x )=máx ( 0 ,x ancho1+b1) W2+b2+X

donde xxx significa entrada,W 1 W_1W1y b 1 b_1b1es la matriz de pesos y el vector de sesgo de la primera capa completamente conectada, W 2 W_2W2y b 2 b_2b2es la matriz de pesos y el vector de polarización de la segunda capa totalmente conectada.

AÑADIR módulo NORM

El módulo ADD NORM consiste en una conexión residual y una Normalización de Capa. Las conexiones residuales agregan la entrada directamente a la salida del módulo. La normalización de capas se utiliza para normalizar las características de cada muestra en diferentes dimensiones.

La fórmula de cálculo del módulo ADD NORM es la siguiente:

Capa N orm ( x + S subcapa ( x ) ) \mathrm{LayerNorm}(x+\mathrm{Subcapa}(x))Normas de capa ( x+Subcapa ( x ))

donde xxx representa la entrada y Sublayer representa una subcapa en el modelo de Transformer (como un módulo de autoatención o un módulo de capa de avance). x + Subcapa ( x ) x+\mathrm{Subcapa}(x)X+Subcapa ( x ) representa la entrada más la salida de la subcapa. LayerNorm parax + Subcapa ( x ) x+\mathrm{Subcapa}(x)X+Subcapa ( x ) para la normalización.

pensar

Después de comprender los principios de cada estructura del algoritmo, los siguientes son algunos de mis pensamientos personales.

¿Por qué esta estructura de transformador calcula el vector de características original a través de la similitud con el contexto (o las imágenes superior e inferior), y el nuevo vector de características obtenido puede representar con mayor precisión el vector de características de estos datos?

La estructura Transformer es muy utilizada en procesamiento de lenguaje natural y visión artificial, principalmente porque presenta las siguientes ventajas:

  1. La información contextual es abundante. En comparación con los métodos tradicionales basados ​​en características diseñadas manualmente, Transformer puede usar información contextual para representar vectores de características con mayor precisión. En el procesamiento del lenguaje natural, el contexto puede ser la oración o el párrafo donde se encuentra la palabra actual, mientras que en la visión artificial, el contexto puede ser la región de la imagen donde se encuentra el píxel actual.
  2. Gran capacidad para manejar secuencias largas. Debido al uso del mecanismo de autoatención, Transformer puede procesar secuencias largas de manera eficiente. En el procesamiento de lenguaje natural, esto permite que Transformers procese texto largo y en visión por computadora, esto permite que Transformers procese imágenes de alta resolución.
  3. Aprendizaje de extremo a extremo. La estructura de Transformer puede aprender representaciones de características directamente de datos sin procesar sin diseñar características manualmente. Esto permite que el modelo aprenda representaciones de características más precisas a partir de los datos sin procesar, mejorando así el rendimiento del modelo.

Por qué la atención de múltiples cabezas es mejor que la autoatención

La atención de múltiples cabezas es un mecanismo de atención utilizado en el modelo Transformer, que puede mejorar el rendimiento del modelo en comparación con el uso del mecanismo de autoatención solo. Esto se debe principalmente a las siguientes razones:

  1. La atención de múltiples cabezas puede procesar información diferente en paralelo. En la atención de múltiples cabezas, el modelo aprende información diferente simultáneamente usando múltiples cabezas de atención. Esto significa que el modelo puede procesar múltiples piezas de información diferentes en paralelo, lo que acelera el proceso de entrenamiento e inferencia del modelo.
  2. La atención de múltiples cabezas puede aprender representaciones de características más complejas. Dado que la atención de múltiples cabezas puede procesar información múltiple en paralelo, el modelo puede aprender representaciones de características más complejas. Esto puede ayudar al modelo a capturar características más ricas y diversas, mejorando así el rendimiento del modelo.
  3. La atención de múltiples cabezas puede mejorar la capacidad de generalización del modelo. En la atención de múltiples cabezas, cada cabeza de atención puede aprender una representación de características diferente, lo que hace que el modelo sea más sólido y generalice mejor los nuevos datos.

En general, la atención de múltiples cabezas puede procesar información múltiple en paralelo, aprender representaciones de características más complejas y mejorar la capacidad de generalización del modelo, lo que lo hace mejor que usar solo el mecanismo de autoatención.

En el transformador hay múltiples codificadores superpuestos, ¿cuál es su función?, ¿es afinar continuamente la relación entre la imagen y la similitud de la imagen?

En el modelo Transformer, el codificador apila varias capas, cada una de las cuales contiene una red neuronal de alimentación y atención de varios cabezales. El papel del codificador que apila múltiples capas es extraer y combinar gradualmente la información en la secuencia de entrada y generar una representación de características más precisa. Estas representaciones de características se utilizan finalmente para tareas posteriores, como traducción automática, modelos de lenguaje, clasificación de texto, etc.

Específicamente, cada capa en el codificador puede refinar aún más la representación de características del modelo. Al apilar varias capas, el modelo puede capturar gradualmente más información en la secuencia de entrada, lo que da como resultado representaciones de características más precisas. Estas representaciones de características pueden reflejar información importante en la secuencia de entrada y pueden usarse para tareas posteriores.

Por lo tanto, el papel del codificador que superpone múltiples capas no es solo encontrar la similitud entre las imágenes con mayor precisión, sino extraer y combinar gradualmente la información en la secuencia de entrada para generar representaciones de características más precisas, mejorando así el rendimiento del modelo. En tareas de visión artificial, la secuencia de entrada puede ser una secuencia de valores de píxeles de una imagen o una secuencia de representaciones de características de una imagen, no solo la similitud entre imágenes.

Reflexiones sobre la aplicación del modelo multimodal

Dominar el transformador es la primera mitad Incluso si sabemos cómo convertir las imágenes de datos, voces y textos que tenemos ahora en los vectores de características del modelo,

Al poder obtener estos vectores de características, se debe decir que puede generar cualquier tarea de tipo etiqueta.Desde el principio de realización, la entropía está aguas abajo de la estructura del transformador, agregando una capa completamente conectada para lograr la salida. (Esta también es una forma de utilizar modelos preentrenados para realizar ajustes en modelos más grandes).
inserte la descripción de la imagen aquí

Implementos de pádel modelo vit

# ViT Online Class
# Author: Dr. Zhu
# Project: PaddleViT (https://github.com/BR-IDL/PaddleViT)
# 2021.11
import paddle
import paddle.nn as nn
import numpy as np
from PIL import Image

paddle.set_device('cpu')

class Identity(nn.Layer):
    def __init__(self):
        super().__init__()

    def forward(self, x):
        return x

class Mlp(nn.Layer):
    def __init__(self, embed_dim, mlp_ratio=4.0, dropout=0.):
        super().__init__()
        self.fc1 = nn.Linear(embed_dim, int(embed_dim * mlp_ratio))
        self.fc2 = nn.Linear(int(embed_dim * mlp_ratio), embed_dim)
        self.act = nn.GELU()
        self.dropout = nn.Dropout(dropout)

    def forward(self, x):
        x = self.fc1(x)
        x = self.act(x)
        x = self.dropout(x)
        x = self.fc2(x)
        return x

class PatchEmbedding(nn.Layer):
    def __init__(self, image_size, patch_size, in_channels, embed_dim, dropout=0.):
        super().__init__()
        self.patch_embedding = nn.Conv2D(in_channels, embed_dim, patch_size, patch_size)
        self.dropout = nn.Dropout(dropout)

    def forward(self, x):
        # [n, c, h, w]
        x = self.patch_embedding(x) # [n, c', h', w']
        x = x.flatten(2) # [n, c', h'*w']
        x = x.transpose([0, 2, 1]) # [n, h'*w', c']
        x = self.dropout(x)
        return x

class Attention(nn.Layer):
    # TODO: 补全时,删除pass
    def __init__(self, embed_dim, num_heads, qkv_bias=False, qk_scale=None, dropout=0., attention_dropout=0.):
        super().__init__()
        self.num_heads = num_heads 
        self.attn_head_size = int(embed_dim / self.num_heads)
        self.all_head_size = self.attn_head_size * self.num_heads
        self.qkv = nn.Linear(embed_dim, self.all_head_size*3)
        if qk_scale == None:
            self.scales = self.attn_head_size ** -0.5
        else:
            self.scales = qk_scale
        self.proj = nn.Linear(self.all_head_size, embed_dim)
        self.attn_dropout = nn.Dropout(attention_dropout)
        self.proj_dropout = nn.Dropout(dropout)
        self.softmax = nn.Softmax(axis=-1)

    def transpose_multihead(self, x):
        new_shape = x.shape[:-1] + [self.num_heads, self.attn_head_size]
        x = x.reshape(new_shape)
        x = x.transpose([0, 2, 1, 3])
        return x
    
    def forward(self, x):
        qkv = self.qkv(x).chunk(3, axis=-1)
        q, k, v = map(self.transpose_multihead, qkv)
        attn = paddle.matmul(q, k, transpose_y=True)
        attn = attn * self.scales
        attn = self.softmax(attn)
        attn_weights = attn
        attn = self.attn_dropout(attn)
        z = paddle.matmul(attn, v)
        z = z.transpose([0, 2, 1, 3])
        new_shape = z.shape[:-2] + [self.all_head_size]
        z = z.reshape(new_shape)
        z = self.proj(z)
        z = self.proj_dropout(z)
        return z, attn_weights

class EncoderLayer(nn.Layer):
    def __init__(self, embed_dim):
        super().__init__()
        self.attn_norm = nn.LayerNorm(embed_dim)
        self.attn = Attention()
        self.mlp_norm = nn.LayerNorm(embed_dim)
        self.mlp = Mlp(embed_dim)

    def forward(self, x):
        h = x 
        x = self.attn_norm(x)
        x = self.attn(x)
        x = x + h

        h = x
        x = self.mlp_norm(x)
        x = self.mlp(x)
        x = x + h
        return x

class ViT(nn.Layer):
    def __init__(self):
        super().__init__()
        self.patch_embed = PatchEmbedding(224, 7, 3, 16)
        layer_list = [EncoderLayer(16) for i in range(5)]
        self.encoders = nn.LayerList(layer_list)
        self.head = nn.Linear(16, 10)
        self.avgpool = nn.AdaptiveAvgPool1D(1)
        self.norm = nn.LayerNorm(16)

    def forward(self, x):
        x = self.patch_embed(x) # [n, h*w, c]: 4, 1024, 16
        for encoder in self.encoders:
            x = encoder(x)
        # avg
        x = self.norm(x)
        x = x.transpose([0, 2, 1])
        x = self.avgpool(x)
        x = x.flatten(1)
        x = self.head(x)
        return x

def main():
    t = paddle.randn([4, 16, 96])
    print('input shape = ', t.shape)

    model = Attention(embed_dim=96, num_heads=8, 
                      qkv_bias=False, qk_scale=None, dropout=0., attention_dropout=0.)
    print(model)

    out, attn_weights = model(t)
    print(out.shape)
    print(attn_weights.shape)

if __name__ == "__main__":
    main()

Supongo que te gusta

Origin blog.csdn.net/weixin_42010722/article/details/129444261
Recomendado
Clasificación