1 puntos por GN⁺ 2023-07-25 | 1 comentarios | Compartir por WhatsApp
  • El attention softmax dentro de Transformer puede dificultar la cuantización y el despliegue con poca memoria porque no permite que un head elija “no hacer nada”
  • La pista del problema son los weights/activations atípicos que aparecen en los LLM; un paper de Qualcomm AI Research analiza que más del 97% de las activations atípicas provienen de posiciones de espacios en blanco y puntuación
  • El softmax existente asigna un peso de 1/k a cada término incluso si todas las entradas son muy negativas, pero softmax_1 suma 1 al denominador para permitir que la salida de attention pueda acercarse a 0
  • softmax_1 mantiene las proporciones relativas mientras limita la suma entre 0 y 1, y gracias a su derivada positiva también conserva un gradient distinto de cero
  • Este cambio no es un parche que pueda pegarse directamente a los modelos existentes: requiere reentrenamiento, aunque en modelos como LLaMA podrían hacerse experimentos rápidos con un esquema de zero prefix token

Valores atípicos que dificultan la cuantización

  • En los modelos Transformer aparecen weights y activations varias órdenes de magnitud más grandes que otros valores, y parece que esos valores son importantes para el funcionamiento del modelo
  • Estos valores atípicos degradan el rendimiento en la cuantización entera común de scale-and-bias, lo que dificulta ejecutar modelos grandes en entornos con RAM limitada como una Mac Mini o una Raspberry Pi
  • Si se reduce el uso de RAM, tanto en la nube como en el edge habría más margen para manejar modelos más grandes o más funcionalidades
  • Quantizable Transformers: Removing Outliers by Helping Attention Heads Do Nothing de Qualcomm AI Research vincula los valores atípicos con el softmax del mecanismo de attention
    • Analiza que más del 97% de las activations atípicas en los LLM ocurren en posiciones de whitespace y punctuation
    • El clipped softmax tiene el problema de zero gradient, y gated attention agrega millones de parámetros nuevos

El papel de softmax en Transformer

  • El embedding de entrada de Transformer es un vector de punto flotante que representa una palabra
    • LLaMA 2 de Meta usa vectores de embedding de longitud 3,204, y en half-precision se necesitan más de 6 KB para representar una sola palabra
    • El vocabulary normalmente tiene entre 30,000 y 50,000 elementos
  • Transformer convierte el vector de entrada en un vector de salida del mismo tamaño, y el vector de salida final se usa para predecir el token que vendrá después del token actual
  • La residual connection funciona de modo que attention suma información de contexto a la información original de la palabra
    • Por ejemplo, agrega contexto para distinguir si pupil significa estudiante o la pupila del ojo
  • En el paso final, el vector de salida se transforma en un vector del tamaño del vocabulary y luego se le aplica softmax para tratarlo como probabilidades del siguiente token
    • En las implementaciones reales, en vez de confiar literalmente en las probabilidades de salida de softmax, se usa un sampling mechanism
    • El softmax de la etapa de salida se considera una opción razonable porque sirve para dar gradient a todo el vocabulary

Limitaciones del softmax de attention interno

  • La ecuación central del attention interno es la siguiente

[ \textrm{Attention}(Q, K, V) = \textrm{softmax}\left(\frac{QK^T}{\sqrt{d}}\right)V ]

  • En un decoder-only model, (Q), (K) y (V) parten de la misma secuencia de entrada, pero se proyectan de maneras distintas
  • (QK^T) encuentra correlaciones entre los vectores de embedding de los tokens, y se aplica softmax a cada fila para usarlo como peso al mezclar los value vectors de la matriz (V)
  • Multi-head attention realiza este proceso en paralelo con varios heads por capa
    • Divide el vector de embedding en varios segmentos, y cada head agrega información a un segmento del vector de salida
  • El problema es que softmax obliga a cada attention head a producir alguna anotación
    • Aunque el head no tenga información que agregar, softmax igual fuerza una elección
    • Cuanto más especializado sea el head, más probable es que necesite una opción de “pasar”, pero el softmax actual no tiene abstención

Propuesta: softmax_1 y QuietAttention

  • El cambio propuesto es sumar 1 al denominador de softmax

