BPE算法

基本概念 Byte-Pair Encoding (BPE) 是一种常用于自然语言处理(NLP)的分词算法。BPE最初是一种数据压缩算法,由Philip Gage在1994年提出。在NLP中,BPE被用来将文本分割成子词(subword)单元,这样可以在处理未见过的单词时更有效。 工作原理 BPE的核心思想是通过多次迭代,将最常见的字符对(或子词对)合并成一个新的符号,直到词汇表达到预定的大小。具体步骤如下: 初始化词汇表:将所有单个字符作为初始词汇表。 统计频率:统计所有相邻字符对的出现频率。 合并字符对:找到出现频率最高的字符对,并将其合并成一个新的符号。 更新词汇表:将新的符号加入词汇表,并更新文本中的所有相应字符对。 重复步骤2-4:直到词汇表达到预定大小。 例子 假设我们有一个简单的文本:“banana banana”. 初始词汇表为:{b, a, n, }. 具体步骤如下: 初始化:词汇表为 {b, a, n, }。 统计频率:统计相邻字符对的频率,如 “ba” 出现2次,“an” 出现2次,“na” 出现2次。 合并字符对:选择频率最高的字符对 “an”,将其合并成一个新符号 “an”。更新后的文本为 “b an an a b an an a”。 更新词汇表:词汇表更新为 {b, a, n, an}。 重复步骤2-4:继续统计频率并合并,直到词汇表达到预定大小。 Byte-Level BPE 在处理多语言文本时,BPE的一个问题是字符集可能会非常大。为了解决这个问题,可以使用Byte-Level BPE。Byte-Level BPE将每个字节视为一个字符,这样基础字符集的大小固定为256(即所有可能的字节值)。 优缺点 优点: 处理未见过的单词:通过将单词分割成子词,可以更好地处理未见过的单词 词汇表大小可控:可以通过设置预定大小来控制词汇表的大小 缺点: 语义信息丢失:在某些情况下,分割后的子词可能会丢失部分语义信息 计算复杂度:多次迭代合并字符对的过程可能会增加计算复杂度

August 17, 2024 · 60 words · Kurong

😺 Is All You Need——Transformer补充

关于本文动机 Transformer主要内容请见 Lecture 9: Transformer | KurongBlog (kurongtohsaka.github.io),对 Transformer 已经进行比较详细的介绍和讲解了,但还是有一些细节问题不好在该篇文章提及,所以单开一篇讨论。 Q,K,V 的理解 假设我们想让所有的词都与第一个词 $v_1$ 相似,我们可以让 $v_1$ 作为查询。 然后,将该查询与句子中所有词进行点积,这里的词就是键。 所以查询和键的组合给了我们权重,接着再将这些权重与作为值的所有单词相乘。 通过下面的公式可以理解这个过程,并理解查询、键、值分别代表什么意思: $$ softmax(QK)=W \\ WV=Y $$ 一种比较感性的理解:想要得到某个 $V$ 对应的某个可能的相似信息需要先 $Q$ 这个 $V$ 的 $K$ ,$QK$ 得到注意力分数,之后经过 softmax 平滑后得到概率 $W $,然后 $WV$ 后得到最终的相似信息 $Y$ 。 Attention 机制 在数据库中,如果我们想通过查询 $q$ 和键 $k_i$ 检索某个值 $v_i$ 。注意力与这种数据库取值技术类似,但是以概率的方式进行的。 $$ attention(q,k,v)=\sum_isimilarity(q,k_i)v_i $$ 注意力机制测量查询 $q$ 和每个键值 $k_i$ 之间的相似性。 返回每个键值的权重代表这种相似性。 最后,返回所有值的加权组合作为输出。 Mask 掩码 在机器翻译或文本生成任务中,我们经常需要预测下一个单词出现的概率,这类任务我们一次只能看到一个单词。此时注意力只能放在下一个词上,不能放在第二个词或后面的词上。简而言之,注意力不能有非平凡的超对角线分量。 我们可以通过添加掩码矩阵来修正注意力,以消除神经网络对未来的了解。 Multi-head Attention 多头注意力机制 “小美长得很漂亮而且人还很好” 。这里“人”这个词,在语法上与“小美”和“好”这些词存在某种意义或关联。这句话中“人”这个词需要理解为“人品”,说的是小美的人品很好。仅仅使用一个注意力机制可能无法正确识别这三个词之间的关联,这种情况下,使用多个注意力可以更好地表示与“人”相关的词。这减少了注意力寻找所有重要词的负担,增加找到更多相关词的机会。...

