在金融市场中,动态知识图谱(Dynamic Knowledge Graphs,DKGs)是一种表达对象之间随时间变化的多种关系的流行结构。它们可以有效地表示从复杂的非结构化数据源(如文本或图像)中提取的信息。在金融应用中,基于从金融新闻文章中获取的信息,DKGs 可用于检测战略性主题投资的趋势。
本文探讨了大型语言模型(Large Language Models,LLMs)作为动态知识图谱生成器的特性,提出了一种新的开源微调 LLM——集成上下文知识图谱生成器(Integrated Contextual Knowledge Graph Generator,ICKG)。我们利用 ICKG 从金融新闻文章语料库中生成了一个新的开源 DKG,称为 FinDKG,并提出了一种基于注意力机制的图神经网络(Graph Neural Network,GNN)架构来分析它,称为 KGTransformer。
我们在基准数据集和 FinDKG 上测试了所提出模型的性能,展示了其在链接预测任务上的优越性能。此外,我们评估了 KGTransformer 在 FinDKG 上用于主题投资的表现,显示其可以超越现有的主题 ETF。
估计从观测数据中得到的 Gt 的模型的任务称为动态知识图谱学习。这通常涉及到图神经网络(Graph Neural Network,GNN)的训练,旨在同时建模 KG 的结构和时间动态。
在实际应用中,如金融领域,实体和关系可以进一步分组,通常称为元实体(meta-entities)。例如,考虑实体 "Jeff Bezos"(类型为 "Person")和实体 "Amazon"(类型为 "Company")之间的关系 "Founder Of"(可以视为 "Business Action" 类型)。
本文的主要贡献如下:
1. KGTransformer:我们提出了一种基于注意力机制的 GNN 架构,用于动态知识图谱学习,包含元实体信息,称为 KGTransformer。该模型结合了现有的 GAT(Graph Attention Networks)和 EvoKG 架构。
2. ICKG 模型:我们开发了一种用于动态知识图谱生成的开源 LLM,称为集成上下文知识图谱生成器(ICKG)。
3. FinDKG 数据集:我们利用 ICKG 从金融新闻文章中创建了一个开源的动态知识图谱,称为 FinDKG。我们将其用于主题投资,特别是捕捉人工智能(Artificial Intelligence,AI)趋势。
图表示学习(Graph Representation Learning)旨在从图结构中提取低维的潜在空间表示,以改进下游任务的性能。这些方法在节点分类、边预测和图分类等任务中表现出显著的能力。
金融系统通常具有复杂且动态演化的关系,这些关系可以用 DKG 表示,用于欺诈交易识别、股票收益预测、股票关联发现等应用。然而,金融网络的异质性和动态性对现有的静态 GNN 模型提出了挑战。
大型语言模型(LLMs)在金融任务中得到了广泛应用,如金融情感分析、基于新闻标题的股票市场预测等。然而,LLMs 在动态知识图谱中的应用在文献中仍然有限。
图1:经过微调的知识边缘图构建的ICKG LLM流程图,概述了培训方法。
大型语言模型(LLMs) 在自然语言处理领域取得了巨大成功,但其在知识图谱生成中的应用仍然有限。本文提出了ICKG,一种基于 LLM 的知识图谱生成器,通过监督微调(Supervised Fine-tuning) 来适应金融领域的特殊需求。
1. 数据集构建:从开源的金融新闻文章中收集 5,000 篇文章,利用 GPT-4 API 生成知识图谱提取的训练数据。
2. 数据质量过滤:对生成的知识图谱数据进行质量过滤,确保符合预期的格式和内容。
3. 模型微调:使用收集的高质量数据,对开源的 Mistral 7B 模型进行微调,得到最终的 ICKG 模型。
以下是用于训练 ICKG 模型的代码示例:
# 导入必要的库
from transformers import AutoTokenizer, AutoModelForCausalLM
# 加载预训练的 Mistral 7B 模型和 tokenizer
tokenizer = AutoTokenizer.from_pretrained('mistral-7b')
model = AutoModelForCausalLM.from_pretrained('mistral-7b')
# 定义知识图谱提取的提示模板
prompt_template = """
请从以下金融新闻文章中提取实体及其关系,生成五元组 (s, r, o, t, c),其中 s 和 o 是实体,r 是关系,t 是时间戳,c 是实体类别。
文章内容:
{article_content}
"""
# 定义微调函数
def fine_tune_ickg(model, tokenizer, articles):
# 遍历文章进行微调
for article in articles:
......
# 优化器步骤
optimizer.step()
optimizer.zero_grad()
return model
我们收集了大约 40 万篇来自《华尔街日报》的金融新闻文章,时间跨度从 1999 年到 2023 年。我们使用 ICKG 从每篇文章中提取五元组,关系类型限制在 15 种,与金融新闻相关(如表 1 所示)。实体被标记为特定类别(如表 2 所示)。
关系类型示例:
实体类别示例:
通过对 FinDKG 进行可视化,我们可以看到特定时间段内最相关的实体和它们之间的关系。例如,在 2023 年 1 月,图谱中显示了美国和中国之间的地缘政治紧张关系,以及高通胀对全球经济的影响。
KGTransformer 是一种基于注意力机制的图神经网络(GNN)模型,专为动态知识图谱的学习而设计。它结合了图注意力网络(Graph Attention Networks, GAT) 和异构图 Transformer(Heterogeneous Graph Transformer, HGT) 的特点。
在金融知识图谱中,实体和关系可以进一步分类,这些类别称为元实体(Meta-entities)。注意力得分的计算考虑了元实体信息,引入了一个映射函数,将每个实体映射到一个实体类型。KGTransformer 通过引入元实体的信息,能够更好地捕捉实体之间的复杂关系。
引入元实体后,注意力权重的计算考虑了实体的类别:
图2:FinDKG支持ickg的知识图生成管道示意图,表示将文本新闻文章转换为结构化的动态知识图五元
表1:FinDKG数据集中的关系类型。
表2:FinDKG数据集中的实体类别。
图3:截至2023年1月1日FinDKG最具影响力实体的子图。实体按类别着色。
以下是用于训练 KGTransformer 模型的代码示例:
# 导入必要的库
import torch
import os
import sys
import pprint
from copy import deepcopy
from functools import partial
from collections import defaultdict
from datetime import datetime
# 获取当前脚本的绝对路径
current_path = os.path.abspath(__file__)
parent_parent_path = os.path.dirname(os.path.dirname(current_path))
sys.path.append(parent_parent_path)
# 导入 DKG 库
import DKG
from DKG.utils.log_utils import add_logger_file_handler, get_log_root_path, logger
from DKG.utils.model_utils import get_embedding
from DKG.utils.train_utils import setup_cuda, EarlyStopping
from DKG.model import (
DynamicGraphModel, DKG_DEFAULT_CONFIG, EmbeddingUpdater,
Combiner, EdgeModel, InterEventTimeModel, MultiAspectEmbedding
)
from DKG.model.time_interval_transform import TimeIntervalTransform
from DKG.train import compute_loss
from DKG.eval import evaluate
# 配置模型参数
args = deepcopy(DKG_DEFAULT_CONFIG)
args.seed = 41
args.cuda = args.gpu >= 0 and torch.cuda.is_available()
args.device = torch.device("cuda:{}".format(args.gpu) if args.cuda else "cpu")
args.graph = "FinDKG"
args.version = "KGTransformer"
......
# 设置随机种子
import numpy as np
np.random.seed(args.seed)
torch.manual_seed(args.seed)
if args.cuda:
torch.cuda.manual_seed_all(args.seed)
# 加载数据
from torch.utils.data import DataLoader
G = DKG.data.load_temporal_knowledge_graph(args.graph, data_root='./data')
collate_fn = partial(DKG.utils.collate_fn, G=G)
......
# 构建模型
embedding_updater = EmbeddingUpdater(
num_nodes=G.number_of_nodes(),
static_entity_embed_dim=args.static_entity_embed_dim,
structural_dynamic_entity_embed_dim=args.structural_dynamic_entity_embed_dim,
temporal_dynamic_entity_embed_dim=args.temporal_dynamic_entity_embed_dim,
node_latest_event_time=torch.zeros(
G.number_of_nodes(), G.number_of_nodes() + 1, 2, dtype=torch.float32
),
num_relations=G.num_relations,
rel_embed_dim=args.rel_embed_dim,
num_node_types=G.num_node_types,
num_heads=args.num_attn_heads,
......
combiner = Combiner(
......
).to(args.device)
edge_model = EdgeModel(
num_nodes=G.number_of_nodes(),
num_relations=G.num_relations,
rel_embed_dim=args.rel_embed_dim,
combiner=combiner,
dropout=args.dropout
).to(args.device)
inter_event_time_model = InterEventTimeModel(
dynamic_entity_embed_dim=args.temporal_dynamic_entity_embed_dim,
static_entity_embed_dim=args.static_entity_embed_dim,
num_rels=G.num_relations,
......
inter_event_time_mode=args.inter_event_time_mode,
dropout=args.dropout
)
model = DynamicGraphModel(
embedding_updater=embedding_updater,
......
node_latest_event_time=torch.zeros(
G.number_of_nodes(), G.number_of_nodes() + 1, 2, dtype=torch.float32
)
).to(args.device)
# 初始化嵌入
......
# 设置优化器
params = list(model.parameters()) + [
......
time_optimizer = torch.optim.AdamW(params, lr=args.lr, weight_decay=args.weight_decay)
# 训练模型
for epoch in range(args.epochs):
model.train()
for batch_i, (prior_G, batch_G, cumul_G, batch_times) in enumerate(train_data_loader):
# 计算损失
batch_train_loss_dict = compute_loss(
model, args.optimize, batch_G, static_entity_embeds,
init_dynamic_entity_embeds, init_dynamic_relation_embeds, args
)
# 反向传播和优化
loss = sum(batch_train_loss_dict.values())
loss.backward()
edge_optimizer.step()
edge_optimizer.zero_grad()
time_optimizer.step()
time_optimizer.zero_grad()
为了在动态环境中使用 KGTransformer,我们需要将时间信息引入模型。我们使用一个循环神经网络(Recurrent Neural Network,RNN)来建模嵌入的时间演化:
class TemporalKGTransformer(nn.Module):
def __init__(self, ...):
super(TemporalKGTransformer, self).__init__()
......
def forward(self, x, edge_index, edge_type, node_type, h_prev):
x = self.kg_transformer(x, edge_index, edge_type, node_type)
h_t = self.rnn(x, h_prev)
return h_t
为了捕捉知识图谱随时间的变化,KGTransformer 使用了循环神经网络(Recurrent Neural Network, RNN)来更新实体和关系的时间嵌入(Temporal Embeddings)和结构嵌入(Structural Embeddings)。
为了对动态知识图谱进行学习,定义了事件发生的概率模型:
为了训练模型,定义了包含时间和结构信息的损失函数:
我们在多个真实世界的知识图谱数据集上评估了 KGTransformer 的性能,包括 YAGO、WIKI、ICEWS14 和我们构建的 FinDKG。KGTransformer 在包含元实体信息的数据集上表现出色,尤其是在 FinDKG 上,与其他基线模型相比,性能提升了约 10%。
在基准数据集上,KGTransformer 在链接预测任务上表现优异,特别是在包含实体类型信息的 FinDKG 数据集上,KGTransformer 的性能显著超过了其他模型。
# 定义早停机制
stopper = EarlyStopping(
args.graph, args.patience,
result_root=log_root_path,
run_best_checkpoint_prefix=run_best_checkpoint_prefix,
overall_best_checkpoint_prefix=overall_best_checkpoint_prefix,
eval=args.eval
)
# 开始训练
for epoch in range(args.epochs):
model.train()
for batch_i, (prior_G, batch_G, cumul_G, batch_times) in enumerate(train_data_loader):
# 计算损失
batch_train_loss_dict = compute_loss(
model, args.optimize, batch_G, static_entity_embeds,
init_dynamic_entity_embeds, init_dynamic_relation_embeds, args
)
# 反向传播和优化
......
# 验证模型
val_dict, val_dynamic_entity_emb, val_dynamic_relation_emb, loss_weights = evaluate(
......
# 早停判断
score = val_dict['MRR']
pack_args = (
......
if stopper.step(score, pack_checkpoint(*pack_args)):
logger.info(f"[Epoch-{epoch}] Early stop!")
break
# 测试模型
run_best_checkpoint = stopper.load_checkpoint()
model, edge_optimizer, time_optimizer, val_static_entity_emb, \
init_dynamic_entity_embeds, val_dynamic_entity_emb, \
init_dynamic_relation_embeds, val_dynamic_relation_emb, \
node_latest_event_time_post_valid, loss_weights, _ = \
unpack_checkpoint(run_best_checkpoint, model, edge_optimizer, time_optimizer)
evaluate(
model, test_data_loader, G, val_static_entity_emb, val_dynamic_entity_emb,
val_dynamic_relation_emb, G.num_relations, args,
"Test", args.full_link_pred_test, args.time_pred_eval, loss_weights=loss_weights
)
通过分析 FinDKG,我们可以动态跟踪全球金融网络。例如,我们可以观察到 COVID-19 实体的中心性指标随着时间的变化,捕捉到疫情在不同时间点对全球经济的影响。
图4:FinDKG上模型的性能比较。
图5:2018年1月至2022年12月期间Covid-19实体中心性均值的演变。
# 计算节点中心性指标
def compute_centrality(graph):
......
# 其他中心性指标
return degree_centrality, betweenness_centrality
# 绘制中心性指标随时间的变化
def plot_centrality_over_time(centrality_data):
# 绘图逻辑省略
plt.show()
我们利用 KGTransformer 对 FinDKG 进行训练,预测与人工智能(AI)相关的公司。通过构建一个 AI 主题的投资组合,我们发现该投资策略在评估期间的表现优于市场基准和其他 AI 主题的 ETF。
图6:2022年6月至2023年12月,人工智能主题的只做多投资组合和市场指数的累计回报。
# 根据模型预测构建投资组合
def construct_portfolio(model, fin_dkg, theme='AI'):
predicted_entities = model.predict_entities(theme)
portfolio = allocate_weights(predicted_entities)
return portfolio
# 模拟投资组合表现
......
# 绘制投资组合表现
def plot_portfolio_performance(returns):
plt.plot(returns)
plt.xlabel('Time')
plt.ylabel('Returns')
plt.title('Portfolio Performance')
plt.show()
表5:市场、ai主题ETF和FinDKG投资组合的整体表现。在指标中表现最好的两个投资组合以粗体突出显示,最好的投资组合进一步强调。评估期为2022年6月30日至2023年12月29日。
本文提出了一种利用大型语言模型生成动态知识图谱的新方法,并开发了一个用于金融领域的开源数据集 FinDKG。我们还提出了 KGTransformer 模型,展示了其在链接预测任务上的优越性能。我们的研究为在金融市场中利用 DKGs 和 LLMs 提供了新的思路和工具。
文章来自于“LLMQuant”,作者“量化前沿”。
【开源免费】XTuner 是一个高效、灵活、全能的轻量化大模型微调工具库。它帮助开发者提供一个简单易用的平台,可以对大语言模型(LLM)和多模态图文模型(VLM)进行预训练和轻量级微调。XTuner 支持多种微调算法,如 QLoRA、LoRA 和全量参数微调。
项目地址:https://github.com/InternLM/xtuner
【开源免费】LangGPT 是一个通过结构化和模板化的方法,编写高质量的AI提示词的开源项目。它可以让任何非专业的用户轻松创建高水平的提示词,进而高质量的帮助用户通过AI解决问题。
项目地址:https://github.com/langgptai/LangGPT/blob/main/README_zh.md
在线使用:https://kimi.moonshot.cn/kimiplus/conpg00t7lagbbsfqkq0