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

Python基于BERT的文本分类代码运行时进度条卡在0%问题求解

BERT文本分类代码卡住问题修复

核心错误原因

  • 数据集读取逻辑错误:BERTDataset类的__getitem__方法调用分词器时传入了全量文本集合,而非单条样本文本,导致每次取样本都要处理数万条数据,直接卡住进度条。
  • 模型前向传播变量名错误:前向传播输出变量命名为x,但后续计算损失和指标时误用了未定义的outputs变量,会触发运行时异常。
  • 分词参数不匹配:bert-base-uncased为全小写预训练模型,do_lower_case设为False会导致分词效果偏差。

修复后的代码

## Import Packages
import tez
import torch
import torch.nn as nn
import transformers
from transformers import AdamW, get_linear_schedule_with_warmup
from sklearn import metrics
import pandas as pd

## Create a data loader using a class named BERTDataset 
class BERTDataset:
    def __init__(self, texts, targets, max_len = 64):
        self.texts = texts
        self.targets = targets
        self.tokenizer = transformers.BertTokenizer.from_pretrained(
            "bert-base-uncased", #model name
            do_lower_case = True # 修正:uncased模型需开启小写转换
        )
        self.max_len = max_len
        
    # length function
    def __len__(self):
        return len(self.texts)
    
    def __getitem__(self, idx):
        text = str(self.texts[idx])
        # 修正:传入单条文本text而非全量texts
        inputs = self.tokenizer.encode_plus(
        text,
        None,
        add_special_tokens = True,
        max_length = self.max_len,
        padding = "max_length",
        truncation = True
        )
        resp = {
            "ids": torch.tensor(inputs["input_ids"], dtype = torch.long),
            "mask": torch.tensor(inputs["attention_mask"], dtype = torch.long),
            "token_type_ids": torch.tensor(inputs["token_type_ids"], dtype = torch.long),
            "targets": torch.tensor(self.targets[idx], dtype = torch.float),
            
            ## for multiclass classification, convert change dtype from torch.float to torch.long
            #"targets": torch.tensor(self.targets[idx], dtype = torch.long),
        }
        return resp

## Build the model
class TextModel(tez.Model):
    def __init__(self, num_classes, num_train_steps):
        
        super().__init__()
        self.bert = transformers.BertModel.from_pretrained(
            "bert-base-uncased", return_dict = False
        )
        self.bert_drop = nn.Dropout(0.3)
        self.out = nn.Linear(768, num_classes) # num_classes is 1 or > 1 if it is binary multiclass classification respectively
        self.num_train_steps = num_train_steps
        
        
    # optimizer
    def fetch_optimizer(self):
        opt = AdamW(self.parameters(), lr = 3e-5) # 修正:BERT微调推荐学习率区间2e-5~5e-5
        return opt
    
    # scheduler
    def fetch_scheduler(self):
        sch = get_linear_schedule_with_warmup(
            self.optimizer, num_warmup_steps = 0, num_training_steps = self.num_train_steps        
        )
        return sch
    
    # loss
    def loss(self, outputs, targets):
        return nn.BCEWithLogitsLoss()(outputs, targets.view(-1, 1))
    
        ## include the next line if you have multiclass classification 
        # return nn.CrossEntropyLoss()(outputs, targets)
    
    # calculate accuracy
    def monitor_metrics(self, outputs, targets):
        outputs = torch.sigmoid(outputs).cpu().detach().numpy() >= 0.5
        
       
        targets = targets.cpu().detach().numpy()
        return {"accuracy": metrics.accuracy_score(targets, outputs)}
    
    # forward function
    def forward(self, ids, mask, token_type_ids, targets = None):
        _, x = self.bert(ids, attention_mask = mask, token_type_ids = token_type_ids)
        x = self.bert_drop(x)
        x = self.out(x)
        if targets is not None:
            # 修正:使用正确的输出变量x而非未定义的outputs
            loss = self.loss(x, targets)
            met = self.monitor_metrics(x, targets)
            return x, loss, met
        return x, 0, {} # if there is no target, return 0        


## Read Dataset
def train_model(fold):
    df = pd.read_csv("imdb_folds.csv") # read file
    df_train = df[df.kfold != fold].reset_index(drop=True)
    df_valid = df[df.kfold == fold].reset_index(drop=True)
    
    train_dataset = BERTDataset(df_train.review.values, df_train.sentiment.values)
    valid_dataset = BERTDataset(df_valid.review.values, df_valid.sentiment.values)
    
    # n_train_steps = int(len(df_train) / TRAIN_BS * EPOCHS)
    n_train_steps = int(len(df_train) / 32 * 10)
    model = TextModel(num_classes = 1, num_train_steps = n_train_steps)
    
    es = tez.callbacks.EarlyStopping(monitor = "valid_loss", patience = 3, model_path = "model.bin")
    # 无cuda设备可将device改为"cpu"
    model.fit(
        train_dataset, 
        valid_dataset = valid_dataset, 
        device = "cuda", 
        epochs = 10, 
        train_bs = 32,
        callbacks = [es],
    )
    
    
if __name__=="__main__":
    train_model(fold = 0)

补充说明

如果本地无CUDA环境,将model.fit中的device参数改为"cpu"即可正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 18:24:03