自然语言处理与大型语言模型 (LLM)(例如 ChatGPT 和)的演变GPT-4 标志着一个重要的里程碑,这些模型在基于文本的任务中展示了接近人类的理解能力。除此之外,OpenAI 引入的大型多模态模型 (LMM) 代表了一个显着的转变,使这些模型能够处理图像和文本数据。本文将重点讨论法学硕士的核心文本解释技术——标记化和嵌入——及其在多模态环境中的适应,预示着人工智能的未来将超越文本,涵盖更广泛的感官输入。

将原始文本转换为 GPT-4 等大型语言模型可以理解的格式涉及一系列复杂且相互关联的步骤。每个过程(标记化、标记嵌入和变压器架构的使用)在这些模型如何理解和生成人类语言方面都发挥着关键作用。

标记化:理解文本的门户

处理法学硕士语言数据的第一步是标记化。这是将文本分割成更小的单元(称为标记)的过程。此步骤对于将复杂的语言结构分解为机器学习模型可以处理和理解的元素至关重要。

不同的代币化方法

代币化可以采取多种形式,每种形式都有其独特的优势和挑战。

字符级标记化是最简单的形式,其中文本被划分为单个字符。然而,其直接性会导致令牌序列较长,从而降低处理效率。另一方面是单词级标记化,它将文本拆分为单词。这种方法很直观,但在处理大量词汇时可能会遇到困难,并且在遇到新的或未知的单词时常常会犹豫不决。

在子字标记化中找到了一种更平衡的方法,例如字节对编码(BPE)。 BPE 从包含训练语料库中所有独特字符的基础词汇开始,确保每个单词都可以分解为这些基本单元。 BPE的核心在于其频率分析和对合并的方法。它迭代地扫描语料库以识别最常出现的字符或标记对。然后将这些对合并以形成新的令牌。此步骤至关重要,因为它使模型能够识别和巩固常见的配对,并在后续处理中将它们视为单个单元。该过程继续进行,每次迭代都会合并下一个最频繁的对。

随着每次迭代词汇的发展,新的标记(合并对)会被添加。重复该过程,直到词汇表达到预定义的大小或所需的粒度级别。最终的词汇量在足够详细以表示复杂单词和易于管理以有效处理之间取得了平衡。

在对新文本进行标记时,算法会采用这种精炼的词汇表。它首先搜索词汇表中最大可能的标记。如果没有找到匹配项,它会将文本分解为更小的单元,继续下去,直到找到合适的匹配项。该方法确保将常用单词和短语标记为更少、更大的标记,从而提高处理速度,同时将不太常见的短语进一步细分以提高准确性。

BPE 表示常用短语的效率、通过子词单元处理罕见和未知单词的能力以及其平衡方法使其对于处理词汇量大或词形复杂的语言特别有效。该方法体现了一种准备供法学硕士处理的数据的复杂方法,极大地促进了他们对人类语言的理解。

我将通过一个示例演示 BPE 的工作原理,并附上一些代码,以使这个概念更加具体。

让我们用“这是一个例子”这句话作为例子。最初,BPE 将句子分解为基本单元。它不是以整个单词,而是以字符或一小群字符开头。因此,“这是一个示例”首先会被标记为每个单独的字符,例如“T”、“h”、“i”、“s”等。

BPE 然后分析训练数据中字符对的频率并开始合并最常见的字符对。例如,如果“Th”、“is”、“an”、“ex”和“ample”是训练数据中的频繁对,BPE 会将它们合并为单个标记。这个过程被迭代地应用,导致句子由更少、更大的标记来表示,例如“Th”、“is”、“an”、“ex”和“ample”。

将句子从单个字符序列转换为更大、更有意义的单元,减少了表示文本所需的标记总数,在保持效率的同时又不失去意义。此外,BPE 的方法擅长处理新词或罕见词。对于训练期间未见过的单词(例如“exemplary”),BPE 可以将其分解为已知的子词或字符,例如“ex”、“am”、“pl”、“ar”和“y”。此功能使 BPE 在处理未知单词时特别有效,方法是使用现有的子词词汇来近似未知单词。

我还将向您展示 BPE 的简化表示在代码中的样子。

分段 1:从语料库初始化词汇

此部分从示例文本语料库中准备初始词汇。每个单词都被拆分为字符,并附加一个特殊的词尾标记 。此标记有助于区分以相同字符结尾但属于不同单词的单词。

Python

 


if 词汇中的单词:
词汇[单词] += 1
别的:
词汇[词] = 1″ data-lang=”text/x-python”>

corpus =“这是一个示例。这是另一个示例。”
词汇={}

# 预处理和初始化词汇
对于 corpus.split() 中的单词:
词 = ' '.join(列表(词)) + ' '
if 词汇中的单词:
词汇[单词] += 1
别的:
词汇[单词] = 1

<表格样式=“最大宽度:100%;宽度:自动;表格布局:固定;显示:表格;”宽度=“自动”>
<正文>

