上次阅读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的一致。
读取过程:
- 从Vocabulary的词典中获得所有的词
- 逐行读取txt词向量文件,如果没什么问题,则加入embeddings(Dict),
embeddings[token] = vector
,key为词,vector为向量 - 得到包含所有词的embeddings(Dict)
- normal_(embeddings_mean,embeddings_std)的方式初始化一个embedding_matrix,尺寸为N*d,这样可以确保将向量加进来时,如果某一项缺失,则它的位置用一个随机值填充。
- 迭代embeddings(Dict)的每一个向量,逐行加入到embedding_matrix(FloatTensor)
组装代码构造Embedding
如果不使用配置文件,自己组装进行训练,也很简单,参考def from_params的处理过程,先调用_read_pretrained_embeddings_file,得到weight。加其他参数,构造Embedding类。