跳转至

4 训练词向量

学习目标

  • 了解词向量的相关知识
  • 掌握fasttext工具训练词向量的过程

4.1 训练词向量介绍

  • 词向量概念

    词向量(Word Embeddings)是将词语映射为固定维度的稠密向量,通常是在高维空间中。每个词向量包含了该词的语义信息,并且能反映词与词之间的关系。常见的词向量模型包括:

    • Word2Vec:由Mikolov等人提出,基于神经网络的模型。
    • GloVe:通过矩阵分解方法来训练词向量。
    • FastText:Facebook提出的扩展Word2Vec的模型,能够处理词形变化。
  • 核心思想

    FastText的词向量训练基于Skip-gram with Negative Sampling (SGNS)模型。其核心思想是:给定一个中心词,预测其上下文中的词。 通过学习中心词与其上下文词之间的关系,模型能够学习到词的语义表示。与Word2Vec的Skip-gram模型相比,FastText的主要创新在于引入了字符n-gram,将词拆分为字符级别的n-grams,例如 “apple” 的 3-grams为["<ap", "app", "ppl", "ple", "le>"]。这些n-gram和单词本身一起构成单词的最终表示。这样做的好处有:

    • 处理未登录词 (OOV): 对于未在训练语料中出现的单词,FastText可以通过其n-gram来构建向量表示,从而有效地解决OOV问题。
    • 捕捉形态信息: 对于具有词形变化的语言,字符n-gram可以捕捉到单词内部的形态信息,例如,“running” 和 “run” 之间的关系可以通过共享n-gram来体现。
    • 提高泛化能力: 使用n-gram可以提高模型的泛化能力,使其更好地处理unseen data。
  • FastText与Word2Vec比较

    FastText与Word2Vec (Skip-gram) 的主要区别在于:

    • 字符n-gram: FastText使用字符n-gram来丰富单词表示,而Word2Vec通常只使用单词本身。
    • 处理OOV: FastText可以更好地处理未登录词。
    • 训练速度: FastText的训练速度通常更快。

4.2 训练词向量实现

  • 第一步: 获取数据
  • 第二步: 训练词向量
  • 第三步: 模型超参数设定
  • 第四步: 模型效果检验
  • 第五步: 模型的保存与重加载

4.2.1 数据介绍

数据集仍然使用:英语维基百科的部分网页信息

注意:预处理后的数据为data/fil9

查看预处理后的数据:

Bash
# 查看前80个字符
# 输出结果为由空格分割的单词
 anarchism originated as a term of abuse first used against early working class

4.2.2 训练词向量

Python
# 代码运行在python解释器中
# 导入fasttext
import fasttext


# 使用fasttext的train_unsupervised(无监督训练方法)进行词向量的训练
# 它的参数是数据集的持久化文件路径'data/fil9'
# 注意,该行代码执行耗时很长
model = fasttext.train_unsupervised('data/fil9') 

# 可以使用以下代码加载文本预处理章节已经训练好的模型
model = fasttext.load_model("data/fil9.bin")

# 有效训练词汇量为124M, 共218316个单词
Read 124M words
Number of words:    218316
Number of labels: 0
Progress: 100.0% words/sec/thread:     53996 lr:    0.000000 loss:    0.734999 ETA:     0h 0m

查看单词对应的词向量:

Python
# 通过get_word_vector方法来获得指定词汇的词向量
print(model.get_word_vector("the"))

[ 0.39927667    0.1106462     0.08427446    0.09149589 -0.19243452 -0.29397076
 -0.19361322    0.00540577 -0.16164373 -0.01016428    0.18142511    0.01579806
 -0.36013448    0.1152205    -0.22123231 -0.02243577 -0.18662278 -0.01284971
 -0.14532585 -0.3008444    -0.02893916 -0.20764123    0.26436484    0.12347665
 -0.16956569    0.06943749    0.26272452 -0.33402282    0.07903852    0.228938
    0.06698014 -0.0043668    -0.14023364 -0.2685339    -0.37279004    0.19210193
 -0.12468006 -0.26495013 -0.2109854     0.11181766 -0.05237127    0.10172919
    0.30633664    0.04337211    0.18390231 -0.52560234    0.08089379 -0.09324447
 -0.20415         0.20581587    0.0728284    -0.45319322 -0.15610519 -0.0805693
 -0.17666356    0.24203898 -0.12371875    0.03256057 -0.22328985 -0.06557693
 -0.29617023    0.40588886    0.3878154     0.16827671 -0.02174405    0.10524382
 -0.02750404 -0.08420668    0.18017569    0.3753169     0.35997233 -0.0821524
 -0.15430236 -0.13327129    0.12386149    0.14352481 -0.07313053    0.06678908
    0.02200742 -0.28622466 -0.00115055    0.01683688 -0.07603466    0.03997784
 -0.1036246    -0.18134357 -0.06875866 -0.45207763 -0.3559347     0.15210047
    0.06070778    0.18472968 -0.05691566 -0.264611     -0.16316931 -0.26561385
    0.2783478     0.04740454    0.26854888 -0.07840855]

4.2.3 模型超参数设定

