NLP学习路线图(十八):Word2Vec (CBOW Skip-gram)

article/2025/7/2 1:29:36

自然语言处理(NLP)的核心挑战在于让机器“理解”人类语言。传统方法依赖独热编码(One-hot Encoding) 表示单词,但它存在严重缺陷:每个单词被视为孤立的符号,无法捕捉词义关联(如“国王”与“王后”的关系),且维度灾难使计算效率低下。

词向量(Word Embedding) 革命性地解决了这些问题。它将单词映射为稠密、低维的实数向量(如50-300维),其核心思想是:具有相似上下文(Context)的单词,其向量表示在向量空间中也应彼此接近。Word2Vec正是实现这一思想的里程碑式模型。

一、Word2Vec:分布式表示的引擎

Word2Vec由Tomas Mikolov等人于2013年在谷歌提出,包含两种高效架构:

  1. CBOW(Continuous Bag-of-Words):通过上下文预测中心词

  2. Skip-gram:通过中心词预测上下文

两者共享核心目标:优化词向量,使模型能根据上下文/中心词准确预测目标词的概率

🔍 核心概念:分布式假设

“一个词的意义由其周围经常出现的词所决定。” —— J.R. Firth

Word2Vec完美实践了这一假设。例如:

句子:“猫在沙发上睡觉”
上下文窗口(size=2): [“在”, “沙发”, “上”, “睡觉”] → 中心词“猫”

模型通过上下文学习“猫”的向量表示。 

二、CBOW模型详解:上下文预测中心词

1. 模型架构

  • 输入层:上下文窗口内所有单词的独热向量(1×V,V=词汇表大小)

  • 投影层:上下文词向量求平均(或求和),形成固定长度向量

  • 隐藏层:无激活函数的全连接层(本质是词向量查找)

  • 输出层:Softmax计算中心词概率分布

2. 数学过程

设上下文词为 c₁, c₂, ..., cₘ,中心词为 w

  1. 输入:one_hot(c₁), ..., one_hot(cₘ)

  2. 查词向量:v_{c₁} = W_input · one_hot(c₁) (W_input为输入矩阵)

  3. 计算上下文平均向量:h = (v_{c₁} + ... + v_{cₘ}) / m

  4. 预测中心词概率:P(w|context) = softmax(W_output · h)
    W_output为输出矩阵)

3. 损失函数:交叉熵
Loss = -log(P(w_true | context))

通过反向传播更新 W_input 和 W_output

✅ 优点:
  • 对小规模数据更鲁棒

  • 训练速度快(尤其高频词)

  • 对中心词预测更平滑

❌ 缺点:
  • 上下文词平等对待(忽略位置信息)

  • 对低频词学习效果较差

三、Skip-gram模型详解:中心词预测上下文

1. 模型架构

 

  • 输入层:中心词的独热向量

  • 隐藏层:直接映射为中心词向量

  • 输出层:为每个上下文位置独立预测概率

2. 数学过程

设中心词为 w,上下文词为 c₁, c₂, ..., cₘ

  1. 输入:one_hot(w)

  2. 查中心词向量:v_w = W_input · one_hot(w)

  3. 对每个上下文位置 j
    P(c_j | w) = softmax(W_output · v_w)

  4. 目标:最大化所有上下文词的概率乘积

3. 损失函数:负对数似然
Loss = -Σ log(P(c_j | w))   (j=1 to m)
✅ 优点:
  • 在大型语料库上表现优异

  • 能有效学习低频词表示

  • 生成高质量的词向量(尤其在复杂任务中)

❌ 缺点:
  • 训练速度较慢(需预测多个目标)

  • 小数据集易过拟合


四、关键技术:优化训练效率

原始Softmax计算成本高昂(O(V)复杂度)。Word2Vec采用两种加速技术:

1. 层次Softmax(Hierarchical Softmax)
  • 使用哈夫曼树(Huffman Tree) 组织词汇表(高频词路径短)

  • 将V分类问题转化为约 log₂(V) 次二分类

  • 每个节点有参数向量,概率计算沿路径进行:

    P(word=w | context) = ∏ P(branch_decision at node)

2. 负采样(Negative Sampling)
  • 核心思想:仅更新少数权重

  • 对每个正样本(中心词, 真实上下文词),随机采样K个负样本(中心词, 非上下文词)

  • 优化目标变为:

    Loss = -log(σ(u_o^T · v_c)) - Σ_{k=1}^K log(σ(-u_k^T · v_c))

  • 其中:

    • σ 为sigmoid函数

    • u_o 是正样本词向量

    • u_k 是负样本词向量

  • K通常取5~20,大幅减少计算量

