当前位置: 首页 > news >正文

自然语言处理(五):子词嵌入(fastText模型)

子词嵌入

在英语中,“helps”“helped”和“helping”等单词都是同一个词“help”的变形形式。“dog”和“dogs”之间的关系与“cat”和“cats”之间的关系相同,“boy”和“boyfriend”之间的关系与“girl”和“girlfriend”之间的关系相同。在法语和西班牙语等其他语言中,许多动词有40多种变形形式,而在芬兰语中,名词最多可能有15种变形。在语言学中,形态学研究单词形成和词汇关系。但是,word2vec和GloVe都没有对词的内部结构进行探讨。

文章内容来自李沐大神的《动手学深度学习》并加以我的理解,感兴趣可以去https://zh-v2.d2l.ai/查看完整书籍


文章目录

  • 子词嵌入
  • fastText模型
  • 字节对编码


fastText模型

回想一下词在word2vec中是如何表示的。在跳元模型和连续词袋模型中,同一词的不同变形形式直接由不同的向量表示,不需要共享参数。为了使用形态信息,fastText模型提出了一种子词嵌入方法,其中子词是一个字符 n n n-gram (Bojanowski et al., 2017)。fastText可以被认为是子词级跳元模型,而非学习词级向量表示,其中每个中心词由其子词级向量之和表示。

fastText是一种用于自然语言处理的词向量表示和文本分类的模型。与传统的词向量模型(如word2vec)不同,fastText不仅考虑了单词级别的表示,还考虑了子词(n-grams)级别的表示。这使得fastText能够更好地处理词汇中的复杂性和稀有词。

以下是fastText模型的主要特点和工作原理:

  1. 子词表示:fastText将每个单词表示为其字符级别n-grams的平均值。例如,对于单词"apple",它可以表示为"ap"、“app”、“ppl”、"ple"等子词的平均向量。这样做的好处是能够捕捉到词汇的内部结构和形态信息,对于处理未登录词(out-of-vocabulary)和稀有词具有优势。

  2. 分层Softmax:fastText使用了分层Softmax来加速训练过程。传统的词向量模型在训练时需要计算输出层中所有词的概率,而分层Softmax将词汇表划分为多个层级,每个层级包含一部分词汇。这样可以减少计算量,并加快训练速度。

  3. 文本分类:除了词向量表示,fastText还可以用于文本分类任务。它使用了基于词袋(bag-of-words)模型的方法,将文本表示为词向量的加权和,并通过softmax函数进行分类预测。

fastText是一个开源项目,由Facebook AI Research团队开发。它以其快速训练速度、对稀有词的处理能力和在文本分类任务上的良好表现而受到广泛关注和应用。

让我们来说明如何以单词“where”为例获得fastText中每个中心词的子词。首先,在词的开头和末尾添加特殊字符“<”和“>”,以将前缀和后缀与其他子词区分开来。 然后,从词中提取字符 n n n-gram。 例如,值 n = 3 n=3 n=3时,我们将获得长度为3的所有子词: “<wh”“whe”“her”“ere”“re>”和特殊子词“”。

在fastText中,对于任意词 w w w,用 C w C_w Cw表示其长度在3和6之间的所有子词与其特殊子词的并集。词表是所有词的子词的集合。假设 z g z_g zg是词典中的子词 g g g的向量,则跳元模型中作为中心词的词 w w w的向量 v w v_w vw是其子词向量的和:
v w = ∑ g ∈ C w z g v_w=\sum_{g\in C_w}z_g vw=gCwzg
fastText的其余部分与跳元模型相同。与跳元模型相比,fastText的词量更大,模型参数也更多。此外,为了计算一个词的表示,它的所有子词向量都必须求和,这导致了更高的计算复杂度。然而,由于具有相似结构的词之间共享来自子词的参数,罕见词甚至词表外的词在fastText中可能获得更好的向量表示。

字节对编码

在fastText中,所有提取的子词都必须是指定的长度,例如 3 3 3 6 6 6,因此词表大小不能预定义。为了在固定大小的词表中允许可变长度的子词,我们可以应用一种称为字节对编码(Byte Pair Encoding,BPE)的压缩算法来提取子词 (Sennrich et al., 2015)。

字节对编码执行训练数据集的统计分析,以发现单词内的公共符号,诸如任意长度的连续字符。从长度为1的符号开始,字节对编码迭代地合并最频繁的连续符号对以产生新的更长的符号。请注意,为提高效率,不考虑跨越单词边界的对。最后,我们可以使用像子词这样的符号来切分单词。字节对编码及其变体已经用于诸如GPT-2 (Radford et al., 2019)和RoBERTa (Liu et al., 2019)等自然语言处理预训练模型中的输入表示。在下面,我们将说明字节对编码是如何工作的。

