PyTorch + BERT 文本分类学习笔记:Dataset、DataLoader、Tokenizer、Sequential 与 BERT 输出

PyTorch + BERT 文本分类学习笔记:Dataset、DataLoader、Tokenizer、Sequential 与 BERT 输出
一、整体流程在 BERT 文本分类任务中整体流程通常是原始文本文件 - Dataset - DataLoader - Tokenizer - BERT - 分类层 - 输出类别分数比如酒店评论二分类任务评论文本 - 判断是好评还是差评二、Dataset 的作用Dataset负责管理数据核心作用是告诉 PyTorch 如何取出一条数据。通常需要继承from torch.utils.data import Dataset并实现两个方法class JdDataset(Dataset): def __init__(self, x, label): self.X x self.Y label def __getitem__(self, item): return self.X[item], self.Y[item] def __len__(self): return len(self.X)1.__init__用于初始化数据def __init__(self, x, label): self.X x self.Y label例如self.X [酒店很好, 房间很差] self.Y tensor([1, 0])2.__getitem__用于根据下标取出一条数据def __getitem__(self, item): return self.X[item], self.Y[item]当执行dataset[0]实际上会调用dataset.__getitem__(0)返回酒店很好, tensor(1)3.__len__用于返回数据集长度def __len__(self): return len(self.X)三、DataLoader 的作用DataLoader负责把Dataset中的数据按 batch 取出来。from torch.utils.data import DataLoader train_loader DataLoader( train_set, batch_size4, shuffleTrue )它主要负责按 batch 读取数据打乱训练数据自动遍历数据集把多条数据组合成一批支持多进程读取数据例如Dataset每次返回一条(酒店很好, tensor(1))DataLoader每次返回一批([酒店很好, 房间很差], tensor([1, 0]))常用参数batch_size表示每个 batch 中有多少条数据。shuffle表示是否打乱数据。训练集一般设置为True验证集一般设置为False。num_workers表示用几个子进程加载数据。drop_last表示最后一个 batch 不够batch_size时是否丢弃。四、Tokenizer 的作用BERT 不能直接处理中文字符串例如酒店很好它只能处理数字 tensor所以需要 tokenizer 把文本转成 BERT 可以识别的输入。self.tokenizer BertTokenizer.from_pretrained(bert_path)调用 tokenizerInput self.tokenizer( text, return_tensorspt, paddingmax_length, truncationTrue, max_length128 )这一步完成原始文本 - token 编号 - tensor五、Tokenizer 返回的内容Input是一个类似字典的对象通常包含Input.keys()输出dict_keys([input_ids, token_type_ids, attention_mask])所以可以这样取input_ids Input[input_ids] attention_mask Input[attention_mask] token_type_ids Input[token_type_ids]1. input_idsinput_ids是文本转换后的 token 编号。例如酒店很好可能被转换成[101, 2792, 2421, 2523, 1962, 102, 0, 0, ...]其中101通常表示[CLS]句子开始。102通常表示[SEP]句子结束。0通常表示[PAD]补齐。2. attention_maskattention_mask用来区分真实文本和 padding。[1, 1, 1, 1, 1, 1, 0, 0, ...]其中1表示真实 token。0表示 padding。3. token_type_idstoken_type_ids用来区分第一句话和第二句话。单句分类任务中一般全是0如果是句子对任务则第一句话通常为0第二句话通常为1。六、Tokenizer 参数解释return_tensorspt表示返回 PyTorch tensor。paddingmax_length表示把所有文本补齐到固定长度。truncationTrue表示文本太长时截断。max_length128表示最大长度为 128。如果输入两条文本[酒店很好, 房间很差]那么输出形状通常是input_ids.shape # torch.Size([2, 128])含义是2 条文本每条长度为 128七、为什么要.to(self.device)代码中常见写法input_ids Input[input_ids].to(self.device) attention_mask Input[attention_mask].to(self.device) token_type_ids Input[token_type_ids].to(self.device)作用是把数据移动到指定设备cpu或者cuda如果模型在 GPU 上输入数据也必须在 GPU 上否则会报错。八、调用 BERT 模型sequence_out, pooled_output self.bert( input_idsinput_ids, attention_maskattention_mask, token_type_idstoken_type_ids, return_dictFalse )这一步是把 tokenizer 生成的数字输入送进 BERT让 BERT 提取文本特征。九、sequence_out 和 pooled_output 的区别1. sequence_outsequence_out表示每个 token 的输出特征。形状通常是[batch_size, max_length, 768]例如[4, 128, 768]含义是4 条文本 每条文本 128 个 token 每个 token 用 768 维向量表示适合用于命名实体识别词性标注每个字或词都要分类的任务2. pooled_outputpooled_output表示整句话的输出特征。形状通常是[batch_size, 768]例如[4, 768]含义是4 条文本 每条文本用一个 768 维向量表示适合用于文本分类情感分类句子级分类任务在评论分类中通常使用out self.out(pooled_output)十、return_dictFalse 的作用当设置return_dictFalseBERT 会以元组形式返回结果sequence_out, pooled_output如果使用默认对象形式则可以这样写outputs self.bert(...) sequence_out outputs.last_hidden_state pooled_output outputs.pooler_output两种方式本质相同只是返回形式不同。十一、nn.Sequential 的作用nn.Sequential是 PyTorch 中的顺序容器用来把多个网络层按顺序组合起来。例如self.out nn.Sequential( nn.Linear(768, num_class) )这表示输入 - Linear(768, num_class) - 输出在 BERT 分类模型中BERT 输出的pooled_output维度是[batch_size, 768]而分类任务需要输出类别分数。如果是二分类num_class 2则需要把[batch_size, 768]转换成[batch_size, 2]所以使用nn.Linear(768, num_class)十二、为什么使用 Sequential如果只有一层self.out nn.Sequential( nn.Linear(768, num_class) )也可以简写成self.out nn.Linear(768, num_class)两者效果基本一样。但是Sequential方便以后扩展例如self.out nn.Sequential( nn.Dropout(0.1), nn.Linear(768, 256), nn.ReLU(), nn.Linear(256, num_class) )调用时仍然只需要out self.out(pooled_output)十三、完整模型流程总结def forward(self, text): input_ids, attention_mask, token_type_ids self.build_bert_input(text) sequence_out, pooled_output self.bert( input_idsinput_ids, attention_maskattention_mask, token_type_idstoken_type_ids, return_dictFalse ) out self.out(pooled_output) return out对应流程文本 - tokenizer - input_ids / attention_mask / token_type_ids - BERT - pooled_output - Sequential 分类层 - 分类结果十四、最终总结在 BERT 文本分类任务中Dataset负责告诉 PyTorch 如何取一条数据。DataLoader负责按 batch 读取数据。Tokenizer负责把文本转换成 BERT 可处理的数字 tensor。BERT负责提取文本特征。sequence_out表示每个 token 的特征。pooled_output表示整句话的特征。nn.Sequential负责组织分类层把 BERT 的输出转换成最终类别分数。整体可以记成Dataset 管数据 DataLoader 管批量 Tokenizer 管文本转数字 BERT 管提特征 Sequential/Linear 管分类