⚡ 经验:Skip-gram + 负采样是最常用组合,在语义任务中表现最佳。 

五、Word2Vec特性与局限

✨ 核心特性:
  • 语义相似性:相似词向量距离小
    cosine(v("国王"), v("王后")) ≈ 0.8

  • 线性关系:词类比任务表现惊艳
    v("国王") - v("男人") + v("女人") ≈ v("王后")

  • 上下文依赖:一词多义有不同向量(需结合上下文扩展)

⚠️ 重要局限:
  1. 静态表示:每个词仅一个向量,无法处理一词多义
    (如“苹果”在公司和水果语境中含义不同)

  2. 未考虑全局统计:仅依赖局部窗口,忽略文档级共现

  3. 未建模词序:CBOW/Skip-gram均忽略词位置信息

  4. OOV问题:无法处理未登录词


六、实战:训练与评估

🛠️ 训练步骤(Python示例):
from gensim.models import Word2Vecsentences = [["猫", "坐", "在", "沙发"], ...]  # 分词后的语料# 训练Skip-gram模型
model = Word2Vec(sentences,vector_size=100,   # 向量维度window=5,          # 上下文窗口sg=1,              # 1=Skip-gram; 0=CBOWnegative=5,        # 负采样数min_count=5,        # 忽略低频词workers=4          # 并行线程
)# 保存与加载
model.save("word2vec.model")
model = Word2Vec.load("word2vec.model")# 应用示例
print(model.wv.most_similar("人工智能", topn=5))
# 输出: [('机器学习', 0.88), ('深度学习', 0.85), ...]result = model.wv.evaluate_word_analogies("analogy-questions.txt")
print("词类比准确率:", result["correct"] / result["total"])
📊 评估方法:
  1. 内部任务

    • 词相似度(如计算与人类判断的相关性)

    • 词类比(如 man:woman :: king:?

  2. 下游任务

    • 文本分类(作为特征输入)

    • 命名实体识别(增强上下文表示)

    • 情感分析(捕捉情感语义)

研究显示:在词类比任务中,Skip-gram比CBOW平均高5-10%准确率。 

七、超越Word2Vec:现代嵌入技术

尽管Word2Vec影响深远,后续技术已解决其关键短板:

  • FastText:引入子词(subword)信息,能生成未登录词向量
    向量("深度学习") ≈ 向量("深") + 向量("度") + 向量("学习")

  • GloVe:结合全局统计与局部窗口,优化共现矩阵分解

  • 上下文嵌入(ELMo/BERT):动态生成词向量,解决一词多义
    BERT("苹果股价") vs BERT("吃苹果") → 不同向量表示

  • 大规模预训练模型(GPT, T5):基于Transformer架构,生成任务感知嵌入


八、总结:为什么Word2Vec仍是基石?

Word2Vec的成功在于其简洁性与高效性的完美平衡:

  1. 首次证明浅层神经网络可学习高质量语义表示

  2. 负采样/层次Softmax 大幅提升训练效率

  3. 开创了词类比评估范式,直观展示语义关系

  4. 启发了后续嵌入技术的爆炸性发展

 


http://www.hkcw.cn/article/BPFcJLWivL.shtml

相关文章

win32相关(事件)

事件 什么是事件? 事件是指系统或应用程序中发生的特定动作或状态变化,这些动作或变化可以被程序检测并响应。Windows 采用事件驱动的编程模型,应用程序主要通过处理各种事件来与用户交互 我们来看一下事件的函数 HANDLE CreateEventW(LPSE…

VisionPro项目记录3 —— 圆心距

简介:本项目实现基于Cognex视觉系统的两圆心对位功能,使用一个圆作为基准,另一个圆进行补偿,输出偏移值给PLC或机械手。 系统采用CogFindCircleTool定位两圆心坐标,通过脚本计算圆心距并乘以缩放系数kValue&#xff0…

面向连接的运输:TCP

目录 TCP连接 TCP报文段结构 往返时间估计与超时 可靠数据传输 回退N步or超时重传 超时间隔加倍 快速重传 流量控制 TCP连接管理 三次握手 1. 客户端 → 服务器:SYN 包 2. 服务器 → 客户端:SYNACK 包 3. 客户端 → 服务器:AC…

使用Python进行函数作画

前言 因为之前通过deepseek绘制一下卡通的人物根本就不像,又想起来之前又大佬通过函数绘制了一些图像,想着能不能用Python来实现,结果发现可以,不过一些细节还是需要自己调整,deepseek整体的框架是没有问题&#xff0…

C#项目07-二维数组的随机创建

实现需求 创建二维数组,数组的列和宽为随机,数组内的数也是随机 知识点 1、Random类 Public Random rd new Random(); int Num_Int rd.Next(1, 100);2、数组上下限。 //定义数组 int[] G_Array new int[1,2,3,4];//一维数组 int[,] G_Array_T …

java Semaphore‌

Java Semaphore 用于控制同时访问特定资源的线程数量,通过管理一组“许可”(permits)实现并发限制。 模拟6人上厕所,但只有两个坑位,测试代码: import java.util.concurrent.Semaphore;// 假设厕所只有俩…

代码随想录算法训练营第60期第五十五天打卡

大家好,我们今天继续我们图论的部分,其实我们昨天是主要讲解了深搜与广搜的理论基础,我们大体上了解了两种算法的差异与适用情景,今天我们就继续我们的图论的章节,以后几天的题目是图论中比较有名的问题叫做岛屿问题&a…

【音视频】FFmpeg 编码H265

一、概述 实现了读入本地yuv文件,通过libx265编码为H265格式,并存储到本地文件中 二、实现流程 准备文件 在build路径下准备yuv文件 在项目中添加文件参数,输出为h265文件,使用libx265编码 初始化解码器 通过传进来的libx265…

贪心算法应用:带权任务间隔调度问题详解

贪心算法应用:带权任务间隔调度问题详解 贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。带权任务间隔调度问题是贪心算法的一个经典应用场景。 问题定义…

Git-flow流

Git git是版本控制软件,一般用来做代码版本控制 github是一个免费版本控制仓库是国内外很多开源项目的集中地,其本体是一个git服务器 Git初始化操作 git init 初始化仓库 git status 查看当前仓库的状态 git add . 将改动的文件加到暂存区 gi…

LeetCode-链表操作题目

虚拟头指针,在当前head的前面建立一个虚拟头指针,然后哪怕当前的head的val等于提供的val也能进行统一操作 203移除链表元素简单题 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(…

mybatisplus的总结

一.通用Mapper 1.首先创建一个接口与实体类 Data TableName("user") public class User { TableId(value "id", type IdType.AUTO) private Long id; TableField("name") private String name; TableField("age") pri…

UE5 创建2D角色帧动画学习笔记

UE5 创建2D角色帧动画 1.对导入的角色所有帧动画图片Apply paper2d Texture Setting 2.创建图片精灵 Create Sprite 3.全选创建的图片精灵,右键点击 Create Flipbook(创建图像序列视图) 4.双击此paper Flipbook 即可预览该角色帧动画 UE5 2D角色帧动画 Frames P…

MyBatisPlus--条件构造器及自定义SQL详解

条件构造器 在前面学习快速入门的时候,练习的增删改查都是基于id去执行的,但是在实际开发业务中,增删改查的条件往往是比较复杂的,因此MyBatisPlus就提供了一个条件构造器来帮助构造复杂的条件。 MyBatisPlus支持各种复杂的wher…

《类和对象--继承》

引言: 在刚接触C的时候,我们首先学习了有关类和对象的一些基础知识,今天我们就要接着学习类和对象的另一板块–继承。 一:继承的概念和定义 1. 继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手…

利用R语言生成区试中随机区组试验设计——多点

目前,区试要求对照不得位于区组的首尾小区,且不同区组的相邻小区位置不得出现同一品种。基于这一要求,编写了R语言的随机区组试验设计。此函数可用于多个试验点试验设计生成情况。 rcbd函数有6个参数: local_name为试验点名称的向…

pytorch基本运算-范数

引言 前序学习进程中,已经对pytorch基本运算有了详细探索,文章链接有: 基本运算 广播失效 乘除法和幂运算 hadamard积、点积和矩阵乘法 上述计算都是以pytorch张量为运算元素,这些张量基本上也集中在一维向量和二维矩阵&#x…

STM32G4 电机外设篇(四)DAC输出电流波形 + CAN通讯

目录 一、STM32G4 电机外设篇(四)DAC输出电流波形 CAN通讯1 DAC输出电流波形1.1 STM32CubeMX配置和Keil代码1.2 实验现象 2 CAN/CANFD通讯2.1 STM32CubeMX配置和Keil代码2.2 实验现象 附学习参考网址欢迎大家有问题评论交流 (* ^ ω ^) 一、STM32G4 电机…

电子电气架构 --- 后轮转向的一点事情

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从&#x…

web复习(四)

盒子模型的例题 例一&#xff1a; <!doctype html> <html> <head> <meta charset"utf-8"> <title>咖啡店banner</title> <style type"text/css"> /*将页面中所有元素的内外边距设置为0*/ *{ padding:0; margin…