说明

  • 语料库字符串包含示例文本。
  • 词汇词典将保存初始词汇。
  • 循环将每个单词拆分为字符并添加单词结束标记。
  • 每个唯一的单词(现在是字符序列)都会以其频率添加到词汇表中。

第 2 部分:定义辅助函数

这些函数对于 BPE 操作至关重要。他们在训练数据中找到常见的对并将它们合并,正如我们在上面的示例中讨论的那样。

Python

 

导入重新、集合

def get_stats(词汇):
对 = collections.defaultdict(int)
对于单词,vocab.items() 中的频率:
符号 = word.split()
对于范围内的 i(len(符号)-1):
对[符号[i],符号[i+1]] += 频率
返回对

def merge_vocab(pair, v_in):
v_输出 = {}
二元组 = re.escape(' '.join(pair))
p = re.compile(r'(?

说明

  • get_stats:计算词汇表中每对相邻标记的频率。
  • merge_vocab:将最常见的词对合并为单个标记。它使用正则表达式来查找并合并词汇表中的这些对。

第 3 部分:对的迭代合并

该段执行 BPE 的核心:迭代合并词汇表中最常见的字符对。

Python

 

# 合并次数
合并数量 = 10


对于范围内的 i(num_merges):

对 = get_stats(词汇)

如果不是成对的:

休息

最佳 = 最大(对, key=pairs.get)

词汇 = merge_vocab(最佳, 词汇)


print("BPE 之后的词汇:")

打印(词汇)

说明

  • 循环运行指定的迭代次数 (num_merges)。
  • 在每次迭代中,它都会识别并合并最频繁的对。
  • 经过所有迭代后,更新后的词汇表反映了 BPE 的结果。

第 4 部分:对新文本进行标记

这最后一段演示了如何使用 BPE 词汇来标记新句子。

Python

 

打印(tokenized_sentence)” data-lang =“text / x-python”>

def bpe_tokenize(text, vocab):

代币 = []

对于 text.split() 中的单词:

词 = ' '.join(列表(词)) + ' '

当 len(word) > 1 时:

possible_tokens = [如果单词中的标记为词汇中的标记,则标记为]

如果不可能_tokens:

休息

最长的令牌 = 最大(可能的令牌, key=len)

tokens.append(longest_token)

word = word.replace(longest_token, '', 1)

返回令牌


new_sentence =“这个例子是不同的。”

tokenized_sentence = bpe_tokenize(new_sentence, vocab)

print("\n标记化句子:")

打印(tokenized_sentence)

说明

  • bpe_tokenize 函数使用 BPE 词汇表对新句子进行标记。
  • 它将句子拆分为单词,然后将每个单词拆分为字符,从 BPE 词汇表中搜索匹配的最长标记。
  • 该函数输出新句子的标记形式。

这些代码段共同演示了从语料库创建 BPE 词汇表及其在标记新文本中的应用。

令牌化不仅仅是一个初步步骤;它为更深入的语言理解奠定了基础。通过将文本转换为标记,我们为嵌入的后续阶段准备数据,真正的语义处理从这里开始。

意义转变:令牌嵌入的意义

一旦标记化,文本的下一步就是标记嵌入,这是一个根据上下文捕获单词语义的过程。该过程包括初始化嵌入、训练模型以调整这些嵌入,以及确保语义相似的标记在嵌入空间中接近。

嵌入初始化

模型词汇表中的每个标记(单词或子词)都与一个嵌入相关联,嵌入是一个高维向量。这些嵌入通常是随机初始化的。这种随机性为训练过程提供了调整和细化这些向量的起点。

情境调整培训

在训练期间,模型会接触大量文本数据。它学习根据每个标记出现的上下文来调整嵌入。这个学习过程涉及反向传播和优化算法(如随机梯度下降或 Adam)来迭代调整嵌入以最小化模型的预测误差。

语义关系

该模型旨在调整嵌入,以便在相似上下文中使用的标记在向量空间中具有彼此接近的嵌入。这种接近度通常使用余弦相似度来衡量。此过程创建一个语义图,其中具有相似含义或用法的单词在高维空间中彼此靠近。

Python 代码示例

我将通过一个简化的示例逐步介绍初始化令牌嵌入并模拟基本训练过程以调整这些嵌入的过程。

Python

 

将 numpy 作为 np 导入
随机导入

# 嵌入的词汇和随机初始化
vocab = [“猫”、“狗”、“动物”、“宠物”、“猫科动物”、“犬科动物”]
embedding_dim = 300 # 典型尺寸范围从 128 到 4096
嵌入 = {word: np.random.randn(embedding_dim) for 词汇中的单词}

# 模拟训练调整的函数
def adjustment_embeddings(嵌入、word_pairs、learning_rate=0.01):
对于 word_pairs 中的 word1、word2:
如果 word1 位于嵌入中,word2 位于嵌入中:
# 简单调整:将相关词的嵌入移得更近
embedding_diff = 嵌入[word1] - 嵌入[word2]
嵌入[word1] -= 学习率 * 嵌入_diff
嵌入[word2] += 学习率 * 嵌入_diff

# 模拟训练数据(上下文相关的单词对)
related_word_pairs = [(“猫”,“猫科动物”),(“狗”,“犬科动物”),(“猫”,“宠物”),(“狗”,“宠物”)]

# 模拟训练
for _ in range(1000): # 迭代次数
random.shuffle(相关词对)
调整嵌入(嵌入,相关词对)

# 检查调整后的嵌入
print(“调整‘猫’和‘狗’的嵌入:”)
print("Cat:", embeddings["cat"][:5]) # 显示前 5 个维度
print("狗:", 嵌入["狗"][:5])

代码说明

  • 嵌入初始化:代码定义词汇表并随机初始化每个单词的嵌入,为简单起见,将嵌入维度设置为 300。
  • 训练模拟:使用 adjust_embeddings 函数,代码通过调整相关单词对(例如“cat”和“feline”)的嵌入来模拟训练") 在向量空间中更接近。这是通过迭代地减少每对嵌入之间的距离来实现的,模仿 LLM 如何根据上下文优化令牌嵌入。
  • 结果:经过多次迭代,上下文相关单词的嵌入被调整为在嵌入空间中彼此更接近,代表了法学硕士上下文学习的基本形式。

推进语境解释:Transformer 架构的力量

令牌嵌入为大型语言模型 (LLM) 提供了对语言上下文和含义的深入理解。 Transformer 在此基础上并行处理这些嵌入,使用自注意力机制来辨别复杂的单词关系。这种协同作用使法学硕士能够通过对语言语义和结构的细致理解来解释和生成文本。

变压器架构

Transformers 采用分层架构设计,每一层都有助于处理输入数据。每层的核心组件是自注意力机制和前馈神经网络网络。 Transformer 与 RNN 和 LSTM 等早期模型的区别在于它们能够同时处理输入序列中的所有标记。这种并行处理方法不仅提高了计算效率,而且使模型能够更有效地捕获数据中复杂的依赖关系和关系。

自我注意力机制

每个 Transformer 层的核心是自注意力机制。该机制计算输入序列中每个标记的所谓注意力分数。这些分数衡量模型在处理特定标记时应分配给序列中其他标记的程度。

自注意力机制允许 Transformer 根据整个序列本身动态调整序列中每个 token 的影响力。这对于理解上下文至关重要,因为它使模型能够解释每个标记,而不是孤立地,而是与其他标记相关。

此外,变形金刚采用了所谓的多头注意力机制。这意味着自注意力过程在每一层内并行复制多次。每个复制或​​“头”可能会关注令牌关系的不同方面,例如句法或语义连接。通过这样做,模型可以捕获对文本更丰富、更细致的理解。

位置编码

Transformers 设计中的一个独特挑战是它们缺乏固有的序列处理能力——这是 RNN 等序列模型固有的特征。为了解决这个问题,Transformers 使用位置编码。这些被添加到标记嵌入中,以便为模型提供有关序列中每个标记位置的信息。

位置编码通常使用正弦函数生成。此方法可确保序列中的每个位置接收唯一的编码,从而允许模型根据令牌在序列中的顺序来区分令牌。该位置信息对于模型理解语言的流程和结构至关重要。

逐层处理

在 Transformer 模型中,每一层都会处理输入序列,逐步转换和细化每个标记的表示。这种转换是由自注意力机制提供的上下文以及层内前馈网络的后续操作通知的。

当输入数据通过 Transformer 的连续层时,标记的表示形式变得越来越细化并丰富了上下文信息。这种逐层处理可以实现对语言的复杂理解和生成,使模型能够以卓越的效率和效果处理复杂的语言任务。

代码示例和说明

下面是一个简化的 Python 代码示例,用于说明 Transformer 自注意力机制的基本版本。

Python

 

将 numpy 作为 np 导入
导入数学

def Softmax(x):
返回 np.exp(x) / np.sum(np.exp(x), axis=0)

def scaled_dot_product_attention(Q, K, V):
# 计算 Q 和 K 的点积,按 K 维度的平方根缩放
matmul_qk = np.dot(Q, K.T) / math.sqrt(K.shape[1])

# 应用softmax来获取注意力权重
注意权重 = softmax(matmul_qk)

# 乘以V得到输出
输出 = np.dot(attention_weights, V)
返回输出,attention_weights

# 令牌嵌入示例(随机初始化)
token_embeddings = np.random.rand(3, 64) # 3 个 token,64 维嵌入

# 模拟查询 (Q)、键 (K) 和值 (V) 矩阵
Q = token_embeddings
K = token_embeddings
V = token_embeddings

# 应用自注意力
注意输出,注意权重=scaled_dot_product_attention(Q,K,V)

print("注意力输出:", Attention_output)
print("注意力权重:",attention_weights)