首先,我们将符号词表初始化为所有英文小写字符、特殊的词尾符号’_‘和特殊的未知符号’[UNK]'。

import collectionssymbols = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm','n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z','_', '[UNK]']

因为我们不考虑跨越词边界的符号对,所以我们只需要一个字典raw_token_freqs将词映射到数据集中的频率(出现次数)。注意,特殊符号’_'被附加到每个词的尾部,以便我们可以容易地从输出符号序列(例如,“a_all er_man”)恢复单词序列(例如,“a_all er_man”)。由于我们仅从单个字符和特殊符号的词开始合并处理,所以在每个词(词典token_freqs的键)内的每对连续字符之间插入空格。换句话说,空格是词中符号之间的分隔符。

raw_token_freqs = {'fast_': 4, 'faster_': 3, 'tall_': 5, 'taller_': 4}
token_freqs = {}
for token, freq in raw_token_freqs.items():token_freqs[' '.join(list(token))] = raw_token_freqs[token]
token_freqs

在这里插入图片描述

我们定义以下get_max_freq_pair函数,其返回词内最频繁的连续符号对,其中词来自输入词典token_freqs的键。

def get_max_freq_pair(token_freqs):pairs = collections.defaultdict(int)for token, freq in token_freqs.items():symbols = token.split()for i in range(len(symbols) - 1):# “pairs”的键是两个连续符号的元组pairs[symbols[i], symbols[i + 1]] += freqreturn max(pairs, key=pairs.get)  # 具有最大值的“pairs”键

作为基于连续符号频率的贪心方法,字节对编码将使用以下merge_symbols函数来合并最频繁的连续符号对以产生新符号。

def merge_symbols(max_freq_pair, token_freqs, symbols):symbols.append(''.join(max_freq_pair))new_token_freqs = dict()for token, freq in token_freqs.items():new_token = token.replace(' '.join(max_freq_pair),''.join(max_freq_pair))new_token_freqs[new_token] = token_freqs[token]return new_token_freqs

解释一下new_token = token.replace(’ ‘.join(max_freq_pair),’'.join(max_freq_pair))
max_freq_pair 是一个元组,表示最高频率的一对符号。例如,假设 max_freq_pair = ('a', 'b')
' '.join(max_freq_pair) 将最高频率符号对中的两个符号用空格连接起来,生成一个字符串。对于上述示例,结果将是 'a b'
''.join(max_freq_pair) 将最高频率符号对中的两个符号直接连接起来,生成一个新的合并后的符号。对于上述示例,结果将是 'ab'
token.replace(' '.join(max_freq_pair), ''.join(max_freq_pair)) 则使用生成的字符串和新的合并后的符号对标记进行替换操作。它将标记中所有出现的最高频率符号对 'a b' 替换为合并后的符号 'ab',得到新的合并标记。

现在,我们对词典token_freqs的键迭代地执行字节对编码算法。在第一次迭代中,最频繁的连续符号对是’t’和’a’,因此字节对编码将它们合并以产生新符号’ta’。在第二次迭代中,字节对编码继续合并’ta’和’l’以产生另一个新符号’tal’。

num_merges = 10
for i in range(num_merges):max_freq_pair = get_max_freq_pair(token_freqs)token_freqs = merge_symbols(max_freq_pair, token_freqs, symbols)print(f'合并# {i+1}:',max_freq_pair)

在这里插入图片描述
在字节对编码的10次迭代之后,我们可以看到列表symbols现在又包含10个从其他符号迭代合并而来的符号。

print(symbols)
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '_', '[UNK]', 'ta', 'tal', 'tall', 'fa', 'fas', 'fast', 'er', 'er_', 'tall_', 'fast_']

对于在词典raw_token_freqs的键中指定的同一数据集,作为字节对编码算法的结果,数据集中的每个词现在被子词“fast_”“fast”“er_”“tall_”和“tall”分割。例如,单词“faster_”和“taller_”分别被分割为“fast er_”和“tall er_”。

print(list(token_freqs.keys()))

在这里插入图片描述
请注意,字节对编码的结果取决于正在使用的数据集。我们还可以使用从一个数据集学习的子词来切分另一个数据集的单词。作为一种贪心方法,下面的segment_BPE函数尝试将单词从输入参数symbols分成可能最长的子词。

