{
  "source_file": "0930",
  "source_platform": "个人博客",
  "author": "Jay Alammar",
  "title_listed": "Interfaces for Explaining Transformer Language Models",
  "keywords": "Transformer,可解释性,界面",
  "domain": "大模型算法",
  "content_type": "图解教程",
  "is_paid_flag": "否",
  "url": "https://jalammar.github.io/explaining-transformers/",
  "publish_date": "2021-05",
  "corpus_stage": "预训练/SFT",
  "notes": "Transformer语言模型解释界面",
  "id": "653ce72f77e6",
  "collected_at": "2026-10-02T14:24:55",
  "title": "Interfaces for Explaining Transformer Language Models – Jay Alammar – Visualizing machine learning one concept at a time.",
  "body_markdown": "Interfaces for Explaining Transformer Language Models\nInterfaces for exploring transformer language models by looking at input saliency and neuron activation.\nExplorable #1:\nInput saliency of a list of countries generated by a language model\nTap or hover over\nthe\noutput tokens\n:\nExplorable #2:\nNeuron activation analysis reveals four groups of neurons, each is associated with generating a certain type of token\nTap or hover over\nthe sparklines on the left to isolate a certain factor:\nThe Transformer architecture\nhas been powering a number of the recent advances in NLP. A breakdown of this architecture is provided\nhere\n. Pre-trained language models based on the architecture,\n    in both its auto-regressive\n(models that use their own output as input to next time-steps and that process tokens from left-to-right, like GPT2)\n    and denoising\n(models trained by corrupting/masking the input and that process tokens bidirectionally, like BERT)\n    variants continue to push the envelope in various tasks in NLP and, more recently, in computer vision\n. Our understanding of why these models work so well, however, still lags behind these developments.\nThis exposition series continues the pursuit to interpret\nand visualize\nthe inner-workings of transformer-based language models.\n\nWe illustrate how some key interpretability methods apply to transformer-based language models. This article focuses on auto-regressive models, but these methods are applicable to other architectures and tasks as well.\nThis is the first article in the series. In it, we present explorables and visualizations aiding the intuition of:\nInput Saliency\nmethods that score input tokens importance to generating a token.\nNeuron Activations\nand how individual and groups of model neurons spike in response to\n        inputs and to produce outputs.\nThe next article addresses\nHidden State Evolution\nacross the layers of the model and what it may tell us about each layer's role.\nIn the language of Interpretable Machine Learning (IML) literature like Molnar et al.\n, input saliency is a method that explains individual predictions. The latter two methods fall under the\n    umbrella of \"analyzing components of more complex models\", and are better described as increasing the transparency\nof transformer models.\nMoreover, this article is accompanied by\nreproducible notebooks\nand\nEcco - an open source library\nto create similar\n    interactive interfaces directly in Jupyter notebooks\nfor GPT-based\nmodels from the HuggingFace transformers library\n.\nIf we're to impose the three components we're examining to explore the architecture of the transformer, it would look like the following figure.\nFigure: Three methods to gain a little more insight into the inner-workings of Transformer language models.\nBy introducing tools that visualize input saliency, the evolution of hidden states, and neuron activations, we aim to enable researchers to build more intuition about Transformer language models.\nInput Saliency\nWhen a computer vision model classifies a picture as containing a husky, saliency maps can tell us whether the classification was made due to the visual properties of the animal itself, or because of the snow in the background\n. This is a method of\nattribution\nexplaining the relationship between a model's output and inputs -- helping us detect errors and biases, and better understand the behavior of the system.\nFigure: Input saliency map attributing a model's prediction to input pixels.\nMultiple methods exist for assigning importance scores to the inputs of an NLP model\n. The literature is most often concerned with this application for classification tasks, rather than natural\n    language generation. This article focuses on language generation. Our first interface calculates feature importance after each token is generated, and by\n    hovering or tapping on an output token, imposes a saliency map on the tokens responsible for generating it.\nThe first example for this interface asks GPT2-XL\nfor William Shakespeare's date of birth. The model is correctly able to produce the date (1564, but broken into two tokens: \" 15\" and \"64\", because the model's vocabulary does not include \" 1564\" as a single token). The interface shows the importance of each input token when generating each output token:\nExplorable: Input saliency of Shakespeare's birth\n            year using Gradient × Input.\nTap or hover over\nthe output tokens.\nGPT2-XL is able to tell the birth date of William Shakespeare expressed in two tokens. In generating the\n        first token, 53% of the importance is assigned to the name (20% to the first name, 33% to the last name).\n        The next most important two tokens are \" year\" (22%) and \" born\" (14%). In generating the second token to\n        complete the date, the name still is the most important with 60% importance, followed by the first portion\n        of the date -- a model output, but an input to the second time step.\nThis prompt aims to probe world knowledge. It was generated using greedy decoding. Smaller variants of GPT2\n        were not able to output the correct date.\nOur second example attempts to both probe a model's world knowledge, as well as to see if the model\n    repeats the patterns in the text (simple patterns like the periods after numbers and like new lines, and\n    slightly more involved patterns like completing a numbered list). The model used here is DistilGPT2\n.\nThis explorable shows a more detailed view that displays the attribution percentage for each token -- in case you need that precision.\nExplorable: Input saliency of a list of EU countries\nTap or hover over\nthe output tokens.\nThis was generated by DistilGPT2 and attribution via Gradients X Inputs. Output sequence is cherry-picked to\n        only include European countries and uses sampled (non-greedy) decoding. Some model runs would include China,\n        Mexico, and other countries in the list. With the exception of the repeated \" Finland\", the model continues\n        the list alphabetically.\nAnother example that we use illustratively in the rest of this article is one where we ask the model to complete\n    a simple pattern:\nExplorable: Input saliency of a simple\n            alternating pattern of commas and the number one.\nTap or hover over\nthe output tokens.\nEvery generated token ascribes the first token in the input the highest feature importance score. Then\n        throughout the sequence, the preceding token, and the first three tokens in the sequence are often the most\n        important. This uses Gradient × Inputs on GPT2-XL.\nThis prompt aims to probe the model's response to syntax and token patterns. Later in the article, we build\n        on it by switching to counting instead of repeating the digit ' 1'. Completion gained using greedy decoding.\n        DistilGPT2 is able to complete it correctly as well.\nIt is also possible to use the interface to analyze the responses of a transformer-based conversational agent.\n    In the following example, we pose an existential question to DiabloGPT\n:\nExplorable: Input saliency of DiabloGPT's answer to the ultimate question\nTap or hover over\nthe output tokens.\nThis was the model's first response to the prompt. The question mark is attributed the highest score in the\n        beginning of the output sequence. Generating the tokens \" will\" and \" ever\" assigns noticeably more importance to\n        the word \" ultimate\".\n        This uses Gradient × Inputs on DiabloGPT-large.\nAbout Gradient-Based Saliency\nDemonstrated above is scoring feature importance based on Gradients X Inputs\n-- a gradient-based saliency method shown by Atanasova et al.\nto perform well across various datasets for text classification in transformer models.\nTo illustrate how that works, let's\n    first recall how the model generates the output token in each time step. In the following figure, we see how\n①\nthe\n    language model's final hidden state is projected into the model's vocabulary resulting in a numeric score for\n    each\n    token in the model's vocabulary. Passing that scores vector through a softmax operation results in a probability\n    score for each token.\n②\nWe proceed to select a token\n    (e.g. select the highest-probability scoring token, or sample from the top scoring tokens) based\n    on\n    that vector.\nFigure: Gradient-based input saliency\n③\nBy calculating the gradient of the\n    selected logit (before the softmax) with respect to the inputs by back-propagating it all the way back to the\n    input tokens, we get a signal of how important each token was in the calculation resulting in this generated\n    token.\n    That assumption is based on the idea that the smallest change in the input token with the highest\n    feature-importance\n    value makes a large change in what the resulting output of the model would be.\nFigure: Gradient X input calculation and aggregation\nThe resulting gradient vector per token is then multiplied by the input embedding of the respective token. Taking\n    the L2 norm of the resulting vector results in the token's feature importance score. We then normalize the\n    scores by dividing by the sum of these scores.\nMore formally,\ngradient\n×\ninput\nis described as follows:\n∥\n∇\nX\ni\nf\nc\n(\nX\n1\n:\nn\n)\nX\ni\n∥\n2\n\\lVert \\nabla _{X_i} f_c (X_{1:n})  X_i\\lVert_2\n∥\n∇\nX\ni\n​\n​\nf\nc\n​\n(\nX\n1\n:\nn\n​\n)\nX\ni\n​\n∥\n2\n​\nWhere\nis the embedding vector of the input token at timestep\ni\n, and\nis the back-propagated gradient of the score of the selected token unpacked as follows:\nis the list of input token embedding vectors in the input sequence (of length\n)\nis the score of the selected token after a forward pass through the model (selected through any one of a number of methods including greedy/argmax decoding, sampling, or beam search).\n        With the\nc\nstanding for \"class\" given this is often described in the classification context. We're keeping the notation even though in our case, \"token\" is more fitting.\nThis formalization is the one stated by Bastings et al.\nexcept the gradient and input vectors are multiplied element-wise. The resulting vector is then aggregated into a score via calculating the\nL2 norm\nas this was empirically shown in Atanasova et al.\nto perform better than other methods (like averaging).\nNeuron Activations\nThe Feed Forward Neural Network (FFNN) sublayer is one of the two major components inside a transformer block (in\n    addition to self-attention). It accounts for 66% of the parameters of a transformer block and thus provides a\n    significant portion of the model's representational capacity. Previous work\nhas examined neuron firings inside deep neural networks in both the NLP and computer vision domains. In this\n    section we apply that examination to transformer-based language models.\nContinue Counting: 1, 2, 3, ___\nTo guide our neuron examination, let's present our model with the input \"1, 2, 3\" in hopes it would echo the\n    comma/number alteration, yet also keep incrementing the numbers.\nIt succeeds.\nBy using the methods we'll discuss in Article #2 (following the lead of\nnostalgebraist\n), we can produce a graphic that exposes the probabilities of output tokens after each layer in the model. This looks at the hidden state after each layer, and displays the ranking of the ultimately produced output token in that layer.\nFor example, in the first step, the model produced the token \" 4\". The first column tells us about that process. The bottom most cell in that column shows that the token \" 4\" was ranked #1 in probability after the last layer. Meaning that the last layer (and thus the model) gave it the highest probability score. The cells above indicate the ranking of the token \" 4\" after each layer.\nBy looking at the hidden states, we observe that the model gathers confidence\n    about the two patterns of the\n    output sequence (the commas, and the ascending numbers) at different layers.\nThe model is able to successfully complete the list. Examining the hidden states shows that the earlier\n        layers of\n        the model are more comfortable predicting the commas as that's a simpler pattern. It is still able to\n        increment\n        the digits, but it needs at least one more layer to start to be sure about those outputs.\nWhat happens at Layer 4 which makes the model elevate the digits (4, 5, 6) to the top of the probability\n    distribution?\nWe can plot the activations of the neurons in layer 4 to get a sense of neuron activity. That is what the first of the following three figures shows.\nIt is difficult, however, to gain any interpretation from looking at activations during one forward pass through the model.\nThe figures below show neuron activations while five tokens are generated (' 4 , 5 , 6'). To get around the\n    sparsity of the firings, we may wish to cluster the firings, which is what the subsequent figure shows.\nActivations of 200 neurons (out of 3072) in Layer 4's FFNN resulting in the model outputting the\n                    token ' 4'\nEach row is a neuron. Only neurons with positive activation are colored. The darker they are, the more\n                intense the firing.\nNeuron firings in the FFNN sublayer of Layer 4\nEach row corresponds to a neuron in the feedforward neural network of layer #4. Each column is\n                    that neuron's status when a token was generated (namely, the token at the top of the\n                    figure).\nA view of the first 400 neurons shows how sparse the activations usually are (out of the 3072\n                    neurons in the FFNN layer in DistilGPT2).\nClustering Neurons by Activation Values\nTo locate the signal, the neurons are clustered (using kmeans on the activation values) to reveal the firing pattern. We notice:\nThe largest cluster or two tend to be sparse like the\norange cluster\n.\nNeurons in the\ngreen cluster\nfire the\n                            most when generating a number.\nNeurons in the\nred cluster\n, however,\n                            fire the most when generating the commas.\nThe\npurple cluster\ntracks the digits,\n                            but with less intensity and larger number of\n                            neurons.\nNeurons in the\npink cluster\nare focused\n                            on the numbers and rarely fire when generating\n                            the\n                            commas. Their activations\n                            get higher and higher the more the token value is incremented.\nIf visualized and examined properly, neuron firings can reveal the complementary and compositional roles that can be played by individual neurons, and groups of neurons\n.\nEven after clustering, looking directly at activations is a crude and noisy affair. As presented in\n    Olah et al.\n,\n    we are better off reducing the dimensionality using a matrix decomposition method. We follow the authors'\n    suggestion to use Non-negative Matrix Factorization (NMF) as a natural candidate for reducing the dimensionality\n    into groups that are potentially individually more interpretable. Our first experiments were with Principal Component Analysis (PCA), but NMF\n    is a better approach because it's difficult to interpret the negative values in a PCA component of neuron\n    firings.\nFactor Analysis\nBy first capturing the activations of the neurons in FFNN layers of the model, and then decomposing them into a\n    more manageable number of factors (using\n) using NMF, we are able to shed light on how various neurons contributed towards each generated token.\nThe simplest approach is to break down the activations into two factors. In our next interface, we have the model\n    generate thirty tokens, decompose the activations into two factors, and highlight each token with the factor\n    with the highest activation when that token was generated:\nExplorable: Two Activation Factors of a Counting Sequence\nTap or hover over\nthe sparklines on the left to isolate a certain\n        factor\nFactor #1\ncontains the collection of neurons\n        that\n        light up to produce a number. It is a linear transformation of 5,449 neurons (30% of the 18,432 neurons in\n        the FFNN layers: 3072 per layer, 6 layers in DistilGPT2).\nFactor #2\ncontains the collection of neurons\n        that light up to produce a comma. It is a linear transformation of 8,542 neurons (46% of the FFNN neurons).\nThe two factors have 4,365 neurons in common.\nNote\n: The association between the color and the token is different in the case of the input tokens and\n        output tokens. For the input tokens, this is how the neurons fired\nin response\nto the token as an\n        input. For the output tokens, this is the activation value\nwhich produced\nthe token. This is why the\n        last input token and the first output token share the same activation value.\nThis interface is capable of compressing a lot of data that showcase the excitement levels of factors composed of\n    groups of neurons. The sparklines\non the left give a snapshot of the excitement level of each factor across the entire sequence. Interacting with\n    the sparklines (by hovering with a mouse or tapping on touchscreens) displays the activation of the factor on\n    the tokens in the sequence on the right.\nWe can see that decomposing activations into two factors resulted in factors that correspond with the alternating\n    patterns we're analyzing (commas, and incremented numbers). We can increase the resolution of the factor\n    analysis by increasing the number of factors. The following figure decomposes the same activations into five\n    factors.\nExplorable: Five Activation Factors of a Counting Sequence\nTap or hover over\nthe sparklines on the left to isolate a certain\n        factor\nDecomposition into five factors shows the counting factor being broken down into three factors, each\n                addressing a distinct portion of the sequence (\nstart\n,\nmiddle\n,\nend\n).\nThe\nyellow factor\nreliably tracks\n                generating the commas in the sequence.\nThe\nblue factor\nis common across\n                various GPT2 factors -- it is of neurons that intently focus on the first token in the sequence, and\n                only on that token.\nWe can start extending this to input sequences with more content, like the list of EU countries:\nExplorable: Six Activation Factors of a list of EU countries\nTap or hover over\nthe sparklines on the left to isolate a certain\n        factor\nAnother example, of how DistilGPT2 reacts to XML, shows a clear distinction of factors attending to different\n    components of the syntax. This time we are breaking down the activations into ten components:\nExplorable: Ten Activation Factors of XML\nTap or hover over\nthe sparklines on the left to isolate a certain\n        factor\nFactorizing neuron activations in response to XML (that was generated by an RNN from\n) into ten\n        factors\n        results in factors corresponding to:\nNew-lines\nLabels of tags\n, with higher activation on\n                closing tags\nIndentation spaces\nThe\n'<' (less-than) character\nstarting XML tags\nThe large factor focusing on the\nfirst token\n. Common to GPT2 models.\nTwo factors tracking the\n'>'\n(greater than)\ncharacter at the end of XML\n                tags\nThe\ntext inside XML tags\nThe\n'</'\nsymbols indicating\n                closing XML tag\nFactorizing Activations of a Single Layer\nThis interface is a good companion for hidden state examinations which can highlight a specific layer of\n    interest, and using this interface we can focus our analysis on that layer of interest. It is straight-forward\n    to apply this method to specific layers of interest. Hidden-state evolution diagrams, for example,\n    indicate that layer #0 does a lot of heavy lifting as it often tends to shortlist the tokens that make it to the\n    top of the probability distribution. The following figure showcases ten factors applied to the activations\n    of layer 0 in response to a passage by Fyodor Dostoyevsky:\nExplorable: Ten Factors From The Underground\nTap or hover over\nthe sparklines on the left to isolate a certain\n        factor\nTen Factors from the activations the neurons in Layer 0 in response to a passage from Notes from Underground\n        by Dostoevsky.\nFactors that focus on specific portions of the text (\nbeginning\n,\nmiddle\n, and\nend\n. This is interesting as the only signal\n                the model gets about how these tokens are connected are the positional encodings. This indicates the\n                neurons that are keeping track of the order of words. Further examination is required to assess\n                whether these FFNN neurons directly respond to the time signal, or if they are responding to a\n                specific trigger in the self-attention layer's transformation of the hidden state.\nFactors corresponding to linguistic features, for example, we can see factors for\npronouns\n(he, him),\nauxiliary verbs\n(would, will),\nother verbs\n(introduce, prove -- notice the\n                understandable misfiring at the 'suffer' token which is a partial token of 'sufferings', a noun),\nlinking verbs\n(is, are, were), and a factor\n                that favors\nnouns and their adjectives\n(\"fatal rubbish\", \"vulgar folly\").\nA factor corresponding to\ncommas\n, a\n                syntactic feature.\nThe\nfirst-token\nfactor\nWe can crank up the resolution by increasing the number of factors. Increasing this to eighteen factors\n    starts to\n    reveal factors that light up in response to adverbs, and other factors that light up in response to partial\n    tokens. Increase the number of factors more and you'll start to identify factors that light up in response\n    to\n    specific words (\"nothing\" and \"man\" seem especially provocative to the layer).\nAbout Activation Factor Analysis\nThe explorables above show the factors resulting from decomposing the matrix holding the activations values of FFNN neurons using Non-negative Matrix Factorization. The following figure sheds light on how that is done:\nFigure: Decomposition of activations matrix using NMF.\nNMF reveals patterns of neuron activations inside one or a collection of layers.\nBeyond dimensionality reduction, Non-negative Matrix Factorization can reveal underlying common behaviour of groups of neurons. It can be used to analyze the entire network, a single layer, or groups of layers.\nConclusion\nThis concludes the first article in the series. Be sure to click on\nthe\nnotebooks\nand play with\nEcco\n! I would love your feedback on this article, series, and on Ecco in\nthis thread\n. If you find interesting factors or neurons, feel free to post them there as well. I welcome all feedback!\nAcknowledgements\nThis article was vastly improved thanks to feedback on earlier drafts provided by\n    Abdullah Almaatouq,\n    Ahmad Alwosheel,\n    Anfal Alatawi,\n    Christopher Olah,\n    Fahd Alhazmi,\n    Hadeel Al-Negheimish,\n    Isabelle Augenstein,\n    Jasmijn Bastings,\n    Najla Alariefy,\n    Najwa Alghamdi,\n    Pepa Atanasova, and\n    Sebastian Gehrmann.\nReferences\nCitation\nIf you found this work helpful for your research, please cite it as following:\nAlammar, J. (2020). Interfaces for Explaining Transformer Language Models  \n[Blog post]. Retrieved from https://jalammar.github.io/explaining-transformers/\nBibTex:\n@misc{alammar2020explaining, \n  title={Interfaces for Explaining Transformer Language Models},\n  author={Alammar, J},\n  year={2020},\n  url={https://jalammar.github.io/explaining-transformers/}\n}\nWritten on December 17, 2020",
  "metadata": {
    "title": "Interfaces for Explaining Transformer Language Models – Jay Alammar – Visualizing machine learning one concept at a time.",
    "description": "Interfaces for exploring transformer language models by looking at input saliency and neuron activation.\n\n\n\n\n\n    \n        Explorable #1:  Input saliency of a list of countries generated by a language model\n         Tap or hover over the output tokens:\n    \n    \n    \n    \n    \n        Explorable #2:  Neuron activation analysis reveals four groups of neurons, each is associated with generating a certain type of token\n        Tap or hover over the sparklines on the left to isolate a certain factor:\n    \n    \n    \n\n    \n\n\n\n\nThe Transformer architecture\n    has been powering a number of the recent advances in NLP. A breakdown of this architecture is provided here . Pre-trained language models based on the architecture,\n    in both its auto-regressive (models that use their own output as input to next time-steps and that process tokens from left-to-right, like GPT2)\n    and denoising (models trained by corrupting/masking the input and that process tokens bidirectionally, like BERT)\n    variants continue to push the envelope in various tasks in NLP and, more recently, in computer vision. Our understanding of why these models work so well, however, still lags behind these developments.\n\n\nThis exposition series continues the pursuit to interpret\n    and visualize\n    the inner-workings of transformer-based language models.\n\nWe illustrate how some key interpretability methods apply to transformer-based language models. This article focuses on auto-regressive models, but these methods are applicable to other architectures and tasks as well.\n     \n\n\nThis is the first article in the series. In it, we present explorables and visualizations aiding the intuition of:\n\n    \n        Input Saliency methods that score input tokens importance to generating a token.\n    \n    \n        Neuron Activations and how individual and groups of model neurons spike in response to\n        inputs and to produce outputs.\n    \n\n\nThe next article addresses Hidden State Evolution across the layers of the model and what it may tell us about each layer's role.",
    "keywords": null,
    "author": "Jay Alammar",
    "og:description": "Interfaces for exploring transformer language models by looking at input saliency and neuron activation.\n\n\n\n\n\n    \n        Explorable #1:  Input saliency of a list of countries generated by a language model\n         Tap or hover over the output tokens:\n    \n    \n    \n    \n    \n        Explorable #2:  Neuron activation analysis reveals four groups of neurons, each is associated with generating a certain type of token\n        Tap or hover over the sparklines on the left to isolate a certain factor:\n    \n    \n    \n\n    \n\n\n\n\nThe Transformer architecture\n    has been powering a number of the recent advances in NLP. A breakdown of this architecture is provided here . Pre-trained language models based on the architecture,\n    in both its auto-regressive (models that use their own output as input to next time-steps and that process tokens from left-to-right, like GPT2)\n    and denoising (models trained by corrupting/masking the input and that process tokens bidirectionally, like BERT)\n    variants continue to push the envelope in various tasks in NLP and, more recently, in computer vision. Our understanding of why these models work so well, however, still lags behind these developments.\n\n\nThis exposition series continues the pursuit to interpret\n    and visualize\n    the inner-workings of transformer-based language models.\n\nWe illustrate how some key interpretability methods apply to transformer-based language models. This article focuses on auto-regressive models, but these methods are applicable to other architectures and tasks as well.\n     \n\n\nThis is the first article in the series. In it, we present explorables and visualizations aiding the intuition of:\n\n    \n        Input Saliency methods that score input tokens importance to generating a token.\n    \n    \n        Neuron Activations and how individual and groups of model neurons spike in response to\n        inputs and to produce outputs.\n    \n\n\nThe next article addresses Hidden State Evolution across the layers of the model and what it may tell us about each layer's role.",
    "og:title": "Interfaces for Explaining Transformer Language Models"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/653ce72f77e6/code/body-000.txt",
      "chars": 156,
      "language": "text"
    },
    {
      "file": "attachments/653ce72f77e6/code/body-001.txt",
      "chars": 195,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://jalammar.github.io/images/explaining/transformer-input-saliency-hidden-states-neuron-activations.png",
      "bytes": 117263,
      "reused": false,
      "local_path": "attachments/653ce72f77e6/images/body-ef1a30763b975bc0d56f.png",
      "src": "https://jalammar.github.io/images/explaining/transformer-input-saliency-hidden-states-neuron-activations.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://jalammar.github.io/images/explaining/dog-saliency-map.jpg",
      "bytes": 29121,
      "reused": false,
      "local_path": "attachments/653ce72f77e6/images/body-ad036afa0d9acc50641b.jpg",
      "src": "https://jalammar.github.io/images/explaining/dog-saliency-map.jpg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://jalammar.github.io/images/explaining/colab-badge.svg",
      "bytes": 2369,
      "reused": false,
      "local_path": "attachments/653ce72f77e6/images/body-dcc12c5aed7f6af360e9.svg",
      "src": "https://jalammar.github.io/images/explaining/colab-badge.svg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://jalammar.github.io/images/explaining/111.PNG",
      "bytes": 231057,
      "reused": false,
      "local_path": "attachments/653ce72f77e6/images/body-e9ef8f6ce05393f10075.png",
      "src": "https://jalammar.github.io/images/explaining/111.PNG",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://jalammar.github.io/images/explaining/gradXinput.PNG",
      "bytes": 205696,
      "reused": false,
      "local_path": "attachments/653ce72f77e6/images/body-c72ee7fdb24bb1f5aa41.png",
      "src": "https://jalammar.github.io/images/explaining/gradXinput.PNG",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://jalammar.github.io/images/explaining/ranking_123.png",
      "bytes": 20625,
      "reused": false,
      "local_path": "attachments/653ce72f77e6/images/body-e09490c939a3c6b9432c.png",
      "src": "https://jalammar.github.io/images/explaining/ranking_123.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://jalammar.github.io/images/explaining/activations-4.PNG",
      "bytes": 12474,
      "reused": false,
      "local_path": "attachments/653ce72f77e6/images/body-a461daa874ba863b22d6.png",
      "src": "https://jalammar.github.io/images/explaining/activations-4.PNG",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://jalammar.github.io/images/explaining/activations_1.PNG",
      "bytes": 177983,
      "reused": false,
      "local_path": "attachments/653ce72f77e6/images/body-df43083f79a9c403a13d.png",
      "src": "https://jalammar.github.io/images/explaining/activations_1.PNG",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://jalammar.github.io/images/explaining/activations_2.PNG",
      "bytes": 206550,
      "reused": false,
      "local_path": "attachments/653ce72f77e6/images/body-68c5b6fc04950187da89.png",
      "src": "https://jalammar.github.io/images/explaining/activations_2.PNG",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://jalammar.github.io/images/explaining/neuron-factors-decomposition.PNG",
      "bytes": 177219,
      "reused": false,
      "local_path": "attachments/653ce72f77e6/images/body-4c1c5b89efbb67b9da37.png",
      "src": "https://jalammar.github.io/images/explaining/neuron-factors-decomposition.PNG",
      "alt": "",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [],
  "links": [
    {
      "href": "https://jalammar.github.io/illustrated-transformer/",
      "label": "here",
      "type": "a"
    },
    {
      "href": "https://github.com/jalammar/ecco/tree/main/notebooks",
      "label": "reproducible notebooks",
      "type": "a"
    },
    {
      "href": "https://github.com/jalammar/ecco/",
      "label": "Ecco - an open source library",
      "type": "a"
    },
    {
      "href": "https://colab.research.google.com/github/jalammar/ecco/blob/main/notebooks/Ecco_Input_Saliency.ipynb",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://www.lesswrong.com/posts/AcKRB8wDpdaN6v6ru/interpreting-gpt-the-logit-lens",
      "label": "nostalgebraist",
      "type": "a"
    },
    {
      "href": "https://colab.research.google.com/github/jalammar/ecco/blob/main/notebooks/Ecco_Neuron_Factors.ipynb",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://github.com/jalammar/ecco",
      "label": "Ecco",
      "type": "a"
    },
    {
      "href": "https://github.com/jalammar/ecco/discussions/9",
      "label": "this thread",
      "type": "a"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:52:32Z",
  "source_url": "https://jalammar.github.io/explaining-transformers/",
  "papers": [],
  "actual_video_files": [],
  "body_chars": 23455,
  "expected_body_images": 10,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/653ce72f77e6/pages/source.html",
  "local_html": "attachments/653ce72f77e6/pages/article.html",
  "body_base_path": "attachments/653ce72f77e6/pages/",
  "body_markdown_path": "attachments/653ce72f77e6/pages/article.md"
}