AIWIN2023 研报类型识别 baseline

赛题背景

在投资管理业务的研究过程中,研究人员需要阅读和分析各个券商机构制作的研究分析报告。他们需要从这些报告中提取出有价值的关键信息,包括研报分析的个股、当前评级、目标价和盈利预测数据等。这部分研究工作较为繁琐,会耗费研究人员大量的时间和精力。

比赛链接:http://ailab.aiwin.org.cn/competitions/87

基于上述分析,我们希望利用人工智能技术从研报PDF中自动抽取出关键信息并组织成结构化的数据进行分析。具体地,我们结合自然语言处理与计算机视觉相关技术,设计了一套研究报告(以下简称研报)关键信息要素抽取解决方案。该方案包含研报文件解析、研报类型分析和研报要素抽取等功能。

赛题任务

本赛题任务是利用机器学习、深度学习等方法训练一个预测模型,该模型主要针对各种各样的研报进行类型分析。赛题的难点在于不同机构、券商研报形式多样以及需要借助PDF的解析或者多模态的应用。

  • 本赛题可以使用外部预训练模型(包括GPT类的LLM等)用于数据处理和建模过程,但不得直接使用ChatGPT类的应用作为产出最终分类结果的直接工具
  • 请注意在研报数据上微调过程中不能引入其他数据,所有数据预处理只能在这些研报数据上。

赛题数据集

本赛题将10中类型的研报数据会划分为训练集、测试集。训练集用于模型架构设计、模型训练,在测试集上验证效果。以macro precision/recall/f1三个指标为验证标准(f1分数为排名依据)。

初赛提供研报首页的结果结果,包括header 和title。在初赛的基础上,复赛将只提供研报原文,并期望选手能充分解析和利用研报中文本、图形等多模态的信息用于优化模型。

初赛提供的数据集如下:

  • 研报数据首页解析结果
  • 研报数据对应类型标签

复赛提供的数据集如下:

  • 完整研报原文
  • 研报数据对应类型标签

赛题思路

赛题在初赛可以视为典型的文本分类任务,因此可以直接参考文本分类的流程进行。接下来我们将展示BERT思路比较关键的部分代码,完成代码见文末。

步骤1:初始化训练配置

class Config(): 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.05 print_log = 20 # 日志打印步骤


config = Config()
config.device = 'cuda' if torch.cuda.is_available() else 'cpu'


步骤2:自定义数据读取

# 自定义dataset class MyDataset(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] # tokenizer inputs = 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)} if self.label is not None:
result['labels'] = torch.tensor([self.label[idx]], dtype=torch.long) # 返回 return result


def __len__(self): return self.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., 0 for iter_id, batch in enumerate(val_dataloader): # 转GPU batch_cuda = {item: value.to(config.device) for item, value in batch.items()} # 模型计算 output = model(batch_cuda) # 获取结果 loss = output[0]
        logits = torch.argmax(output[1], dim=1)

y_pred = [[i] for i in logits.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


return total_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): # 模型写入GPU model.to(config.device)


# 获取BERT模型的所有可训练参数 params = list(model.named_parameters()) # 对除了bias和LayerNorm层的所有参数应用L2正则化 no_decay = ['bias', 'LayerNorm.bias', 'LayerNorm.weight']
optimizer_grouped_parameters = [
{'params': [p for n, p in params if not any(nd in n for nd in no_decay)], 'weight_decay': config.l2_weight_decay},
{'params': [p for n, p in params if any(nd in n for nd in no_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模型预训练
  • 增加输入长度
  • 修改预训练模型

【竞赛报名/项目咨询请加微信:mollywei007】

上一篇

上海浦东区有哪些国际学校?

下一篇

申请美国大学该选美国公立还是私立大学?

你也可能喜欢

  • 暂无相关文章!

评论已经被关闭。

插入图片
返回顶部