August 14, 2024 · 840 words · Kurong

Encoder-Decoder 架构

原理 Encoder-Decoder架构通常由两个主要部分组成:编码器(Encoder)和解码器(Decoder)。 编码器(Encoder):编码器的任务是将输入序列(如一句话)转换为一个固定长度的上下文向量(context vector)。这个过程通常通过递归神经网络(RNN)、长短期记忆网络(LSTM)或门控循环单元(GRU)来实现。编码器逐步读取输入序列的每个元素,并将其信息压缩到上下文向量中。 解码器(Decoder):解码器接收编码器生成的上下文向量,并将其转换为输出序列。解码器同样可以使用RNN、LSTM或GRU。解码器在生成每个输出元素时,会考虑上下文向量以及之前生成的输出元素。 作用 Encoder-Decoder架构主要用于处理需要将一个序列转换为另一个序列的任务,例如: 机器翻译:将一种语言的句子翻译成另一种语言。 文本摘要:将长文本压缩成简短摘要。 对话系统:生成对用户输入的响应。 近年来,基于Transformer的Encoder-Decoder架构(如BERT、GPT、T5等)因其更好的性能和并行计算能力,逐渐取代了传统的RNN架构。 优缺点 优点: 灵活性:可以处理不同长度的输入和输出序列。 强大的表示能力:能够捕捉输入序列中的复杂模式和关系。 缺点: 长距离依赖问题:传统RNN在处理长序列时可能会遗忘早期的信息。 计算复杂度高:训练和推理过程需要大量计算资源。

August 11, 2024 · 18 words · Kurong

残差连接

原理 残差连接(Residual Connection)最早由何凯明等人在2015年提出的 ResNet 中引入。ResNet 通过引入残差块,使得网络可以扩展到更深的层数,并在 ImageNet 比赛中取得了显著的成功。 残差连接的核心思想是引入跳跃连接,将输入信号直接传递到网络的后续层,从而构建了一条捷径路径。这种结构允许网络学习输入和输出之间的残差,而不是直接学习输出。 残差连接可以表示为: $$ y=F(x)+x $$ 其中,$x$ 表示输入,$F(x)$ 表示经过非线性变换后的输出。 作用 解决梯度消失和梯度爆炸问题 提高训练效率 增强模型的泛化性能 例子 下图是 Transformer 论文中的模型结构图。 可以看到在每一个 Attention Layer 中都有一个 Add ,原输入和 Multi-head 变换后的输出做了一个简单的相加操作,而这就是所谓的残差连接。

August 11, 2024 · 32 words · Kurong

RNN速成(二)

LSTM 长短期记忆(Long short-term memory, LSTM)是一种特殊的 RNN,主要是为了解决长序列训练过程中的梯度消失和梯度爆炸问题。简单来说,就是相比普通的 RNN,LSTM 能够在更长的序列中有更好的表现。 门结构中的激活函数 门结构中包含着 sigmoid 激活函数。sigmoid 激活函数与 tanh 函数类似,不同之处在于 sigmoid 是把值压缩到 0~1 之间而不是 -1~1 之间。这样的设置有助于更新或忘记信息,因为任何数乘以 0 都得 0,这部分信息就会剔除掉。同样的,任何数乘以 1 都得到它本身,这部分信息就会完美地保存下来。这样网络就能了解哪些数据是需要遗忘,哪些数据是需要保存。这也代表着门结构最后计算得到的是一个概率。 遗忘门 遗忘门的功能是决定应丢弃或保留哪些信息。来自前一个隐藏状态的信息和当前输入的信息同时传递到 sigmoid 函数中去,输出值介于 0 和 1 之间,越接近 0 意味着越应该丢弃,越接近 1 意味着越应该保留。 输入门 输入门用于更新细胞状态。首先将前一层隐藏状态的信息和当前输入的信息传递到 sigmoid 函数中去。将值调整到 0~1 之间来决定要更新哪些信息。0 表示不重要,1 表示重要。 细胞状态 下一步,就是计算细胞状态。首先前一层的细胞状态与遗忘向量逐点相乘。如果它乘以接近 0 的值,意味着在新的细胞状态中,这些信息是需要丢弃掉的。然后再将该值与输入门的输出值逐点相加,将神经网络发现的新信息更新到细胞状态中去。至此,就得到了更新后的细胞状态。 输出门 输出门用来确定下一个隐藏状态的值,隐藏状态包含了先前输入的信息。首先,我们将前一个隐藏状态和当前输入传递到 sigmoid 函数中,然后将新得到的细胞状态传递给 tanh 函数。 最后将 tanh 的输出与 sigmoid 的输出相乘,以确定隐藏状态应携带的信息。再将隐藏状态作为当前细胞的输出,把新的细胞状态和新的隐藏状态传递到下一个时间步长中去。 数学计算方式 其中,$W$ 为当前层权重矩阵,$t$ 表示 timestep,$i,f,o$ 分别为输入门、遗忘门、输出门,第一个 $Z$ 为输出向量,$\sigma$ 为 sigmoid 。...

