大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流
个人主页-Sonhhxg_柒的博客_CSDN博客
欢迎各位→点赞 + 收藏⭐️ + 留言
系列专栏 - 机器学习【ML】 自然语言处理【NLP】 深度学习【DL】
foreword
✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。
如果你对这个系列感兴趣的话,可以关注订阅哟
文章目录
什么是词向量/词嵌入
词向量的理解 TODO
Word2Vec
基于层次 SoftMax 的 CBOW 模型
层次 SoftMax 的正向传播
层次 Softmax 的反向传播 TODO
基于层次 Softmax 的 Skip-gram 模型
---
基于负采样的 CBOW 和 Skip-gram
负采样算法
Word2Vec 中的做法
一些源码细节
σ(x) 的近似计算
低频词的处理
高频词的处理
自适应学习率
参数初始化
GloVe
共现矩阵
构架共现矩阵的细节
GloVe 的基本思想
GloVe 的目标函数
GloVe 目标函数的推导过程
GloVe 与 Word2Vec 的区别
FastText
gensim.models.FastText 使用示例
获取单个词的 ngrams 表示
计算一个未登录词的词向量
WordRank TODO
CharCNN 字向量
其他实践
一般 embedding 维度的选择
word2vec 中的数学原理详解(三)背景知识 - CSDN博客
One-hot 表示
分布式表示 (distributed representation)
Word2Vec 本质上也是一个神经语言模型,但是它的目标并不是语言模型本身,而是词向量;因此,其所作的一系列优化,都是为了更快更好的得到词向量
Word2Vec 提供了两套模型:CBOW 和 Skip-Gram(SG)
context(w)
的情况下,预测 w
w
的情况下预测 context(w)
从训练集的构建方式可以更好的理解和区别 CBOW 和 SG 模型
每个训练样本为一个二元组 (x, y)
,其中 x
为特征,y
为标签
假设上下文窗口的大小 context_window =5
,即
或者说 skip_window = 2
,有 context_window = skip_window*2 + 1
CBOW 的训练样本为:
SG 的训练样本为:
一般来说,skip_window <= 10
除了两套模型,Word2Vec 还提供了两套优化方案,分别基于 Hierarchical Softmax (层次SoftMax) 和 Negative Sampling (负采样)
【输入层】将 context(w)
中的词映射为 m
维词向量,共 2c
个
【投影层】将输入层的 2c
个词向量累加求和,得到新的 m
维词向量
【输出层】输出层对应一棵哈夫曼树,以词表中词作为叶子节点,各词的出现频率作为权重——共 N
个叶子节点,N-1
个非叶子节点
对比 N-gram 神经语言模型的网络结构
w
的前 n-1
个词,后者使用 w
两边的词
这是后者词向量的性能优于前者的主要原因
模型改进
层 Softmax 实际上是把一个超大的多分类问题转化成一系列二分类问题
示例:求 P("足球"|context("足球"))
为什么层次 SoftMax 能加速
word2vec 中的数学原理详解(四)基于 Hierarchical Softmax 的模型 - CSDN博客
这里保留了【投影层】,但实际上只是一个恒等变换
从模型的角度看:CBOW 与 SG 模型的区别仅在于 x_w
的构造方式不同,前者是 context(w)
的词向量累加;后者就是 w
的词向量
虽然 SG 模型用中心词做特征,上下文词做类标,但实际上两者的地位是等价的
噪音对比估计(NCE) - CSDN博客
(context(w), w)
二元对;对于给定的 context(w)
,w
就是它的正样本,而其他所有词都是负样本。w
,生成相应负样本的方法记
以这 N+1
个点对区间 [0,1]
做非等距切分
引入的一个在区间 [0,1]
上的 M
等距切分,其中 M >> N
源码中取
M = 10^8
然后对两个切分做投影,得到映射关系
采样时,每次生成一个 [1, M-1]
之间的整数 i
,则 Table(i)
就对应一个样本;当采样到正例时,跳过(拒绝采样)。
特别的,Word2Vec 在计算 len(w)
时做了一些改动——为 count(·)
加了一个指数
σ(x)
的近似计算Sub-sampling 技巧
t
,将 w
以 p(w)
的概率舍弃,p(w)
的计算如下 Word2Vec 中的Sub-sampling
预先设置一个初始的学习率 η_0
(默认 0.025),每处理完 M
(默认 10000)个词,就根据以下公式调整学习率
随着训练的进行,学习率会主键减小,并趋向于 0
为了方式学习率过小,Word2Vec 设置了一个阈值 η_min
(默认 0.0001 * η_0
);当学习率小于 η_min
,则固定为 η_min
。
[-0.5/m, 0.5/m]
,其中 m
为词向量的维度0
CS224d - L2&3-词向量
min(x, t)
x
为功能词语其他词的共现次数,t
为设置的阈值但是似乎没有人这么做
GloVe 模型的是基于共现矩阵构建的
GloVe 认为共现矩阵可以通过一些统计信息得到词之间的关系,这些关系可以一定程度上表达词的含义
说明 TODO
GloVe 的基本思想:
其中
以前整理在 OneNote 上的,有时间在整理
实际 Word2Vec 已结有了一些对高频词的措施 > 高频词的处理
FastText 是从 Word2Vec 的 CBOW 模型演化而来的;
从网络的角度来看,两者的模型基本一致;区别仅在于两者的输入和目标函数不同;
基于层次 SoftMax 的 CBOW 模型
FastText 与 CBOW 的相同点:
不同点:
skip_window
内的上下文词;FastText 除了上下文词外,还包括这些词的字符级 N-gram 特征注意,字符级 N-gram 只限制在单个词内,以英文为例
// 源码中计算 n-grams 的声明,只计算单个词的字符级 n-gram
compute_ngrams(word, unsigned int min_n, unsigned int max_n);
# > https://github.com/vrasneur/pyfasttext#get-the-subwords
>>> model.args.get('minn'), model.args.get('maxn')
(2, 4)
# 调用源码的 Python 接口,源码上也会添加 '<' 和 '>'
>>> model.get_all_subwords('hello') # word + subwords from 2 to 4 characters
['hello', '', 'lo', 'lo>', 'o>']
>>> # model.get_all_subwords('hello world') # warning
值得一提的是,因为 FastText 使用了字符级的 N-gram 向量作为额外的特征,使其能够对未登录词也能输出相应的词向量;
具体来说,未登录词的词向量等于其 N-gram 向量的叠加
gensim.models.FastText
使用示例../codes/FastText
# gensim 示例
import gensim
import numpy as np
from gensim.test.utils import common_texts
from gensim.models.keyedvectors import FastTextKeyedVectors
from gensim.models._utils_any2vec import compute_ngrams, ft_hash
from gensim.models import FastText
# 构建 FastText 模型
sentences = [["Hello", "World", "!"], ["I", "am", "huay", "."]]
min_ngrams, max_ngrams = 2, 4 # ngrams 范围
model = FastText(sentences, size=5, min_count=1, min_n=min_ngrams, max_n=max_ngrams)
# 可以通过相同的方式获取每个单词以及任一个 n-gram 的向量
print(model.wv['hello'])
print(model.wv['
compute_ngrams
方法,gensim 提供了该方法的 Python 接口 sum_ngrams = 0
for s in sentences:
for w in s:
w = w.lower()
# from gensim.models._utils_any2vec import compute_ngrams
ret = compute_ngrams(w, min_ngrams, max_ngrams)
print(ret)
sum_ngrams += len(ret)
"""
['', '', '']
['', '', '']
['', '']
['', '']
['', '', '']
['', '', '']
['<.', '.>', '<.>']
"""
assert sum_ngrams == len(model.wv.vectors_ngrams)
print(sum_ngrams) # 57
print()
未登录词实际上是已知 n-grams 向量的叠加平均
# 因为 "a", "aa", "aaa" 中都只含有 "
只要未登录词能被已知的 n-grams 组合,就能得到该词的词向量
gensim.models.keyedvectors.FastTextKeyedVectors.word_vec(token)
的内部实现
word_unk = "aam"
ngrams = compute_ngrams(word_unk, min_ngrams, max_ngrams) # min_ngrams, max_ngrams = 2, 4
word_vec = np.zeros(model.vector_size, dtype=np.float32)
ngrams_found = 0
for ngram in ngrams:
ngram_hash = ft_hash(ngram) % model.bucket
if ngram_hash in model.wv.hash2index:
word_vec += model.wv.vectors_ngrams[model.wv.hash2index[ngram_hash]]
ngrams_found += 1
if word_vec.any(): #
word_vec = word_vec / max(1, ngrams_found)
else: # 如果一个 ngram 都没找到,gensim 会报错;个人认为把 0 向量传出来也可以
raise KeyError('all ngrams for word %s absent from model' % word_unk)
print(word_vec)
print(model.wv["aam"])
"""
[ 0.02210762 -0.10488641 0.05512805 0.09150169 0.00725085]
[ 0.02210762 -0.10488641 0.05512805 0.09150169 0.00725085]
"""
# 如果一个 ngram 都没找到,gensim 会报错
# 其实可以返回一个 0 向量的,它内部实际上是从一个 0 向量开始累加的;
# 但返回时做了一个判断——如果依然是 0 向量,则报错
# print(model.wv['z'])
"""
Traceback (most recent call last):
File "D:/OneDrive/workspace/github/DL-Notes-for-Interview/code/工具库 /gensim/FastText.py", line 53, in
print(model.wv['z'])
File "D:\program\work\Python\Anaconda3\envs\tf\lib\site-packages\gensim\models \keyedvectors.py", line 336, in __getitem__
return self.get_vector(entities)
File "D:\program\work\Python\Anaconda3\envs\tf\lib\site-packages\gensim\models \keyedvectors.py", line 454, in get_vector
return self.word_vec(word)
File "D:\program\work\Python\Anaconda3\envs\tf\lib\site-packages\gensim\models \keyedvectors.py", line 1989, in word_vec
raise KeyError('all ngrams for word %s absent from model' % word)
KeyError: 'all ngrams for word z absent from model'
"""
[1509] Character-level Convolutional Networks for Text Classification
Feature Columns | TensorFlow
embedding_size = n_categories ** 0.25
100~300
如果根据经验公式,是不需要这么大的,比如 200W 词表的词向量维度只需要
200W ** 0.25 ≈ 37