[ (\textrm{softmax}_1(x))_i = \frac{\exp(x_i)}{1+\sum_j \exp(x_j)} ]

  • El softmax existente hace que cada término converja a (1/k) incluso si todos los valores de (x) se vuelven muy negativos

[ \lim_{x_1 \to -\infty} \ldots \lim_{x_k \to -\infty} (\textrm{softmax}(x))_i = \frac{1}{k} \gt 0 ]

  • softmax_1 hace que, bajo la misma condición, cada término converja a 0

[ \lim_{x_1 \to -\infty} \ldots \lim_{x_k \to -\infty} (\textrm{softmax}_1(x))_i = 0 ]

  • Gracias a esta diferencia, el attention head puede elegir no agregar información
  • La ecuación de attention propuesta es la siguiente

[ \textrm{QuietAttention}(Q, K, V) := \textrm{softmax}_1 \left(\frac{QK^T}{\sqrt{d}}\right)V ]

Propiedades de softmax_1 y condiciones experimentales

  • softmax_1 reduce un poco la magnitud total, pero como después de attention hay normalización, esa reducción puede compensarse
  • Las proporciones relativas del vector de salida son las mismas que con el softmax existente

[ \frac{(\textrm{softmax}_1(x))_i}{(\textrm{softmax}_1(x))_j} = \frac{(\textrm{softmax}(x))_i}{(\textrm{softmax}(x))_j} = \frac{\exp(x_i)}{\exp(x_j)} \quad \forall \ i, j ]

  • La derivada es positiva, así que mantiene un gradient no nulo, y la suma queda entre 0 y 1, por lo que la salida no se sale del rango de control
  • Este problema se trata no como uno de numerical precision sino como un problema matemático, y no se resuelve solo con precision extra
  • La idea experimental consiste en anteponer un zero vector a todo el contexto de entrada y garantizar, incluyendo positional encoding, que no se agregue bias
    • Si el cero pasa intacto, produce el efecto de sumar 1 a cada denominador de softmax posterior
    • Podría ser posible en modelos LLaMA que usan fixed embedding y special prefix token
  • No es un experimento que pueda aplicarse directamente a modelos existentes, sino que requiere reentrenamiento del modelo
  • Los valores que se quiere observar son los cambios en weight kurtosis y activation infinity norm

