You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch中如何获取BERT预训练模型最后一层Transformer全输出而非CLS?

How to Get Full Last-Layer Transformer Outputs from BERT (Instead of Just CLS Token)

Hey there! Let's clear up how to grab the complete output of BERT's final Transformer layer in your PyTorch setup, since it looks like you've got a bit of confusion around how the Hugging Face models return their outputs.

First, let's fix a quick misconception in your code: when you use BertForSequenceClassification, the default forward pass only returns classification logits—not a tuple of two values like x1, x2. That means your current line x1, x2 = self.bert(sent_id, attention_mask=mask) would throw an error unless you're working with the base BertModel instead. Let's walk through the two best ways to get what you need.

Option 1: Use the Base BertModel with a Custom Classification Head

This is the most flexible approach, as it lets you fully control the model outputs:

from transformers import BertTokenizerFast, BertModel
import torch.nn as nn

class CustomBertClassifier(nn.Module):
    def __init__(self, num_labels):
        super().__init__()
        # Initialize the base BERT model (no built-in classification head)
        self.bert = BertModel.from_pretrained(
            "bert-base-uncased",
            output_attentions=False,
            output_hidden_states=False
        )
        # Add your own classification head (using CLS token output, or any token you want)
        self.classifier = nn.Linear(self.bert.config.hidden_size, num_labels)

    def forward(self, sent_id, mask):
        # Get the full output from BERT
        bert_outputs = self.bert(sent_id, attention_mask=mask)
        
        # `last_hidden_state` is exactly what you're after: all tokens' outputs from the final Transformer layer
        # Shape: (batch_size, sequence_length, hidden_size)
        full_last_layer_output = bert_outputs.last_hidden_state
        
        # If you still need the CLS token for classification (like the original model), grab the first token
        cls_token_output = full_last_layer_output[:, 0, :]
        logits = self.classifier(cls_token_output)
        
        # Return both the classification logits and the full layer output for your needs
        return logits, full_last_layer_output

With this setup, you can easily access the complete final layer output whenever you need it, while still keeping your classification logic intact.

Option 2: Modify an Existing BertForSequenceClassification Model

If you already have a BertForSequenceClassification instance and don't want to rebuild everything, you can access the underlying base BertModel directly via the model's bert attribute:

from transformers import BertTokenizerFast, BertForSequenceClassification

# Initialize your classification model as before
bert_classifier = BertForSequenceClassification.from_pretrained(
    "bert-base-uncased",
    num_labels=int(data['class'].nunique()),
    output_attentions=False,
    output_hidden_states=False
)

# Create a modified version of the model to return full layer outputs
class ModifiedBertClassifier(BertForSequenceClassification):
    def forward(self, sent_id, attention_mask=None):
        # First, get the full output from the underlying BertModel
        bert_base_outputs = self.bert(sent_id, attention_mask=attention_mask)
        full_last_layer_output = bert_base_outputs.last_hidden_state
        
        # Reuse the original classification logic (using the pooled CLS token)
        cls_pooled_output = bert_base_outputs.pooler_output
        logits = self.classifier(cls_pooled_output)
        
        # Return both logits and the full layer output
        return logits, full_last_layer_output

Quick Clarification on Your Original Code

You mentioned thinking x2 was the CLS token output—here's the breakdown if you were using the base BertModel with return_dict=False:

  • The first value would be last_hidden_state (all tokens' final outputs)
  • The second value would be pooler_output (CLS token run through BERT's built-in pooling layer, which is a linear layer + tanh)

But using return_dict=True (the default for newer Hugging Face versions) makes this way clearer, since you can access outputs via named attributes like outputs.last_hidden_state instead of unpacking tuples.


内容的提问来源于stack exchange,提问作者Alaa Grable

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:50:15