如何使用AllenNLP框架嵌入标签得到与文本嵌入同维度的张量?
AllenNLP实现标签嵌入(与文本嵌入维度对齐)
核心逻辑和用TextFieldEmbedder嵌入TextFieldTensors没有本质区别,只要保证标签嵌入层的输出维度和文本嵌入层输出维度完全一致,即可直接对接后续计算逻辑,具体实现步骤如下:
1. 先获取文本嵌入的输出维度
不需要硬编码维度值,直接调用TextFieldEmbedder自带的方法就能拿到准确的输出维度:
# your_text_field_embedder是你项目里已经初始化好的文本嵌入实例 text_embed_dim = your_text_field_embedder.get_output_dim()
如果是基于BERT等预训练模型搭建的TextFieldEmbedder,这个值通常和预训练模型的隐层维度一致,比如base版BERT对应768,large版对应1024。
2. 初始化标签嵌入层
直接用AllenNLP官方提供的Embedding模块即可,这个模块原生支持和全局Vocab对接,不需要手动维护标签到id的映射关系:
- 先确认你的标签存在词汇表的哪个命名空间:普通分类任务的标签默认存在
labels命名空间,序列标注类任务的标签可能存在自定义命名空间(比如ner_tags) - 初始化时把嵌入维度直接设置为上一步拿到的
text_embed_dim,就能保证输出维度和文本嵌入对齐:
from allennlp.modules import Embedding # vocab是模型全局共用的词汇表实例 label_embedder = Embedding( num_embeddings=vocab.get_vocab_size(namespace="labels"), embedding_dim=text_embed_dim, # 默认trainable=True,标签嵌入会随模型训练更新;如果需要固定嵌入,改为trainable=False即可 )
3. 执行标签嵌入计算
整个流程和TextFieldEmbedder处理文本张量的逻辑完全一致:
- 先把原始标签值通过词汇表转成id张量,转换逻辑和文本转token id的逻辑完全相同,可以用
vocab.get_token_index()批量转换,也可以复用TextField的索引流程给标签做预处理 - 把转换好的标签id张量传入初始化完成的
label_embedder,得到的输出就是和文本嵌入维度一致的标签张量
示例代码:
# batch_labels为一个批次的标签id张量 # 单分类场景下shape为(batch_size,),输出label_embeddings的shape为(batch_size, text_embed_dim) # 序列标注场景下shape为(batch_size, seq_len),输出label_embeddings的shape为(batch_size, seq_len, text_embed_dim) label_embeddings = label_embedder(batch_labels)
补充说明
- 如果你需要标签嵌入和文本嵌入处于完全相同的语义空间,不需要单独训练标签嵌入层,可以直接复用现有
TextFieldEmbedder实例处理标签:把每个标签的文本内容按照和输入文本完全一致的分词、索引规则构造成标准TextFieldTensors格式,直接喂给已经初始化好的文本嵌入实例,得到的嵌入自然和输入文本嵌入维度对齐、语义空间一致,适合做标签和文本的语义匹配类任务,效果通常好于单独训练的标签嵌入层。 - 如果是多标签场景,拿到单个标签的嵌入之后,对同一样本对应的所有标签嵌入做平均池化或者最大池化,就能得到整个标签集合的固定维度嵌入,依然和文本嵌入维度对齐。
- 如果需要标签嵌入和文本嵌入共享权重,可以直接提取
TextFieldEmbedder内部的token嵌入层权重来初始化标签嵌入层,不需要从头开始训练。
内容的提问来源于stack exchange,提问作者tzshyr
相关产品推荐
相关产品推荐