July 12, 2024 · 139 words · Kurong

RNN速成(一)

基本概念 循环神经网络 (RNN) 是一种使用序列数据或时序数据的人工神经网络。其最大特点是网络中存在着环,使得信息能在网络中进行循环,实现对序列信息的存储和处理。 循环神经网络 (RNN) 的另一个显著特征是它们在每个网络层中共享参数。 虽然前馈网络的每个节点都有不同的权重,但循环神经网络在每个网络层都共享相同的权重参数。 网络结构 RNN 不是刚性地记忆所有固定长度的序列,而是通过隐藏状态来存储之前时间步的信息。 同时,RNN 还能按时间序列展开循环为如下形式: 以上架构不仅揭示了 RNN 的实质:上一个时刻的网络状态将会作用于(影响)到下一个时刻的网络状态,还表明 RNN 和序列数据密切相关。同时,RNN 要求每一个时刻都有一个输入,但是不一定每个时刻都需要有输出。 如上图所示,隐含层的计算公式如下: $$ s_t=f \ (U_{x_t}+W_{s_{t-1}}) $$ 其中, $f$ 为激活函数。 训练方法 RNN 利用随时间推移的反向传播 (BPTT) 算法来确定梯度,这与传统的反向传播略有不同,因为它特定于序列数据。 BPTT 的原理与传统的反向传播相同,模型通过计算输出层与输入层之间的误差来训练自身。 这些计算帮助我们适当地调整和拟合模型的参数。 BPTT 与传统方法的不同之处在于,BPTT 会在每个时间步长对误差求和。 通过这个过程,RNN 往往会产生两个问题,即梯度爆炸和梯度消失。 这些问题由梯度的大小定义,也就是损失函数沿着错误曲线的斜率。 如果梯度过小,它会更新权重参数,让梯度继续变小,直到变得可以忽略,即为 0。 发生这种情况时,算法就不再学习。 如果梯度过大,就会发生梯度爆炸,这会导致模型不稳定。 在这种情况下,模型权重会变得太大,并最终被表示为 NaN。 RNN的变体 这里只是一个简介,详情见 《RNN速成(二)》 LSTM 这是一种比较流行的 RNN 架构,由 Sepp Hochreiter 和 Juergen Schmidhuber 提出,用于解决梯度消失问题。LSTM 在神经网络的隐藏层中包含一些“元胞”(cell),共有三个门:一个输入门、一个输出门和一个遗忘门。 这些门控制着预测网络中的输出所需信息的流动。 GRU 这种 RNN 变体类似于 LSTM,因为它也旨在解决 RNN 模型的短期记忆问题。 但它不使用“元胞状态”来调节信息,而是使用隐藏状态;它不使用三个门,而是两个:一个重置门和一个更新门。 类似于 LSTM 中的门,重置门和更新门控制要保留哪些信息以及保留多少信息。

July 6, 2024 · 74 words · Kurong

Named Entity Recognition 相关概念与技术