1 comentarios

 
GN⁺ 2023-07-25
Comentarios de Hacker News
  • Lo que propone el autor no es agregar algo al softmax de la salida final, sino sumar 1 al denominador del softmax interno de la atención
    El softmax de la atención hace que el emparejamiento clave/consulta se vea como probabilidades, para que la consulta clave-valor use pesos continuos en lugar de una búsqueda binaria 0/1
    Si se suma 1 al denominador, la suma de los pesos queda por debajo de 1, así que ya no sería un verdadero vector de probabilidad, pero si el modelo aprende pesos altos funciona casi como uno, y también puede elegir “no estar seguro de nada” dando pesos bajos a todo
    Si realmente es bueno, solo se sabrá entrenando un LLM de esta manera. Aun así, no parece que vaya a haber una gran diferencia. Los nodos de atención con baja confianza ya pueden producir puntajes previos al softmax parecidos entre sí y crear una distribución casi uniforme; entonces el resultado sería el promedio de varios vectores y estadísticamente tendría muchas probabilidades de acercarse a 0
    Además, en un Transformer ya hay muchos pesos entrenables que pueden implementar un opt-out, como la matriz V y la capa feedforward posterior a la atención. Aun así, me gusta el tono no académico del texto y la actitud de tantear una idea fundamental; no me convenció del todo, pero me gustaría leer más textos así

    • Según entiendo, el autor sugiere que con este cambio desaparecen los valores grandes, y que la salida del Transformer puede codificarse con menos bits, reduciendo los requisitos de memoria de la red
      Como la memoria es el cuello de botella al ejecutar modelos grandes, si esto fuera cierto tendría bastante importancia
    • Me gusta más el modelo conceptual que propone el autor
      Como cuando dice que originalmente quería llamar a esta función ghostmax, se puede pensar que x tiene un elemento adicional con valor 0 y, como exp(0)=1, también habría en la matriz V un vector 0 que debilita el resultado
      En vez de decir “la suma de los pesos es menor que 1, así que a veces no elige nada”, me parece mejor verlo como que, cada vez que se considera un conjunto de opciones, también se obliga a considerar la opción de no hacer nada
      Es la diferencia entre “si solo tienes un martillo, todo parece un clavo” y “aunque solo tengas un martillo, golpeas los clavos e ignoras lo que no lo es”
      Por ejemplo, en un sistema de voz a texto, si primero la persona indica el idioma y luego se le da audio en ese idioma, puede producir una transcripción bastante buena, pero es incómodo que si en el paso 1 se elige mal el idioma termine diciendo tonterías. Si fuera un transcriptor de inglés, sería más parecido a cómo actúa una persona si primero dijera “esto no es inglés” cuando recibe audio en francés
    • Para verificar si sirve, basta con entrenar dos modelos idénticos en un dataset grande
      Uno con +1 en el denominador del softmax del módulo de atención y otro sin eso. Habría que mostrar que el rendimiento es similar y que en el modelo con +1 hay menos explosiones, por lo que se puede cuantizar de manera más efectiva
    • Me cuesta estar de acuerdo con la idea de que “si la confianza es baja, basta con hacer parecidos los puntajes previos al softmax”
      Así como las redes neuronales no modelan bien la función identidad y por eso necesitan conexiones residuales, creo que también son bastante débiles para aprender implícitamente transformaciones de baja entropía
      Incluso si no aumenta la expresividad, podría tener el efecto de incorporar en el modelo una transformación tipo buscar una aguja en un pajar, difícil de alcanzar mediante descenso por gradiente. No sé qué tan útil sea en la práctica
    • Esta técnica ya se conocía desde hace años y PyTorch incluso la incluye
      Si no se usa mucho, probablemente sea porque la gente ya la probó y en la práctica no funcionó tan bien. Llamarlo un “bug pasado por alto durante más de 8 años”, como hace el texto original, suena más a clickbait
  • Puede que se me esté escapando algo, pero no entiendo por qué los comentarios lo tratan como si fuera algo tan importante. Este truco realmente ya lo vi varias veces
    Por ejemplo, incluso hay código así en un repositorio viejo de Google: https://github.com/google/flaxformer/blob/ee62754ebe5a5eeb11...

    • Sí. Nosotros también lo usamos hace unos años en nuestros modelos anteriores. No recuerdo exactamente los detalles, pero no me parece que haya tenido mucho efecto
      No creo que ayude en nada con la estabilidad. Al escalar el tamaño, para la estabilidad del softmax sirven más trucos como Q/K layernorm: https://arxiv.org/pdf/2302.05442.pdf
    • Si los modelos populares todavía siguen cometiendo este error, entonces sigue siendo algo digno de atención
      Es totalmente válido escribir una entrada de blog o un paper para aumentar la conciencia sobre ello. También es común que buenas ideas se descubran de forma independiente varias veces
    • La clave es si la gente lo ha probado en cuantización, es decir, con enfoques int8 / GGML / GPTQ
      Si el denominador más grande aplana la distribución y eso lleva a un mejor comportamiento de cuantización, solo se sabrá comparando directamente el caso con +1 y el caso sin +1. El texto original piensa que este beneficio podría ser grande
    • La argumentación me parece un poco dudosa
      Técnicamente, el softmax no se implementa exactamente con la fórmula presentada, sino como exp(x_i-max(x)), y luego esos valores se suman en el denominador. Puede que se me esté escapando algo
      Además, las conexiones residuales se usan porque la red no puede aprender la función identidad, pero 0 sí puede aprenderse. Entonces, en f(x): x+g(x), bastaría con que g:x ~> 0, es decir, que sea casi 0
      f(x): x+g(x) también facilita más el flujo del gradiente
  • Este truco “descubierto” forma parte de la implementación estándar de atención multi-cabeza de PyTorch, y su nombre es add_zero_attention
    Agrega un 0 a los logits, así que como e^0=1, aparece un 1 en el denominador: https://pytorch.org/docs/stable/generated/torch.nn.Multihead...

    • La documentación es bastante mala. Solo dice algo como “si se especifica, agrega un nuevo lote de ceros a las secuencias key y value en dim=1”
      No explica el significado ni de manera muy breve. Con solo agregar la segunda oración que acabo de escribir, sería mucho más útil
    • Es una opción cuyo valor por defecto es false. Entonces, ¿eso quiere decir que la gente ya lo probó y normalmente no ayuda?
    • Buen hallazgo. Ojalá lo vea el autor del texto original
    • https://en.wikipedia.org/wiki/Multiple_discovery
  • No es sobre IA ni sobre este algoritmo, pero a veces hay errores pequeños que, por más que los señales, no logras convencer a nadie de que son errores
    En 2011 revisé el código fuente porque quería copiar el algoritmo de ranking de reddit en mi proyecto, y estaba haciendo algo totalmente absurdo para publicaciones con suma de votos negativa
    Me pareció que en una fórmula simple habían intercambiado un término y aplicado mal el signo positivo/negativo. Así que lo escribí en mi blog y lo publiqué en reddit, pero mucha gente, incluidos empleados de reddit, dijo que yo estaba completamente equivocado y que el algoritmo funcionaba como se había previsto
    También dijeron que antes ya había habido personas que notaron lo mismo y lo señalaron, pero a todas les dijeron que estaban equivocadas
    Al final edité la entrada del blog a: “personas más inteligentes que yo dijeron que no había errores en el algoritmo de reddit, solo que mi variante me parecía más lógica”
    Pero 3 años después, en 2014, en el código fuente de reddit hicieron commit exactamente de la corrección que yo, y otros antes que yo, habíamos propuesto todo ese tiempo: https://github.com/reddit-archive/reddit/commit/50d35de04b92...
    El código abierto permite que muchos ojos encuentren bugs, pero a veces, aunque encuentres el bug, no logras convencer a nadie. Claro, reddit cerró el código en 2017
    Al final no terminé poniendo en mi app ni la función de ranking que quería copiar originalmente ni el sistema de votos

    • Me pasó algo parecido alrededor de 2008 cuando, como pasante en Yahoo, hice una herramienta interna para generar OAuth 1.0 URL
      Había que codificar muchos valores en los parámetros de consulta, y cierto parámetro en realidad tenía que quedar codificado dos veces, así que mi herramienta también lo hacía así. Pero el ingeniero que implementaba insistía en que mi herramienta estaba mal, sacó a relucir que yo era pasante y hasta recurrió a la especificación de OAuth para forzar una interpretación según la cual su implementación era correcta y yo la estaba leyendo mal
      Al final tuvieron que llamar a Eran Hammer-Lahav para confirmarlo, y solo entonces se concluyó que yo tenía razón; recién ahí ese ingeniero admitió, como si nada, que obviamente esa era la forma correcta. No hubo ningún reconocimiento ni disculpa por varios días de ataques personales
      Aprendí una lección importante: tener más seniority no significa siempre tener la razón. Ahora normalmente yo soy la parte más senior, pero trato de recordarlo todos los días
    • Trabajo en una FAANG, y me sorprendió muchísimo descubrir con qué frecuencia pasa esto
      Solo con ser “la persona que va poniendo logs por todo el codebase y razonando paso a paso” ya puedes construir una carrera larga y de mucho impacto. Incluso a un nivel muy básico, muchas veces vi correcciones sorprendentes para problemas viejos
      Pero también viene con mucha diversión política. La primera reacción de la gente es negar, y después empeora. Solo una o dos personas lo ven y dicen “ah, entonces solo hay que arreglarlo”, mientras que alguien manda un correo, copiando hasta al jefe del jefe del jefe, elegantemente envuelto en que “faltan consideraciones sobre concurrencia / gestión de memoria / etc.”
      En esos casos, conviene esperar en silencio y no confrontar ni quejarse. Si no pasa nada, liderazgo ni pregunta, y los colegas empiezan a irse, es mejor empezar a planear el cambio a otro equipo
    • Acabo de ver el código y simplemente está clarísimo que está mal. Debe haber sido realmente frustrante
    • Pensando en los últimos meses, no me sorprende que las interacciones con empleados de reddit hayan ido por ese camino
  • Hay una discusión interesante sobre características atípicas y cuantización: https://timdettmers.com/2022/08/17/llm-int8-and-emergent-fea...
    Los valores atípicos se usan para podar valores, y los Transformer parecen pasar por una “transición de fase” en la forma de manejar características atípicas cerca de los 6.7 mil millones de parámetros. Esto podría complicar los estudios de ablación
    Parece que habría mucho de qué hablar con Tim Dettmers

  • El autor señala un problema real y propone una solución simple. Pasa por completo mi criterio para detectar a un excéntrico
    Sobre “¿por qué nadie pensó en esto?”, suena plausible la explicación de que el autor estaba muy familiarizado con la función softmax por trabajos fuera del machine learning, y que quienes investigaban este problema, aunque lo hubieran acotado a “algo relacionado con softmax”, quizá no entendían softmax en sí con suficiente profundidad
    Dicho eso, si el autor original llega a ver este comentario, estaría bien que desarrollara más la afirmación de que “resolvería el bucle de retroalimentación de outliers con una probabilidad del 99.44%”. Ahora mismo, esa frase es la única explicación de cómo podrían relacionarse los outliers con softmax

    • Resulta que alguien sí lo había pensado antes. En concreto, Google, y esta idea ya estaba en flaxformer al menos desde noviembre de 2021
      https://github.com/google/flaxformer/blame/ee62754ebe5a5eeb1...
      El comentario dice: “Función softmax con un logit virtual adicional igual a 0. Esto es por compatibilidad con algunos modelos entrenados previamente. Equivale a sumar 1 al denominador. En el contexto de attention, permite no mirar nada”
      Produce exactamente la misma softmax modificada que este post. El tiempo dirá por qué fue ignorada públicamente. Quizá no tuvo mucho efecto, quizá simplemente quedó enterrada, o quizá Google no la impulsó
    • Falta la verificación más importante: los resultados
      En realidad no lo probó; solo pensó que funcionaría. Una modificación tan simple a softmax no debería tardar mucho en validarse, así que no haberlo intentado antes de publicar es bastante penoso
    • La explicación de “¿por qué nadie lo pensó? Porque el autor conocía softmax a fondo desde fuera del machine learning” me parece dudosa
      Softmax se entiende muy bien dentro de la comunidad de machine learning. Es un truco muy común y estas propiedades también son bien conocidas. Parece poco probable que nadie lo hubiera pensado
      Aun así, puede que la convención actual de softmax se haya elegido por accidente y que el autor sí haya señalado correctamente sus desventajas
    • También podría ser porque el efecto del problema es sutil
      Incluso si el diagnóstico es correcto, un LLM de precisión completa puede evitar el problema asignando pesos de attention grandes a tokens sin sentido para producir una salida de attention inofensiva
      Puede que este problema solo importe al cuantizar pesos, y el objetivo del desarrollo de los LLM de punta hoy no sea necesariamente el rendimiento en cuantización
    • Leí el “99.44% de confianza” como una broma sobre las probabilidades mal calibradas de softmax
      Algo como que softmax da muy bien 99.9% de confianza o 0.1% de confianza, pero no tanto los valores intermedios
  • Sé que en HN está de moda quejarse de la academia, pero esta entrada de blog no presenta un buen argumento
    La idea central podría haberse transmitido en una cuarta parte del texto, quizá incluso en menos de una octava parte, pero está envuelta en expresiones informales y quejas apenas disimuladas sobre la publicación académica
    El resultado es que la discusión aquí no trata sobre los resultados o la idea del texto, sino que se convierte en 200 comentarios sobre publicación académica vs blog, escritura formal vs escritura informal
    Puede ser un buen estilo si quieres poner una entrada de blog en la portada de HN. Pero si quieres que la gente examine y discuta las ventajas y desventajas de la idea, no tanto

    • En el fondo, esa es precisamente la razón por la que terminamos en una economía de la atención
      La gente tiene una cantidad limitada de atención para dedicar a todo, pero la capacidad y la necesidad de recibir atención son ilimitadas. Eso es lo que decía Michael Goldhaber
      Esa es la semilla de la explosión de información. Cosas como 6 mil millones de videos de cómo hervir un huevo, o 200 comentarios tipo cobertizo de bicicletas
      Para frenarlo, sitios como Google, Facebook o HN ordenan comentarios, enlaces y feeds de noticias, pero como la mayoría del conjunto que clasifican es puro ruido, solo terminan creando otra capa de ruido
      Aún no hemos diseñado sistemas de información que reflejen lo que Goldhaber decía sobre la atención hace 30 o 40 años
    • Se burlan de que “llegue a la portada de HN”, pero si lo reformulas como “discutir algo observado de manera informal”, ese desprecio pierde fuerza
      El objetivo también puede ser informar y entretener al mismo tiempo. A mucha gente le gustan las discusiones relajadas alrededor del punto central, y el autor puede preferir eso al tono clínico y formal de un paper académico
    • Por cierto, alguien señaló que la API de Multihead Attention de PyTorch tiene una vía de escape opcional para este problema
      Aun así, y de manera algo irritante, para verlo hay que saltarse 200 comentarios de quejas fuera de tema
  • Hice un experimento parecido y en mi configuración no ayudó
    No afirmo que no hubiera algún bug, pero parece que atender a la posición actual resuelve este problema hasta cierto punto. Cuando no hay nada que decir, simplemente emite el valor de la posición actual
    Más exactamente, en vez de sumar 1 al denominador de softmax, añadí antes de QK un attention sink como parámetro aprendido, y después de softmax lo eliminé para que al multiplicar por V la suma no diera 1
    También probé una variante que mira la posición actual y otra que no, y una variante donde el sink se genera por posición con una red feedforward en lugar de usar un parámetro aprendido. En mi configuración ninguna hizo gran diferencia, pero había muchos otros elementos extraños mezclados, así que quizá valga la pena intentarlo de nuevo

    • Cuando dices que no ayudó, me da curiosidad qué mediste
      En el contexto de este post, tanto el rendimiento en la tarea como la cantidad y magnitud de los pesos outlier parecen importantes
    • Él lo está promocionando como una forma de arreglar outliers muy notorios. ¿Tu variante siquiera tenía esos outliers desde el inicio?
  • No se ven resultados. Si hubiera habido números que complementaran la teoría, sería mucho más sólido y convincente
    No es tan difícil tomar un modelo de lenguaje existente y hacerle fine-tuning con un conjunto pequeño de datos para comprobar si funciona
    Aun así, comparto la idea de que podría haber una mejor formulación de attention. El paper de 2020 https://arxiv.org/abs/2005.09561 me ayudó bastante en uno de los modelos Transformer que entrené. No era un modelo de lenguaje general, sino un problema de grafos multimodal especializado
    Ese paper propone attention normalizada y, si no me equivoco, también podría ayudar con problemas de cuantización

  • Este enfoque se usaba con frecuencia antes de que los tokens dummy se volvieran algo común. Yo vi esta idea por primera vez en el paper de XLNet
    Según entiendo, ya estaba en PyTorch desde 2019/2020, y probablemente alguien pueda encontrar referencias incluso anteriores
    Me sorprendió el tono exagerado del post original. Más aún si se trata de algo que la mayoría de los investigadores de Transformers entiende. También me sorprende que en las respuestas haya tanta postura de “así es como debe hacerse la investigación”. Esto se parece más a un ejemplo de por qué la investigación no funciona así, y la revisión por pares es buena en muchos sentidos; uno de ellos es que reduce este tipo de momentos vergonzosos

    • Él no es arrogante. A la gente le gusta un tono informal, directo y autocrítico, y eso es lo opuesto a la arrogancia
      Parece que están leyendo una autocrítica ambigua como si fuera una afirmación literal
      Resumiendo por qué le pareció importante compartirlo: este es un problema bastante de nicho, relevante solo cuando intentas correr una imitación apenas convincente de ChatGPT en hardware limitado. Así que es totalmente posible que los grandes equipos de investigación no lo consideraran importante. Ellos no están intentando correr un LLM en una 3090
    • Me parece extraña la crítica de que “es arrogante”
      El texto tiene un tono coloquial, autocrítico y humorístico. No sé si eso sea bueno o malo, pero pude seguir perfectamente todo el razonamiento. Está muy lejos de ser arrogante
      Decir que “reduce este tipo de momentos vergonzosos” implica que sería vergonzoso estar equivocado o no ser el primero en descubrirlo. ¿Eso no sería lo arrogante?