Python
# 在训练词向量过程中, 我们可以设定很多常用超参数来调节我们的模型效果, 如:
# 无监督训练模式: 'skipgram' 或者 'cbow', 默认为'skipgram', 在实践中,skipgram模式在利用子词方面比cbow更好.
# 词嵌入维度dim: 默认为100, 但随着语料库的增大, 词嵌入的维度往往也要更大.
# 数据循环次数epoch: 默认为5, 但当你的数据集足够大, 可能不需要那么多次.
# 学习率lr: 默认为0.05, 根据经验, 建议选择[0.01,1]范围内.
# 使用的线程数thread: 默认为12个线程, 一般建议和你的cpu核数相同.

model = fasttext.train_unsupervised('data/fil9', "cbow", dim=300, epoch=1, lr=0.1, thread=8)

Read 124M words
Number of words:    218316
Number of labels: 0
Progress: 100.0% words/sec/thread:     49523 lr:    0.000000 avg.loss:    1.777205 ETA:     0h 0m 0s

4.2.4 模型效果检验

Python
# 检查单词向量质量的一种简单方法就是查看其邻近单词, 通过我们主观来判断这些邻近单词是否与目标单词相关来粗略评定模型效果好坏.

# 查找"运动"的邻近单词, 我们可以发现"体育网", "运动汽车", "运动服"等. 
print(model.get_nearest_neighbors('sports'))

[(0.8414610624313354, 'sportsnet'), (0.8134572505950928, 'sport'), (0.8100415468215942, 'sportscars'), (0.8021156787872314, 'sportsground'), (0.7889881134033203, 'sportswomen'), (0.7863013744354248, 'sportsplex'), (0.7786710262298584, 'sporty'), (0.7696356177330017, 'sportscar'), (0.7619683146476746, 'sportswear'), (0.7600985765457153, 'sportin')]


# 查找"音乐"的邻近单词, 我们可以发现与音乐有关的词汇.
print(model.get_nearest_neighbors('music'))

[(0.8908010125160217, 'emusic'), (0.8464668393135071, 'musicmoz'), (0.8444250822067261, 'musics'), (0.8113634586334229, 'allmusic'), (0.8106718063354492, 'musices'), (0.8049437999725342, 'musicam'), (0.8004694581031799, 'musicom'), (0.7952923774719238, 'muchmusic'), (0.7852965593338013, 'musicweb'), (0.7767147421836853, 'musico')]

# 查找"小狗"的邻近单词, 我们可以发现与小狗有关的词汇.
print(model.get_nearest_neighbors('dog'))

[(0.8456876873970032, 'catdog'), (0.7480780482292175, 'dogcow'), (0.7289096117019653, 'sleddog'), (0.7269964218139648, 'hotdog'), (0.7114801406860352, 'sheepdog'), (0.6947550773620605, 'dogo'), (0.6897546648979187, 'bodog'), (0.6621081829071045, 'maddog'), (0.6605004072189331, 'dogs'), (0.6398137211799622, 'dogpile')]

4.2.5 模型保存与重加载

Python
# 使用save_model保存模型
model.save_model("data/fil9.bin")

# 使用fasttext.load_model加载模型
model = fasttext.load_model("data/fil9.bin")
print(model.get_word_vector("the"))

[ 0.39927667    0.1106462     0.08427446    0.09149589 -0.19243452 -0.29397076
 -0.19361322    0.00540577 -0.16164373 -0.01016428    0.18142511    0.01579806
 -0.36013448    0.1152205    -0.22123231 -0.02243577 -0.18662278 -0.01284971
 -0.14532585 -0.3008444    -0.02893916 -0.20764123    0.26436484    0.12347665
 -0.16956569    0.06943749    0.26272452 -0.33402282    0.07903852    0.228938
    0.06698014 -0.0043668    -0.14023364 -0.2685339    -0.37279004    0.19210193
 -0.12468006 -0.26495013 -0.2109854     0.11181766 -0.05237127    0.10172919
    0.30633664    0.04337211    0.18390231 -0.52560234    0.08089379 -0.09324447
 -0.20415         0.20581587    0.0728284    -0.45319322 -0.15610519 -0.0805693
 -0.17666356    0.24203898 -0.12371875    0.03256057 -0.22328985 -0.06557693
 -0.29617023    0.40588886    0.3878154     0.16827671 -0.02174405    0.10524382
 -0.02750404 -0.08420668    0.18017569    0.3753169     0.35997233 -0.0821524
 -0.15430236 -0.13327129    0.12386149    0.14352481 -0.07313053    0.06678908
    0.02200742 -0.28622466 -0.00115055    0.01683688 -0.07603466    0.03997784
 -0.1036246    -0.18134357 -0.06875866 -0.45207763 -0.3559347     0.15210047
    0.06070778    0.18472968 -0.05691566 -0.264611     -0.16316931 -0.26561385
    0.2783478     0.04740454    0.26854888 -0.07840855]

4.3 小结

  • 什么是词向量:

    词向量(Word Embeddings)是将词语映射为固定维度的稠密向量,通常是在高维空间中。每个词向量包含了该词的语义信息,并且能反映词与词之间的关系。

  • 使用fasttext工具训练词向量的过程:

    • 第一步: 获取数据
    • 第二步: 训练词向量
    • 第三步: 模型超参数设定
    • 第四步: 模型效果检验
    • 第五步: 模型的保存与重加载