基本概念 实体:通常指文本中具有特定意义或指代性强的词或短语,如人名、地名、机构名等。 边界识别:确定实体在文本中的起始和结束位置。 分类:将识别出的实体归类到预定义的类别,如人名、地名、组织名、时间表达式、数量、货币值、百分比等。 序列标注:NER任务中常用的一种方法,将文本中的每个词标注为实体的一部分或非实体。 特征提取:从文本中提取有助于实体识别的特征,如词性、上下文信息等。 评估指标:用于衡量NER系统性能的指标,常见的有精确率(Precision)、召回率(Recall)和F1分数。 分类命名方法 BIO:这是最基本的标注方法,其中"B"代表实体的开始(Begin),“I"代表实体的内部(Inside),而"O"代表非实体(Outside)。 BIOES:这种方法在BIO的基础上增加了"E"表示实体的结束(End),和"S"表示单独的实体(Single)。 BMES:这种方法使用"B"表示实体的开始,“M"表示实体的中间(Middle),“E"表示实体的结束,“S"表示单个字符实体。 NER 的一般过程 数据准备:收集并标注一个包含目标实体的数据集。这个数据集应该包含足够的示例,以便模型能够学习如何识别和分类实体。 选择模型架构:选择一个适合任务的模型架构,如基于LSTM的序列模型或者是基于Transformers的预训练模型。 特征工程:根据需要,进行特征工程,提取有助于实体识别的特征,例如词性标注、上下文嵌入等。 模型训练:使用标注好的数据集来训练模型。这通常包括定义损失函数、选择优化器、设置学习率和训练周期等。 评估与优化:在独立的验证集上评估模型性能,使用诸如精确率、召回率和F1分数等指标,并根据结果进行模型调优。 一个小例子 以当前计组KG为例。 数据集 数据格式见 transformers/examples/pytorch/token-classification at main · huggingface/transformers (github.com) 数据来源: 通过百度百科爬虫 BaiduSpider/BaiduSpider: BaiduSpider,一个爬取百度搜索结果的爬虫,目前支持百度网页搜索,百度图片搜索,百度知道搜索,百度视频搜索,百度资讯搜索,百度文库搜索,百度经验搜索和百度百科搜索。 (github.com) 爬取计算机组合原理的相关术语 从计组教材中提取出文本 数据处理: 去掉无用字符、HTML标签等无关信息 使用Tokenizer将文本数据分解成Token 根据Token创建词汇表,每个唯一的Token对应一个唯一的索引 将文本中的Token转换为对应的索引值,以便模型能够处理 添加位置编码,以便模型能够理解Token在序列中的位置 数据集划分: 将数据集划分为训练集、验证集和测试集 格式化数据集: 使数据集符合transformer库NER任务模型的输入格式 模型 选用中文NER预训练模型:ckiplab/albert-base-chinese-ner · Hugging Face 选用peft框架微调:peft/examples/token_classification at main · huggingface/peft (github.com) 训练和测试 一般过程,略。 应用 可以应用在语料中识别实体了。 关系抽取 NER的下一步就是关系抽取了

July 5, 2024 · 62 words · Kurong

Continuous Bag of Words

CBOW CBOW是 continuous bag of words 的缩写,中文译为“连续词袋模型”。它和 skip-gram 的区别在于其通过上下文去预测中心词。 模型结构如下。 在 Projection Layer 中,会将上下文的所有词向量进行累加: $$ X_w=\sum^{2c}_{i=1}v(Context(w)_i) \in \R^m $$ 在 Output Layer 中,使用到的函数是 Hierarchical softmax 层级softmax 。 Hierarchical softmax 是利用哈夫曼树结构来减少计算量的方式。它将 word 按词频作为结点权值来构建哈夫曼树。 哈夫曼树是一种二叉树,实际上就是在不断的做二分类。 具体公式推导见Hierarchical Softmax(层次Softmax) - 知乎 (zhihu.com)。

June 29, 2024 · 38 words · Kurong

Skip-gram Model

skip-gram 具体过程与介绍见 cs224n 系列 从 one-hot 到 lookup-table 每一个单词经过 one-hot 编码后都会得到一个 $(V,1)$ 维的词向量, $V$ 个词就是 $(V,V)$ 维方阵。这样的话,矩阵的计算量会极大,所以要降维以减小计算量。 单词在 one-hot 编码表的位置是由关系的,如果单词出现的位置column = 3,那么对应的就会选中权重矩阵的Index = 3。由此可以通过这个映射关系进行以下操作:将one-hot编码后的词向量,通过一个神经网络的隐藏层,映射到一个低纬度的空间,并且没有任何激活函数。最后得到的东西就叫做 lookup-table,或叫 word embedding 词嵌入,维度 $(V,d)$。 数学原理 一个单词的极大似然估计概率计算公式在取负号后变为: $$ J(\theta)=-\frac{1}{T}\sum^T_{t=1}\sum_{\substack{-m \le j \le m \\ j\neq0}}logP(w_{t+j} \ | \ w_t; \ \theta) $$ 代入softmax计算公式后得到目标函数或叫损失函数: $$ logP(w_o \ | \ w_c)=u_o^Tv_c-log \Bigg( \sum_{i \in V}exp(u_i^Tv_c) \Bigg) $$ 用梯度下降更新参数: $$ \frac{\partial logP(w_o \ | \ w_c)}{\partial v_c} = u_o-\sum_{j \in V}P(w_j \ | \ w_c)u_j $$ 训练结束后,对于词典中的任一索引为 $i$ 的词,我们均得到该词作为中心词和背景词的两组词向量 $vi$ , $u_i$ ....

June 28, 2024 · 172 words · Kurong