【HuggingFace Transformers】input_ids与inputs_embeds的区别

input_ids与inputs_embeds的区别

在使用 BERT 模型时,input_idsinputs_embeds 都是用于表示输入数据的,但它们有不同的用途和数据格式。以下是它们的区别和详细解释:

1. input_ids

定义input_idstoken的索引序列。

类型torch.Tensor,包含整数索引。

用途:直接将文本分词后得到的token索引作为模型的输入。

示例

# -*- coding: utf-8 -*-
# @time: 2024/7/11 18:58

import torch
from transformers import BertTokenizer, BertModel

# 加载预训练的 BERT 模型和分词器
model_name = 'google-bert/bert-base-chinese'
tokenizer = BertTokenizer.from_pretrained(model_name)
model = BertModel.from_pretrained(model_name)

# 示例文本
text = "我爱学习"
inputs = tokenizer(text, truncation=True, padding=True, return_tensors='pt')

input_ids = inputs['input_ids']
attention_mask = inputs["attention_mask"]
token_type_ids = inputs["token_type_ids"]

print(input_ids)  # torch.Size([1, 6])

with torch.no_grad():
    outputs = model(input_ids=input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids)

print(outputs.last_hidden_state)  # torch.Size([1, 6, 768])

输出

tensor([[ 101, 2769, 4263, 2110,  739,  102]])
tensor([[[ 0.0707,  0.1193, -0.1171,  ...,  0.8360,  0.1781, -0.3330],
         [ 0.3077,  0.0733, -0.0056,  ..., -0.9890, -0.0871, -0.1517],
         [ 1.0312, -0.3254, -1.0671,  ...,  0.1756,  0.2145, -0.1055],
         [ 0.1788, -0.1532, -0.9967,  ...,  0.4146,  0.1664, -0.4200],
         [ 0.8302, -0.5292, -0.7375,  ..., -0.1464,  0.2384,  0.2083],
         [ 0.3939,  0.1830, -0.2468,  ...,  0.8480,  0.1541,  0.1683]]])

2. inputs_embeds

定义inputs_embedstoken的嵌入表示。

类型torch.Tensor,包含浮点数的向量。

用途:当已经有了token的嵌入表示时,可以直接将这些嵌入作为模型的输入,而不是使用 input_ids 由模型内部的嵌入层进行转换。

示例

# -*- coding: utf-8 -*-
# @time: 2024/7/11 18:58

import torch
from transformers import BertTokenizer, BertModel

# 加载预训练的 BERT 模型和分词器
model_name = 'google-bert/bert-base-chinese'
tokenizer = BertTokenizer.from_pretrained(model_name)
model = BertModel.from_pretrained(model_name)

# 示例文本
text = "我爱学习"
inputs_embeds = torch.randn(1, 6, 768)  # 假设inputs_embeds是"我爱学习"的token嵌入表示: [batch_size, seq_length, embedding_dim]
attention_mask = torch.tensor([[1, 1, 1, 1, 1, 1]])
token_type_ids = torch.tensor([[0, 0, 0, 0, 0, 0]])

print(inputs_embeds)  # torch.Size([1, 6, 768])

# 获取输入的最终嵌入表示
with torch.no_grad():
    outputs = model(inputs_embeds=inputs_embeds, attention_mask=attention_mask, token_type_ids=token_type_ids)

print(outputs.last_hidden_state)  # torch.Size([1, 6, 768])

输出

tensor([[[-0.7986, -0.0758, -1.5470,  ..., -1.0122,  1.0138,  0.1089],
         [-0.8512, -0.2396, -0.1447,  ...,  1.5843,  1.1964, -0.2520],
         [-1.1290,  0.5671, -0.7088,  ...,  0.1192, -0.2578, -2.7265],
         [-0.4074, -0.7457,  0.3901,  ...,  0.1135,  1.2999,  1.0811],
         [-2.5027,  0.3060,  2.4674,  ...,  0.8905, -0.4032, -0.6385],
         [-1.3476, -1.0436,  2.7078,  ..., -0.8193,  0.5971,  0.2938]]])
tensor([[[-1.0209, -0.2582, -0.7404,  ...,  0.0584,  0.0331, -0.1135],
         [-0.9100,  0.4910,  0.1831,  ...,  0.7255, -0.0487, -0.0845],
         [-0.3630, -0.3341, -0.5843,  ...,  0.2195,  0.2563,  0.3027],
         [-0.5431, -0.4651, -0.4613,  ...,  0.3890, -0.6342,  0.0725],
         [-0.1561, -0.2302,  0.0517,  ..., -0.5924, -0.8542,  0.1668],
         [-0.4830, -0.8926,  0.2385,  ...,  0.5087,  0.1083,  0.0618]]])

3. 总结

  • input_idstoken的索引序列,用于标准的文本输入。
  • inputs_embedstoken的嵌入表示,用于自定义嵌入或高级处理场景。
  • 两者都可以作为 BERT 模型的输入,但不能同时使用
