细节简述
Bert官网已经有训练好的Bert模型,即下载可以使用,在训练模型时,需要保证不对Bert模型参数进行修改。
Bert模型中下载会发现几个文件:
Bert_config.json是存储了Bert的相关模型参数,在后面训练会用到
Bert_model_ckpt等文件是Google保存的一份权重参数
vocat.txt存储的语料库
from transformers import BertModel, BertTokenizer, BertConfig
tokenizer = BertTokenizer.from_pretrained('./model/dl_model/bert')
model = BertModel.from_pretrained('./model/dl_model/bert',)
在BERT模型及其衍生体中,输入文本首先经过一个分词处理流程,其中文本被细分为单词或子单词(subwords),每个分词随后映射到一个唯一的整数标识符。这些标识符组成了所谓的input_ids数组,其代表文本的数字化形式。
# 分词
tokenized_text = tokenizer.tokenize(text)
# 转换为ID索引
indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text)
input_ids
为了适应模型处理的需要,input_ids的长度被规范化为一个固定的值。在这个规范化过程中,长度超出预定值的输入会被截断,而短于此长度的输入则通过添加特定的填充标记([PAD],通常对应的整数标识符为0)来补齐。这种处理机制确保了模型输入的一致性,允许模型批量处理不同长度的文本数据。
attention_mask
与input_ids并行的,attention_mask数组标识了模型应当"关注"的输入部分。具体而言,attention_mask对于实际文本内容的位置赋值为1,而对于填充部分则赋值为0。这使得模型能够区分原始文本与为了长度规范化而添加的填充内容,从而仅对有意义的文本部分进行分析。attention_mask在处理可变长文本输入时尤其关键,因为它直接指导模型聚焦于重要的信息,忽视那些无关紧要的填充部分。
inputs = self.tokenizer(
self.sequences[idx],
padding='max_length',
truncation=True,
return_tensors='pt',
max_length=128
)
· self.sequences[idx]: 从序列列表中获取第 idx 个文本序列。
· self.tokenizer(...): 使用 BERT 分词器对文本进行处理。
- padding='max_length': 将序列填充到最大长度(128),以确保所有输入具有相同的长度。
- truncation=True: 如果文本长度超过最大长度,进行截断。
- return_tensors='pt': 返回 PyTorch 格式的张量。
- max_length=128: 设置最大序列长度为 128。
input_ids = inputs['input_ids'].squeeze(0) # 去掉多余的维度
· inputs['input_ids']: 获取输入的 token IDs。
· .squeeze(0): 去掉第一维(batch size 为 1 时的多余维度),使得 input_ids 的形状为 (128,)
attention_mask = inputs['attention_mask'].squeeze(0)
· inputs['attention_mask']: 获取注意力掩码(指示哪些 token 是填充的)。
· .squeeze(0): 去掉多余的维度,得到的形状同样为 (128,)。
label = torch.tensor(self.labels[idx], dtype=torch.long) # 转换为 Long 类型
· self.labels[idx]: 从标签列表中获取第 idx 个标签。
· torch.tensor(..., dtype=torch.long): 将标签转换为 PyTorch 的 Long 类型张量,以便与模型输出匹配。
return input_ids, attention_mask, label
返回三个元素:输入 IDs、注意力掩码和标签,这些将用于模型训练或推理。
self.bert(...) 返回的 bert_output 包含两个主要部分:
- last_hidden_state:每个 token 的表示,通常用于下游任务(如分类或命名实体识别)。
- pooler_output:通常用于句子级别的任务,表示 [CLS] token 的向量。
对于文本情感分类采用哪个呢?既是句子级别任务,又是分类问题
代码汇总
class SimpleModel(nn.Module):
def __init__(self, output_dim, dropout_prob=0.2):
super(SimpleModel, self).__init__()
# 从本地加载加载 BERT 模型
self.bert = BertModel.from_pretrained('./Bert_pretrain')
.....
def forward(self, input_ids, attention_mask):
with torch.no_grad():
# 获取 BERT 输出
bertOutput = self.bert(input_ids=input_ids, attention_mask=attention_mask)
seq_out,pooled_out = bertOutput[0],bertOutput[1]
......
sequences = df['input_sequence'].tolist()
labels = df['is_anomaly'].tolist()
# 划分数据集
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
dataset = CustomDataset(sequences, labels, tokenizer)
# 自定义数据集类
class CustomDataset(Dataset):
def __init__(self, sequences, labels, tokenizer):
self.sequences = sequences
self.labels = labels
self.tokenizer = tokenizer
def __len__(self):
return len(self.sequences)
def __getitem__(self, idx):
inputs = self.tokenizer(
self.sequences[idx],
padding='max_length',
truncation=True,
return_tensors='pt',
max_length=128
)
input_ids = inputs['input_ids'].squeeze(0) # 去掉多余的维度
attention_mask = inputs['attention_mask'].squeeze(0)
label = torch.tensor(self.labels[idx], dtype=torch.long) # 转换为 Long 类型
return input_ids, attention_mask, label