From e2f9aa1ba17133be125114387e6262cf551772d8 Mon Sep 17 00:00:00 2001 From: sunhanyu <458599247@qq.com> Date: Mon, 29 Apr 2024 10:59:02 +0800 Subject: [PATCH] chapter2.8_update --- Translated_Book/ch02/2.8词位置编码.ipynb | 183 +++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 Translated_Book/ch02/2.8词位置编码.ipynb diff --git a/Translated_Book/ch02/2.8词位置编码.ipynb b/Translated_Book/ch02/2.8词位置编码.ipynb new file mode 100644 index 0000000..69c21e9 --- /dev/null +++ b/Translated_Book/ch02/2.8词位置编码.ipynb @@ -0,0 +1,183 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 2.6 使用滑动窗口进行数据采样" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "在前面的章节中,我们将 token IDs 转换为连续的向量表示,也就是所谓的 token 编码,作为 LLM 的输入。然而,LLM 的一个缺点是自注意力机制(将在第 3 章详细介绍),不包含序列中的 token 位置或顺序信息。\n", + "\n", + "先前介绍的 embedding 层的生成方式中,相同的 token ID 总是被映射成相同的向量表示,不会在乎 token ID 在输入序列中的位置,如图 2.17 所示。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**图 2.17 编码层将 token ID 转换为相同的向量表示,不管其在输入序列中的位置如何。例如,token ID 5 ,无论是在 token ID 输入向量的第一还是第三个位置,都将产生相同的编码向量。**\n", + "\n", + "![](../img/fig-2-17.jpg)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "在原则上,具有确定性的、与位置无关的编码对于可重现性是有益的。然而,由于LLM的自注意力机制本身也不关注位置,因此将额外的位置信息注入到LLM中是有帮助的。\n", + "\n", + "为了实现这一点,有两种常用的位置编码方式:相对位置编码和绝对位置编码。\n", + "\n", + "绝对位置编码与序列中的特定位置相关联。对于输入序列中的每个位置,都会添加一个唯一的位置编码到 token 中,来表示其确切位置。例如,第一个 token 将具有特定的位置编码,第二个 token 将具有另一个不同的位置编码,依此类推,如图2.18所示。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**图2.18 位置编码被添加到 token 中,以创建 LLM 的输入。位置向量具有与原始 token 相同的维度。出于简化考虑,token 编码显示为值为1。**\n", + "\n", + "![](../img/fig-2-18.jpg)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "相对位置编码不是专注于 token 的绝对位置,而是侧重于 token 之间的相对位置或距离。这意味着模型学习的是 “彼此之间有多远” 而不是 “在哪个确切位置”的关系。这样做的好处是,即使模型在训练过程中没有看到这样的长度,它也可以更好地推广到不同长度的序列。\n", + "\n", + "两种类型的位置编码旨在增强 LLM 理解 token 顺序和关系的能力,确保更准确和更具上下文意识的预测。它们的选择通常取决于具体的应用程序和正在处理的数据的性质。\n", + "\n", + "OpenAI 的 GPT 模型使用绝对位置编码,在训练过程中进行了优化,而不是像原始 Transformer 模型中的位置编码那样固定或预定义。这个优化过程是模型训练本身的一部分,我们将在本书的后面部分实现。现在,让我们创建初始的位置编码,为即将到来的章节创建 LLM 输入。\n", + "\n", + "在本章中,我们之前专注于非常小的编码大小,以说明为目的。现在,我们考虑更现实和有用的编码大小,并将输入 token 编码为 256 维向量表示。这比原始的GPT-3 模型使用的要小(在 GPT-3 中,编码大小为 12,288 维),但对于实验来说仍然是合理的。此外,我们假设 token ID 是由我们之前实现的 BPE 标记器创建的,其词汇量大小为 50,257:\n", + "> output_dim = 256\n", + "\n", + "> vocab_size = 50257\n", + "\n", + "> token_embedding_layer = torch.nn.Embedding(vocab_size, output_dim)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "使用上面的 token_embedding_layer ,如果我们从 dataloader 中采样数据,我们将每个批次中的每个 token 编码成一个256维的向量中。如果我们的批次大小为8,每个批次有四个 token ,则结果将是一个8 x 4 x 256的张量。\n", + "\n", + "首先,让我们实例化第2.6节 “使用滑动窗口进行数据采样” 的 dataloader:\n", + ">max_length = 4\n", + "\n", + ">dataloader = create_dataloader_v1(\n", + "> raw_text, batch_size=8, max_length=max_length, stride=max_len)\n", + "\n", + ">data_iter = iter(dataloader)\n", + "\n", + ">inputs, targets = next(data_iter)\n", + "\n", + ">print(\"Token IDs:\\n\", inputs)\n", + "\n", + ">print(\"\\nInputs shape:\\n\", inputs.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "前面的代码打印如下输出:\n", + ">Token IDs:\n", + "\n", + ">tensor([[ 40, 367, 2885, 1464],\\\n", + " [ 1807, 3619, 402, 271],\\\n", + " [10899, 2138, 257, 7026],\\\n", + " [15632, 438, 2016, 257],\\\n", + " [ 922, 5891, 1576, 438],\\\n", + " [ 568, 340, 373, 645],\\\n", + " [ 1049, 5975, 284, 502],\\\n", + " [ 284, 3285, 326, 11]])\n", + " \n", + ">Inputs shape:\n", + " >torch.Size([8, 4])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "正如我们所看到的,token ID 张量是 8x4 维的,这意味着数据批次由 8 个文本样本组成,每个样本有 4 个 token。\n", + "\n", + "现在让我们使用 token_embedding_layer 将这些 token ID 嵌入为 256 维的向量:\n", + "> token_embeddings = token_embedding_layer(inputs)\n", + "> \n", + "> print(token_embeddings.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "前面的代码打印如下输出:\n", + "\n", + ">torch.Size([8, 4, 256])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "根据 8x4x256 维的张量输出,我们可以看出每个 token ID 现在被嵌入为一个 256 维的向量。\n", + "对于 GPT 模型的绝对嵌入方法,我们只需要创建另一个具有与 token_embedding_layer 相同维度的嵌入层:\n", + "\n", + ">context_length = max_length\n", + "\n", + ">pos_embedding_layer = torch.nn.Embedding(context_lengthe, output_dim)\n", + "\n", + ">pos_embeddings = pos_embedding_layer(torch.arange(context_length))\n", + "\n", + ">print(pos_embeddings.shape)\n", + "\n", + "如前面的代码示例所示,pos_embeddings 的输入通常是一个占位符向量 torch.arange(context_length),其中包含一系列数字 0、1、...,一直到最大输入长度减 1。context_length 是一个变量,表示 LLM 支持的输入大小。在这里,我们选择它与输入文本的最大长度类似。在实践中,输入文本可以比支持的上下文长度长。这种情况下,我们必须截断文本。\n", + "\n", + "print 语句的输出如下:\n", + "\n", + ">torch.Size([4, 256])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "正如我们所见,位置嵌入张量由四个 256 维向量组成。我们现在可以直接将它们添加到标记嵌入中,PyTorch 将在每个 8 批次中的每个 4x256 维标记嵌入张量中添加 4x256 维的 pos_embeddings 张量:\n", + ">input_embeddings = token_embeddings + pos_embeddings\n", + "\n", + ">print(input_embeddings.shape)\n", + "\n", + "print 输出如下:\n", + "\n", + ">torch.Size([8, 4, 256])\n", + "\n", + "我们创建的 input_embeddings,如图 2.19 所总结的,是嵌入的输入示例,现在可以由我们将在第 3 章开始实现的主要 LLM 模块进行处理。\n", + "\n", + "![](../img/fig-2-19.jpg)\n", + "**图 2.19 作为输入处理流程的一部分,输入文本首先被分解为单个 token 。然后使用词汇表将这些标记转换为 token ID。将 token ID 转换为编码向量,然后添加相似大小的位置编码,生成用作主要 LLM 层的输入编码。**\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}