### 将机器学习模型转换为Hugging Face兼容格式 为了使现有的机器学习模型能够被集成至Hugging Face生态系统中并利用其提供的各种优势,如便捷的共享机制、丰富的工具链以及活跃的社区支持,通常需要遵循一系列特定的操作流程来完成这种转换。下面将以一个通用的方式描述这个过程。 #### 准备工作 确保已经安装了必要的库文件,特别是`transformers`和`datasets`这两个由Hugging Face维护的核心Python包。可以通过pip命令轻松获取它们: ```bash pip install transformers datasets ``` #### 加载预训练模型Tokenizer 如果目标是从头构建一个新的基于Transformer架构的模型,则可以从官方提供的众多预训练权重中挑选合适的起点;而对于其他类型的模型而言,可能更倾向于先实现基本的功能再考虑适配问题。这里假设已经有了一个可以工作的PyTorch版本的神经网络实例,并希望将其迁移到Hugging Face平台上。 ```python from transformers import AutoModelForSequenceClassification, BertTokenizerFast model_name_or_path = 'bert-base-uncased' # 或者指向本地路径 tokenizer = BertTokenizerFast.from_pretrained(model_name_or_path) pytorch_model = torch.load('path/to/your/model.pth') # 假设这是之前保存好的纯PyTorch模型参数 ``` #### 创建自定义类继承PreTrainedModel 为了让非Transformers系列的模型也能顺利融入进来,最直接的方法就是设计一个派生自`transformers.PreTrainedModel`的新类,在其中重写一些关键函数以便于管理内部状态和其他细节设置。这一步骤涉及到对原始代码结构做出适当调整,使其符合预期接口规范的要求。 ```python import torch.nn as nn from transformers.modeling_outputs import SequenceClassifierOutput from transformers.models.bert.configuration_bert import BertConfig class CustomBertForSequenceClassification(AutoModelForSequenceClassification): config_class = BertConfig def __init__(self, config): super().__init__(config) self.num_labels = config.num_labels self.custom_layer = nn.Linear(config.hidden_size, self.config.num_labels) self.init_weights() def forward( self, input_ids=None, attention_mask=None, token_type_ids=None, position_ids=None, head_mask=None, inputs_embeds=None, labels=None, output_attentions=None, output_hidden_states=None, return_dict=None, ): outputs = self.bert( input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids, position_ids=position_ids, head_mask=head_mask, inputs_embeds=inputs_embeds, output_attentions=output_attentions, output_hidden_states=output_hidden_states, return_dict=return_dict, ) sequence_output = outputs[0] logits = self.custom_layer(sequence_output[:, 0]) loss = None if labels is not None: if self.config.problem_type is None: if self.num_labels == 1: self.config.problem_type = "regression" elif self.num_labels > 1 and (labels.dtype == torch.long or labels.dtype == torch.int): self.config.problem_type = "single_label_classification" else: self.config.problem_type = "multi_label_classification" if self.config.problem_type == "regression": loss_fct = MSELoss() if self.num_labels == 1: loss = loss_fct(logits.squeeze(), labels.squeeze()) else: loss = loss_fct(logits, labels) elif self.config.problem_type == "single_label_classification": loss_fct = CrossEntropyLoss() loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1)) elif self.config.problem_type == "multi_label_classification": loss_fct = BCEWithLogitsLoss() loss = loss_fct(logits, labels) if not return_dict: output = (logits,) + outputs[2:] return ((loss,) + output) if loss is not None else output return SequenceClassifierOutput( loss=loss, logits=logits, hidden_states=outputs.hidden_states, attentions=outputs.attentions, ) ``` 上述例子展示了如何创建一个简单的二分类任务用的BERT变体[^3]。当然实际应用场景可能会更加复杂多变,因此具体的实现方式也要视情况而定。 #### 参数迁移 一旦拥有了新的模型框架之后,下一步就是要将原有的权重值复制过来。由于不同框架之间可能存在命名差异等问题,所以在执行此操作前最好仔细核对两者的变量名映射关系,从而保证整个过程中不会丢失任何重要信息。 ```python for name, param in pytorch_model.named_parameters(): if 'classifier' in name: continue # 如果原模型中有额外层则跳过这部分赋值 hf_param = getattr(custom_model.base_model, name.replace('.', '_')) with torch.no_grad(): hf_param.copy_(param.data) ``` 最后还需要注意一点,即某些情况下可能需要手动初始化那些新增加的部分(比如上面提到的例子中的`custom_layer`),这样才能让整体表现达到最佳效果。 #### 测试验证 经过以上几步处理后应该可以获得一份初步可用的结果了,不过在此之前建议先跑几个简单测试案例看看是否一切正常运行。只有当确认无误以后才能放心大胆地继续推进后续的工作计划。 #### 发布到Hub 成功完成后就可以借助`push_to_hub()`方法将自己的成果发布出去供他人使用啦! ```python custom_model.push_to_hub("my_custom_model", private=True) ``` 通过这种方式不仅可以方便快捷地其他研究人员交流经验心得,同时也促进了整个领域内知识和技术水平的整体提升[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CS_木成河

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值