文章目录[隐藏]
赛题背景
在投资管理业务的研究过程中,研究人员需要阅读和分析各个券商机构制作的研究分析报告。他们需要从这些报告中提取出有价值的关键信息,包括研报分析的个股、当前评级、目标价和盈利预测数据等。这部分研究工作较为繁琐,会耗费研究人员大量的时间和精力。
比赛链接:http://ailab.aiwin.org.cn/competitions/87
基于上述分析,我们希望利用人工智能技术从研报PDF中自动抽取出关键信息并组织成结构化的数据进行分析。具体地,我们结合自然语言处理与计算机视觉相关技术,设计了一套研究报告(以下简称研报)关键信息要素抽取解决方案。该方案包含研报文件解析、研报类型分析和研报要素抽取等功能。
赛题任务
本赛题任务是利用机器学习、深度学习等方法训练一个预测模型,该模型主要针对各种各样的研报进行类型分析。赛题的难点在于不同机构、券商研报形式多样以及需要借助PDF的解析或者多模态的应用。
- 本赛题可以使用外部预训练模型(包括GPT类的LLM等)用于数据处理和建模过程,但不得直接使用ChatGPT类的应用作为产出最终分类结果的直接工具
- 请注意在研报数据上微调过程中不能引入其他数据,所有数据预处理只能在这些研报数据上。
赛题数据集
本赛题将10中类型的研报数据会划分为训练集、测试集。训练集用于模型架构设计、模型训练,在测试集上验证效果。以macro precision/recall/f1三个指标为验证标准(f1分数为排名依据)。
初赛提供研报首页的结果结果,包括header 和title。在初赛的基础上,复赛将只提供研报原文,并期望选手能充分解析和利用研报中文本、图形等多模态的信息用于优化模型。
初赛提供的数据集如下:
- 研报数据首页解析结果
- 研报数据对应类型标签
复赛提供的数据集如下:
- 完整研报原文
- 研报数据对应类型标签
赛题思路
赛题在初赛可以视为典型的文本分类任务,因此可以直接参考文本分类的流程进行。接下来我们将展示BERT思路比较关键的部分代码,完成代码见文末。
步骤1:初始化训练配置
classConfig():train_data ='data/train_dataset.npy'# 训练集predict_data ='data/eval_dataset.npy'# 测试集result_data_save ='result/submission.csv'# 预测结果device ='cpu'# 训练驱动
model_path ='hfl/chinese-roberta-wwm-ext'# 预训练模型model_save_path ='result/model'# 保存模型tokenizer =None# 预训练模型的tokenizer# 数据标签label_dict = {'晨会早报':0,'宏观研报':1,'策略研报':2,'行业研报':3,'公司研报':4,'基金研报':5,'债券研报':6,'金融工程':7,'其他研报':8,'个股研报':9}
num_labels = len(label_dict)# 标签数量max_seq_len =128# 最大句子长度test_size =0.15# 校验集大小random_seed =42# 随机种子batch_size =64# 训练数据批大小val_batch_size =8# 校验/预测批大小epochs =10# 训练次数learning_rate =1e-5# 学习率l2_weight_decay =0.05print_log =20# 日志打印步骤
config = Config()
config.device ='cuda'iftorch.cuda.is_available()else'cpu'
步骤2:自定义数据读取
# 自定义datasetclassMyDataset(Dataset):def__init__(self, config: Config, data: list, label: list = None):self.data = data self.tokenizer = config.tokenizer self.max_seq_len = config.max_seq_len self.len = len(data) self.label = label
def__getitem__(self, idx):text = self.data[idx]# tokenizerinputs = self.tokenizer.encode_plus(text, return_token_type_ids=True, return_attention_mask=True,
max_length=self.max_seq_len, padding='max_length', truncation=True)
# 打包预处理结果result = {'input_ids': torch.tensor(inputs['input_ids'], dtype=torch.long),'token_type_ids': torch.tensor(inputs['token_type_ids'], dtype=torch.long),'attention_mask': torch.tensor(inputs['attention_mask'], dtype=torch.long)}ifself.labelisnotNone:
result['labels'] = torch.tensor([self.label[idx]], dtype=torch.long)# 返回returnresult
def__len__(self):returnself.len
步骤3:加载预训练模型
tokenizer = AutoTokenizer.from_pretrained(config.model_path) model = AutoModelForSequenceClassification.from_pretrained(config.model_path, num_labels=config.num_labels)
config.tokenizer = tokenizer
步骤4:模型训练与验证
# 校验方法def val(model, val_dataloader: DataLoader): model.eval() total_acc, total_f1, total_loss, test_num_batch = 0., 0., 0., 0foriter_id, batchinenumerate(val_dataloader):# 转GPUbatch_cuda = {item: value.to(config.device)foritem, valueinbatch.items()}# 模型计算output = model(batch_cuda)# 获取结果loss = output[0] logits = torch.argmax(output[1], dim=1)
y_pred = [[i]foriinlogits.cpu().detach().numpy()]
y_true = batch_cuda['labels'].cpu().detach().numpy()# 计算指标acc = accuracy_score(y_true, y_pred)
f1 = f1_score(y_true, y_pred, average='weighted')
total_loss += loss.item()
total_acc += acc
total_f1 += f1
test_num_batch += 1
returntotal_loss/test_num_batch, total_acc/test_num_batch, total_f1/test_num_batch
def train(model, config: Config, train_dataloader: DataLoader, val_dataloader: DataLoader):# 模型写入GPUmodel.to(config.device)
# 获取BERT模型的所有可训练参数params = list(model.named_parameters())# 对除了bias和LayerNorm层的所有参数应用L2正则化no_decay = ['bias','LayerNorm.bias','LayerNorm.weight']
optimizer_grouped_parameters = [
{'params': [pforn, pinparamsifnot any(ndinnforndinno_decay)],'weight_decay': config.l2_weight_decay},
{'params': [pforn, pinparamsifany(ndinnforndinno_decay)],'weight_decay': 0.0}
]# 创建优化器并使用正则化更新模型参数opt = torch.optim.AdamW(optimizer_grouped_parameters, lr=config.learning_rate)# 梯度衰减scheduler = optim.lr_scheduler.CosineAnnealingLR(opt, len(train_dataloader) * config.epochs)
完整代码链接:
https://github.com/datawhalechina/competition-baseline/tree/master/competition/AIWIN2023
学习资料汇总:
https://coggle.club/blog/compete/aiwin2023
改进方法
在baseline中给出的基础的BERT分类思路,可以获得0.94左右的分析,还有很大的上分空间:
- 多折交叉验证
- BERT模型预训练
- 增加输入长度
- 修改预训练模型