def segment_BPE(tokens, symbols):outputs = []for token in tokens:start, end = 0, len(token)cur_output = []# 具有符号中可能最长子字的词元段while start < len(token) and start < end:if token[start: end] in symbols:cur_output.append(token[start: end])start = endend = len(token)else:end -= 1if start < len(token):cur_output.append('[UNK]')outputs.append(' '.join(cur_output))return outputs
  1. 函数接受两个参数:tokenssymbols

    • tokens 是待分割的标记列表。
    • symbols 是用于分割标记的符号列表。
  2. 函数创建一个空列表 outputs 用于存储分割后的结果。

  3. 对于每个标记 token,进行以下操作:

  4. 初始化两个变量 startend 为 0 和标记的长度。

  5. 创建一个空列表 cur_output 用于存储当前标记的分割结果。

  6. 在一个循环中,尝试从标记的起始位置开始找到最长的子字,使其在符号列表 symbols 中存在。

  7. 如果从 startend 的子字在 symbols 中存在,则将该子字添加到 cur_output 中,并更新 startend,将 end 重置为标记的长度。

  8. 如果子字不在 symbols 中,则将 end 减小 1,继续尝试找到更短的子字。

  9. 如果 start 小于标记的长度,说明有未被分割的部分,将其视为未知符号 [UNK],并将其添加到 cur_output 中。

  10. cur_output 使用空格连接为一个字符串,并将其添加到 outputs 列表中。

  11. 循环结束后,返回 outputs 列表,其中包含了对每个标记进行分割后的结果。

我们使用列表symbols中的子词(从前面提到的数据集学习)来表示另一个数据集的tokens。

tokens = ['tallest_', 'fatter_']
print(segment_BPE(tokens, symbols))

在这里插入图片描述

相关文章:

自然语言处理(五):子词嵌入(fastText模型)

子词嵌入 在英语中&#xff0c;“helps”“helped”和“helping”等单词都是同一个词“help”的变形形式。“dog”和“dogs”之间的关系与“cat”和“cats”之间的关系相同&#xff0c;“boy”和“boyfriend”之间的关系与“girl”和“girlfriend”之间的关系相同。在法语和西…...

Zabbix“专家坐诊”第202期问答汇总

问题一 Q&#xff1a;请问一下 zabbix 里面怎么能创建出和sh文件有关联的监控项&#xff1f; A&#xff1a; 1.使用 Zabbix Agent 主动模式&#xff1a;如果你在目标主机上安装了 Zabbix Agent&#xff0c;并且想要监控与 sh 文件相关的指标&#xff0c;可以创建一个自定义的…...

【c语言】输出n行按如下规律排列的数

题述&#xff1a;输出n行按如下规律排列的数 输入&#xff1a; 4(应该指的是n) 输出: 思路&#xff1a; 利用下标的规律求解&#xff0c;考察数组下标的灵活应用&#xff0c;我们可以看出数从1开始是斜着往下放的&#xff0c;那么我们如何利用两层for循环求解这道题&#xff…...

023 - STM32学习笔记 - 扩展外部SDRAM(二) - 扩展外部SDRAM实验

023- STM32学习笔记 - 扩展外部SDRAM&#xff08;一&#xff09; - 扩展外部SDRAM实验 本节内容中要配置的引脚很多&#xff0c;如果你用的开发板跟我的不一样&#xff0c;请详细参照STM32规格书中说明对相关GPIO引脚进行配置。 先提前对本届内容的变成步骤进行总结如下&…...

机器学习 | Python实现XGBoost极限梯度提升树模型答疑

机器学习 | MATLAB实现XGBoost极限梯度提升树模型答疑 目录 机器学习 | MATLAB实现XGBoost极限梯度提升树模型答疑问题系列问题回答问题系列 关于XGBoost有几个问题想请教一下。1.XGBoost的API有哪些种调用方法?2.参数如何调? 问题回答 XGBoost的API有2种调用方法,一种是我们…...

关于使用远程工具连接mysql数据库时,提示:Public Key Retrieval is not allowed

我在使用DBeaver工具连接 数据库时&#xff0c;提示&#xff1a;Public Key Retrieval is not allowed&#xff0c; 我在前一天还是可以连接的&#xff0c;但是今天突然无法连接了&#xff0c; 但是最后捣鼓了一下又可以了。 具体方法&#xff1a;首先先把mysql服务停了&#x…...

leetcode做题笔记​117. 填充每个节点的下一个右侧节点指针 II

给定一个二叉树&#xff1a; struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针&#xff0c;让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点&#xff0c;则将 next 指针设置为 NULL 。 初始状态下&#xff0c;所有 next 指针都…...

解决博客不能解析PHP直接下载源码问题

背景&#xff1a; 在网站设置反向代理后&#xff0c;网站突然不能正常访问&#xff0c;而是会直接下载访问文件的PHP源码 解决办法&#xff1a; 由于在搞完反向代理之后&#xff0c;PHP版本变成了纯静态&#xff0c;所以网站不能正常解析&#xff1b;只需要把PHP版本恢复正常…...

voc 转coco

