初步预设使用transformers的form_pretrained解决问题,但通过查看数据集:
label text
2 2967 6758 339 2021 1854 3731 4109 3792 ...
可知训练集通过\t分割,并不符合loaddata()的格式要求。并且分析数据特征可知,文本长短从2到50000不等,而bert模型的最大输入长度为512,需要对数据进行截断操作(文本分类任务无需使用滑动窗口),剔除长度过长及过短数据,并对文本添加[SEP] 和[CLS],并再次覆写csv文件,实现csv_rewritting函数。
def csv_rewritting(text_dir, max_length=510):
# 读取csv文件数据
dataload = pd.read_csv(text_dir, sep='\t')
text_data = dataload['text']
label_data = dataload['label']
f_text_data = []
f_label_data = []
for per_text, per_label in tqdm(zip(text_data, label_data)):
# 统一数据类型
per_text = per_text.split(' ')
per_text = [int(per) for per in per_text]
per_label = int(per_label)
# 添加PAD
while len(per_text) % max_length != 0:
per_text.append(0)
# 截断数据,文本最大长度为max_length
per_label_len = len([per_text[i: i + max_length] for i in range(0, len(per_text), max_length)])
f_text_data.extend([2] + per_text[i: i + max_length] for i in range(0, len(per_text), max_length) + [102])
for _ in range(per_label_len):
f_label_data.append(per_label)
f_text_data = [' '.join(map(str, input_ids)) for input_ids in f_text_data]
dataframe = pd.DataFrame({'labels': f_label_data, 'input_ids': f_text_data})
dataframe.to_csv("./nlp_data/train.csv", index=False)
return per_label_len
重写后的数据集csv文件如下:
labels,input_ids
2,2 2967 6758 339 2021 1854 3731 4109 3792 4149 1519 ...
然而transformers的bert模型还需要传入attention_mask,故需在map一个datamake函数实现attention_mask的制作和数据集格式的转换。
def data_make(data, PAD_ID=0):
text_data = data['input_ids']
label_data = data['labels']
attention_mask = []
token_type_ids = []
f_text_data = []
f_label_data = []
# 制作数据集和mask
for text in text_data:
text = text.split(' ')
text = [int(word) for word in text]
mask = [1 if word == PAD_ID else 0 for word in text]
type_id = [0 for _ in text]
token_type_ids.append(type_id)
attention_mask.append(mask)
f_text_data.append(text)
for label in label_data:
label = int(label)
f_label_data.append(label)
data['input_ids'] = torch.tensor(f_text_data, device=device)
# data['token_type_ids'] = torch.tensor(token_type_ids, device=device)
data['attention_mask'] = torch.tensor(attention_mask, device=device)
data['labels'] = torch.tensor(f_label_data, device=device)
return data
至此,我们的数据准备工作全部完成,我们可以调用两个函数来获取最终的datasets。
接下来是模型的构建,若使用预训练模型,则直接调用:
tokenizer = AutoTokenizer.from_pretrained('bert-base-uncased')
model = AutoModelForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=label_class)
config = AutoConfig.from_pretrained('bert-base-uncased')
若使用transformer的encoder初始化训练(即bert) ,取[CLS]的输出经过线性层完成分类任务,则需要构建以下模型,其中BertConfig设置皆为论文"attention is all you need"中原始参数:
config = BertConfig(
vocab_size=8000,
hidden_size=512,
num_hidden_layers=6,
num_attenti