本文主要介绍一下 torch.nn.Embedding词嵌入过程。因为使用one-hot矩阵表示,在词汇表很长的情况会有很多0的 稀疏矩阵,所以使用稠密矩阵维度会降低很多,也能利用0的空间。这里讲这个的主要目的是给词嵌入过程一个清晰的变换过程,因为很多书讲这个的时候容易混淆概念,导致理解混乱。token我们一般只的是一个词,看代码或者一些说明的时候容易把句子和词表达混淆。
词向量,一行表示一个句子,每个数字代表在词汇表中的索引 shape 2 x 2 词汇表 shape 4 x 3 每行代表一个词,用三维数据表示 通过将索引替换后变成 2 x 2 x 3 |
下面给出一个比较具体的例子
1 样本数据
| 样本1 | 我爱你 |
| 样本2 | 你也爱我 |
2 构建词汇表
词汇表我们可以按照拼音简单排序(如果是用python 的sorted函数,那么使用的是unicode排序)。
[ ’ ‘,’爱‘,’你‘,’我‘、’也‘ ] 索引: 0, 1, 2, 3, 4 |
这里我在词汇表里面加了一个空字符。
3 样本转换成词矩阵
| 样本1 | 我爱你 | [3,1,2] |
| 样本2 | 你也爱我 | [2,4,1,3] |
4 标准化
我们假设允许句子最长为5,那么词矩阵可以在长度不足情况下添加0补齐
| 样本1 | 我爱你 | [3,1,2,0,0] |
| 样本2 | 你也爱我 | [2,4,1,3,0] |
这里搞成这个样子的原因是pytorch里面神经网络都是基于矩阵运算的。长度不一样估计不好处理,第2步' '对应0的用意是防止0造成意义干扰。如果不加会变成下面这样:
[ ’爱‘,’你‘,’我‘、’也‘ ] 索引: 0, 1, 2, 3 |
| 样本1 | 我爱你 | [2,0,1] |
| 样本2 | 你也爱我 | [1,3,0,2] |
填充0后会造成歧义,当然这里只是我发现的一个问题,想了这么一个处理办法。
| 样本1 | 我爱你 | [2,0,1,0,0] (我爱你爱爱) |
| 样本2 | 你也爱我 | [1,3,0,2,0] (你也爱我爱) |
5 确定词嵌入形状
这里词汇表长度是5,词嵌入矩阵input_size=5+1=6,假设我们想输出两个维度的词嵌入向量,我们可以设转换矩阵为(第一列是索引,实际上不需要存储,系数也是随便初始化的,方便演示):
| 0 | 0.1 | 0.9 |
| 1 | 0.2 | 0.6 |
| 2 | 0.5 | 0.5 |
| 3 | 0.6 | 0.3 |
| 4 | 0.8 | 0.2 |
| 5 | 0.9 | 0.1 |
6 查找嵌入表
这里以样本1 [3,1,2,0,0] 为例子
| 3 | [ 0.6,0.3 ] |
| 1 | [ 0.2,0.6 ] |
| 2 | [ 0.5,0.5 ] |
| 0 | [ 0.1,0.1 ] |
| 0 | [ 0.1,0.1 ] |
样本1 就变成了[ [ 0.6,0.3 ],[ 0.2,0.6 ],[ 0.5,0.5 ],[ 0.1,0.1 ],[ 0.1,0.1 ]]
样本2也同样的方式处理,输出为 2 x 5 x 2