分类模型可以输出其文本的embedding吗?LM模型可以输出其文本的embedding吗?答案:可以。
假设你已经用自己的数据fine-tuing好模型。
主要工具设备型号:
python3.6、torch1.7、transformer4.2、macOS、
文档huggingface:https://huggingface.co/transformers/model_doc/bert.html
那么怎么取?用哪个方式获取文本embedding呢?对不起,这个问题也在困扰着我,方法们各有千秋,也不知道如何选择了。那就选择最容易落地、能快速上线的——第一种方式:直接用 CLS Token 的 Embedding 作为句子表征。
BertModel这个类初始化的模型,输出中有pooler_out,可以作为文本的embedding。bert系列的其他类,没有这个输出选项。
例子:
from transformers import BertTokenizer, BertModel
import torch
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
model = BertModel.from_pretrained('bert-base-chinese')
inputs = tokenizer('我是一个好人', return_tensors='pt')
outputs = model(**inputs)
# last_hidden_states = outputs.last_hidden_state
# print('last_hidden_states:' ,last_hidden_states)
pooler_output = outputs.pooler_output
print('---pooler_output: ', pooler_output)
输出:768维,也就是768个数,太长了,这里简单看下效果即可,没有将embedding的值全部粘贴出来。
---pooler_output: tensor([[ 0.9990, 1.0000, 0.9927, 0.9723, 0.7621, 0.8510, -0.3171, -0.5332,
0.9878, -0.9926, 1.0000, 0.9983, -0.6630, -0.9952, 0.9997, -0.9995,
-0.8015, 0.9991, 0.9614, 0.0555, 0.9999, -1.0000, -0.9447, 0.0286,
-0.0421, 0.9650, 0.9261, -0.6247, -1.0000, 0.9954, 0.9358, 0.9990,
0.9796, -1.0000, -0.9987, 0.4368, -0.8486, 0.9951, -0.6203, -0.9828,
-0.9544, -0.9292, -0.2288, -0.9980, -0.9928, 0.6304, -1.0000, -1.0000,
.....
-0.9695, 1.0000, 0.2919, -0.9899, -0.9995, -0.9915, -0.9920, 0.9279]],
grad_fn=)
文档地址:https://huggingface.co/transformers/model_doc/bert.html#bertmodellmheadmodel
3.1文档(翻译)
bert模型transformer输出了未经处理的隐藏状态,在网络的结尾处没有任何特定的head(这个head可以理解为任务,比如分类、NER等)。
这个模型是一个PyTorch torch.nn.Module的子类(多gpu训练时,会用到Module,在之前的博客中有提到为什么用这个模块)。将它作为一个常规的PyTorch模块使用,开发中遇到问题,可以参考PyTorch文档。
参数:config (BertConfig
) –可以将模型的所有参数写到这个类中。初始化这个类时,并不能直接加载跟模型相关的参数,只能起到参数配置的作用,也就是你将所有参数写到一起,便于调参。如果想要加载模型的参数,去看from_pretrained()这个方法。
这个类所代表的模型做了self-attention的自编码和解码,网络结构就像Attention is all you need中描述的那样。
要充当解码器,需要将模型初始化,并将is_decoder参数设置为True。要在Seq2Seq模型中使用,则需要将is_decoder和add_cross_attention设置为True进行初始化;前向传递的输入中需要传入encoder_hidden_states。
forward:
forward(input_ids=None, attention_mask=None, token_type_ids=None, position_ids=None, head_mask=None, inputs_embeds=None, encoder_hidden_states=None, encoder_attention_mask=None, past_key_values=None, use_cache=None, output_attentions=None, output_hidden_states=None, return_dict=None)
torch.LongTensor
,形状: (batch_size, sequence_length)
意义:输入文本在词典中的映射id,又称tokens
torch.FloatTensor
,形状:(batch_size, sequence_length)
意义:避免对padding(填充,因为输入需要时定长,不够长度的,用0补齐)的tokens索引过于关注,所以这里用0和1做mask。0表示是padding产生的值;1表示原文,可有进行关注的词。
torch.LongTensor
,形状:(batch_size, sequence_length)
意义:用来区分一条样本中的第一部分和第二部分,同样用0和1来区分。0表示第一部分,1表示第二部分。常用在句子预测、问答场景下。
torch.LongTensor
,形状: (batch_size, sequence_length)
意义:在位置embedding中,每个输入序列tokens的位置索引。范围[0,config.max_position_embeddings - 1]。这个目前没有用到,没有研究。
Returns:
如果return_dict=True,则
返回一个BaseModelOutputWithPoolingAndCrossAttentions
或者返回一个元组,里面的元素依赖于你在configuration (BertConfig
)文件中的设置,比如:output_hidden_states=True时,才会在元组中返回hidden_states。
torch.FloatTensor
,形状: (batch_size, sequence_length, hidden_size)
意义:模型最后一层的hidden_state
torch.FloatTensor
,形状 (batch_size, hidden_size)
意义:最后一层由线性层和Tanh激活函数进一步处理过的序列的第一个token(分类token)的隐藏状态。在预训练过程中,线性层权值会根据你的任务进行参数更新。
3.2源码简单分析
1.768维度的embedding向量,不管是存储还是加载调用,费时间费空间,所以768维并非一个好的选择。在huggingface模型库中,发现了一个蒸馏模型:"uer/chinese_roberta_L-2_H-128",2层,128维度的蒸馏模型,线上调用时间20ms,比12层,768维度的300ms节省了10多倍时间。空间上节省6倍。