AllenNLP源码学习——Embedding

上次阅读Vocabulary的代码时,我注意到,加入词典的token先用词频进行了排序,再加入词典的,那么它的顺序就和预训练词向量文件不一样了,于是阅读Embedding,了解了它是如何使用预训练词向量的。

Embedding.py文件中定义了一些类和函数,对于处理URL和hdf5文件相关的,我没有看。

训练配置文件

vocabulary有一项pretrained_files,用来构造词典
model的token_embedders的tokens有一项pretrained_file,用来获得预训练词向量,如果这一项是空,则权重以torch.nn.init.xavier_uniform_(self.weight)的方式初始化(Embedding类的__init__中可以看到这段代码)。

class EmbeddingsTextFile(Iterator[str])

这个类用来读取预训练词向量文件,txt或者只包含一个txt文件的压缩包,glove向量的文件就是这种形式的。
它是一个迭代器,一次读取一行。(比如,glove的形式是,一行是一个词和一串数字,中间一个空格隔开,这样一次读一个词)

构造参数

def __init__(self,
                 file_uri: str, 本地文件路径或URL
                 encoding: str = DEFAULT_ENCODING, 编码,默认utf-8
                 cache_dir: str = None) 如果是URL,则确定下载它到哪里

其他函数大概看一下名字就好了。

class Embedding(TokenEmbedder)

这个类用来把词变成一串数字,相比pytorch原始的embedding

def forward
inputs(LongTensor):index后的词,也即对embedding矩阵的索引(N*d,N对应词典中词的数量,顺序也和词典对应)
用来把index后的词进行词嵌入。

从配置文件构造Embedding

def from_params(cls, vocab: Vocabulary, params: Params)
这里传入词典,用来确定哪些词需要进行词嵌入(词典比Embedding先构造出来)
如果事先知道需要多少嵌入,或者没有使用词典确定哪些词需要词嵌入,那可以直接传入(配置文件中进行设置)num_embeddings设置这一项会忽略词汇表

如果设置了pretrained_file,即预训练词向量的路径,这时weight不为None,Embedding时使用这个weight;如果是None,如上文所说,

权重以torch.nn.init.xavier_uniform_(self.weight)的方式初始化(Embedding类的__init__中可以看到这段代码)

if pretrained_file:
        weight = _read_pretrained_embeddings_file(pretrained_file,
                                                  embedding_dim,
                                                  vocab,
                                                  vocab_namespace)
else:
        weight = None
return cls(......)  即构造函数__init__

def _read_pretrained_embeddings_file
file_uri: str, 预训练词向量文件路径,可以是URL/本地路径,文件类型可以是hdf5,txt文件以及txt文件的压缩包(支持多种格式的)。
embedding_dim: int, 使用多少维的词向量,如果它和预训练词向量文件中的不匹配,会打印提示错误
vocab: Vocabulary, 从词典中获得所有词
namespace: str = “tokens” 使用词典的哪个命名空间

这个函数中对文件格式进行了判断,”.h5”和“.hdf5”的文件进入_read_embeddings_from_hdf5函数,其他的进入_read_embeddings_from_text_file函数。

def _read_embeddings_from_text_file
参数与_read_pretrained_embeddings_file的一致。
读取过程:

  1. 从Vocabulary的词典中获得所有的词
  2. 逐行读取txt词向量文件,如果没什么问题,则加入embeddings(Dict),embeddings[token] = vector,key为词,vector为向量
  3. 得到包含所有词的embeddings(Dict)
  4. normal_(embeddings_mean,embeddings_std)的方式初始化一个embedding_matrix,尺寸为N*d,这样可以确保将向量加进来时,如果某一项缺失,则它的位置用一个随机值填充。
  5. 迭代embeddings(Dict)的每一个向量,逐行加入到embedding_matrix(FloatTensor)

组装代码构造Embedding

如果不使用配置文件,自己组装进行训练,也很简单,参考def from_params的处理过程,先调用_read_pretrained_embeddings_file,得到weight。加其他参数,构造Embedding类。

猜你喜欢

转载自blog.csdn.net/m0_38133212/article/details/88354781