import os import random import shutil import sys import json import glob import xml.etree.ElementTree as ET""" 修改下面3个参数 1.val_files_num : 验证集的数量 2.test_files_num &#xff1a;测试集的数量 3.voc_annotations : voc的annotations路径 …...

【C语言每日一题】03. 对齐输出

题目来源&#xff1a;http://noi.openjudge.cn/ch0101/03/ 03 对齐输出 总时间限制: 1000ms 内存限制: 65536kB 问题描述 读入三个整数&#xff0c;按每个整数占8个字符的宽度&#xff0c;右对齐输出它们。 输入 只有一行&#xff0c;包含三个整数&#xff0c;整数之间以一…...

七大排序完整版

目录 一、直接插入排序 &#xff08;一&#xff09;单趟直接插入排 1.分析核心代码 2.完整代码 &#xff08;二&#xff09;全部直接插入排 1.分析核心代码 2.完整代码 &#xff08;三&#xff09;时间复杂度和空间复杂度 二、希尔排序 &#xff08;一&#xff09;对…...

C语言的数据类型简介

一、基本类型 &#xff08;1&#xff09;六种基本类型 **字符串常量和字符常量的不同 1&#xff09;‘a’为字符常量&#xff0c;”a”为字符串常量 2&#xff09;每个字符串的结尾&#xff0c;编译器会自动添加一个结束标志位‘\0’ “a”包含两个字符’a’和’\0’ &#x…...

Fei-Fei Li-Lecture 16:3D Vision 【斯坦福大学李飞飞CV课程第16讲:3D Vision】

目录 P1 2D Detection and Segmentation P2 Video 2D time series P3 Focus on Two Problems P4 Many more topics in 3D Vision P5-10 Multi-View CNN P11 Experiments – Classification & Retrieval P12 3D Shape Representations P13--17 3D Shape Represen…...

【计算机视觉】YOLO 入门:训练 COCO128 数据集

一、COCO128 数据集 我们以最近大热的YOLOv8为例&#xff0c;回顾一下之前的安装过程&#xff1a; %pip install ultralytics import ultralytics ultralytics.checks()这里选择训练的数据集为&#xff1a;COCO128 COCO128是一个小型教程数据集&#xff0c;由COCOtrain2017中…...

【数分面试答疑】XX场景如何分析问题的思考

问题&#xff1a; 如何分析消费贷客户的用款活跃度&#xff0c;简单列出分析报告的思路框架 解答 这个问题是一个典型的数据分析类的面试问题&#xff0c;主要考察面试者对于消费贷客户的用款活跃度分析的理解和方法&#xff0c;以及对于数据分析报告的撰写和呈现的能力。回…...

html中如何用vue语法,并使用UI组件库 ,html中引入vue+ant-design-vue或者vue+element-plus

html中如何用vue语法&#xff0c;并使用UI组件库 前言 先说一下本次应用的场景&#xff0c;本次项目中&#xff0c;需要引入github中别人写好的插件&#xff0c;插件比较大&#xff0c;没有方法直接在自己项目中&#xff0c;把别人的项目打包合并生成html&#xff08;类似于前…...

【数据结构】二叉数的存储与基本操作的实现

文章目录 &#x1f340;二叉树的存储&#x1f333;二叉树的基本操作&#x1f431;‍&#x1f464;二叉树的创建&#x1f431;‍&#x1f453;二叉树的遍历&#x1f3a1;前中后序遍历&#x1f4cc;前序遍历&#x1f4cc;中序遍历&#x1f4cc;后续遍历 &#x1f6eb;层序遍历&am…...

使用 Netty 实现群聊功能的步骤和注意事项

文章目录 前言声明功能说明实现步骤WebSocket 服务启动Channel 初始化HTTP 请求处理HTTP 页面内容WebSocket 请求处理 效果展示总结 前言 通过之前的文章介绍&#xff0c;我们可以深刻认识到Netty在网络编程领域的卓越表现和强大实力。这篇文章将介绍如何利用 Netty 框架开发一…...

一篇文章搞定《WebView的优化及封装》

一篇文章搞定《WebView的优化及封装》 前言WebView的过程分析确定优化方案一、预加载&#xff0c;复用缓冲池&#xff08;初始化优化&#xff09;优化的解析说明具体的实现 二、预置模版&#xff08;请求、渲染优化&#xff09;优化的解析说明具体的实现1、离线包2、预获取数据…...

FreeSWITCH 1.10.10 简单图形化界面5 - 使用百度TTS

FreeSWITCH 1.10.10 简单图形化界面5 - 使用百度TTS 0、 界面预览1、注册百度AI开放平台&#xff0c;开通语音识别服务2、获取AppID/API Key/Secret Key3、 安装百度语音合成sdk4、合成代码5、在PBX中使用百度TTS6、音乐文件-TTS7、拨号规则-tts_command 0、 界面预览 http://…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...