Word2vec

Table of Contents

1. Word2vec

在 的例子中, 使用了 word2vec

普通的 rnn 对单词的索引使用 one-hot 编码, 所以每个 feature 变成一个大小为 N (N 为单词的个数) 的 vector. 这种做法有两个问题:

  1. vector 太大且没有必要, 因为这个 vector 绝大部分都是 0
  2. 这个 vector 无法反映不同单词之间的相似性, 例如, apple 和 orange 很相似 (都是水果, 都可以吃,…), 相似表示两者可以互相替代, 机器学习时学习到的参数 (权重) 可以共享等

因此, 我们会使用一种称为 word2vec 或者叫 word embedding 的技术代替 one-hot 编码

word2vec 其实就是一个反映各个单词特征的 matrix, 例如:

  king queen apple orange
human? 0.99 0.98 0.01 0.01
fruit? 0.01 0.02 0.99 0.98
food? 0.01 0.01 0.99 0.99
size        
       

以上面特征 (human?, fruit?…) 是我们事先选定的, 但这个 matrix 实际上可以通过训练让机器自己学习到.

word embedding 和 CNN 中的卷积很像: 都是反映了数据的特征, 都可以通过训练学习到

1.1. 训练过程

word2vec 获得的 embedding 是通过训练得到的, 它是一个简单的使用非监督学习的网络:

从训练样本中选取一些词做为输入, 让它去预测另一个词, hidden layer 的输出即为 embedding

以 `the quick brown fox jumps over the lazy dog` 为例

1.1.1. n-gram

输入为连续 n 个词, 预测标签是第 n+1 个词:

当 n=3 时:

the quick brown -> fox
quick brown fox -> jumps
brown fox jumps -> over
...

由于训练时使用 3 个词做为输入, 但用来获得 embedding 时只使用 1 个词做为输入, 所以网络的设计也许可以这样:

def get_training_model():
    input_1 = Input(N)
    input_2 = Input(N)
    input_3 = Input(N)
    embedding = Dense(EMBEDDING_SIZE)
    output_1 = embedding(input_1, name="output")
    output_2 = embedding(input_2)
    output_3 = embedding(input_3)
    output = Concatenate()[output_1, output_2, output_3]
    output = Dense(N)(output)
    output = Softmax()(output)
    return Model(input=[input_1, input_2, input_3], output=output)


def get_eval_model():
    model = get_training_model()
    model.load_weights("save.h5")
    return Model(input=model.inputs[0], output=model.get_layer("output").output)

1.1.2. cbow

用两边的词预测中间的词

the brown -> quick
quick fox -> brown
brown jumps -> fox
...
Backlinks

Attention (Attention > BERT > Train BERT): BERT 实际上类似于 word2vec, 随机 mask 的作法和 cbow 也有些类似, 但它用起来与 word2vec 并不完全相同:

1.1.3. skip-gram

使用中的词预测两边的词

quick -> the brown
brown -> quick fox
fox -> brown jumps
...
Backlinks

GNN (GNN > Embedding > DeepWalk): 2. 在 node 序列上使用 skip-gram 得到 embedding

1.2. gensim

gensim 工具可以帮助我们进行上面的训练过程

from gensim.models import word2vec
sentences = word2vec.Text8Corpus("../extra/xwz.txt")
vec = word2vec.Word2Vec(sentences, size=50, iter=5, min_count=0)
print(vec["我"])
print(vec["我"].shape)
print(vec.wv.vocab["我"].index)
print(vec.wv.vectors[5])
vocabulary = vec.wv.vocab.keys()
#print(vocabulary)
[ 2.5379989e-01 -7.9855943e-01  2.1004373e-01  1.4060766e-01
  1.5365046e+00 -1.2147485e-02 -1.1567525e+00  1.4223902e-01
 -1.1346768e+00  6.0506749e-01 -8.8734490e-01 -5.5807270e-02
  7.3605202e-02 -5.1732904e-01  8.1780031e-02  4.4866718e-02
 -3.8633597e-01 -5.1058096e-01 -5.1415718e-01 -8.0242729e-01
 -7.0677415e-02  2.1593498e-01  9.4420961e-05  1.5452372e-01
 -4.0667549e-01  2.0172779e-01 -3.7259430e-01 -8.9318126e-01
  1.7669131e-01 -6.7675710e-01  3.1780142e-01 -1.6200885e+00
  6.8548656e-01 -2.7231857e-01  7.0585549e-01  3.9321697e-01
 -8.2931936e-01  9.1785020e-01 -4.0526435e-01  1.2794651e-01
  3.5713235e-01  6.9550622e-01 -3.1667909e-01 -4.8001361e-01
  4.3599684e-02 -1.1073679e+00  9.8762310e-01 -4.1203447e-02
  7.0740056e-01  5.6313020e-01]
(50,)
5
[ 2.5379989e-01 -7.9855943e-01  2.1004373e-01  1.4060766e-01
  1.5365046e+00 -1.2147485e-02 -1.1567525e+00  1.4223902e-01
 -1.1346768e+00  6.0506749e-01 -8.8734490e-01 -5.5807270e-02
  7.3605202e-02 -5.1732904e-01  8.1780031e-02  4.4866718e-02
 -3.8633597e-01 -5.1058096e-01 -5.1415718e-01 -8.0242729e-01
 -7.0677415e-02  2.1593498e-01  9.4420961e-05  1.5452372e-01
 -4.0667549e-01  2.0172779e-01 -3.7259430e-01 -8.9318126e-01
  1.7669131e-01 -6.7675710e-01  3.1780142e-01 -1.6200885e+00
  6.8548656e-01 -2.7231857e-01  7.0585549e-01  3.9321697e-01
 -8.2931936e-01  9.1785020e-01 -4.0526435e-01  1.2794651e-01
  3.5713235e-01  6.9550622e-01 -3.1667909e-01 -4.8001361e-01
  4.3599684e-02 -1.1073679e+00  9.8762310e-01 -4.1203447e-02
  7.0740056e-01  5.6313020e-01]


/usr/lib/python3.6/site-packages/ipykernel_launcher.py:4: DeprecationWarning: Call to deprecated `__getitem__` (Method will be removed in 4.0.0, use self.wv.__getitem__() instead).
  after removing the cwd from sys.path.
/usr/lib/python3.6/site-packages/ipykernel_launcher.py:5: DeprecationWarning: Call to deprecated `__getitem__` (Method will be removed in 4.0.0, use self.wv.__getitem__() instead).
  """

more example about gensim and word2vec:

https://textminingonline.com/training-a-chinese-wikipedia-word2vec-model-by-gensim-and-jieba

1.3. pytorch.nn.Embedding

pytorch 的 nn.Embedding 是一个简单的 word2vec 的查找表, 可以支持 load 训练好的 word2vec weight:

self.encoder = torch.nn.Embedding(VOCABULARY_SIZE, FEATURE_SIZE)
self.encoder.weight.data.copy_(torch.from_numpy(vec.wv.vectors))
self.encoder.requires_grad = False

Backlinks

Attention (Attention > Transformer > InputEmbedding): InputEmbedding 通常是一个 word embedding (Word2vec), 与 rnn 不同的是, InputEmbedding 可以被并行处理.

GNN (GNN > Embedding): embedding 是用无监督的方法获得低维的向量表示, 例如 Word2vec

RNN (RNN > Word2vec): Word2vec

Author: [email protected]
Date: 2021-08-27 Fri 00:00
Last updated: 2022-01-30 Sun 12:50

知识共享许可协议